Repository navigation
Commit af1b3f8
docs(qa): 18.0 sweep anchor round 2 — expression-editors' RLS clauses to the engine's error tier, a consumed-changeset citation, and §3 accuracy corrections in five areas (#24632)
Refs #24579
Clause-②: no
Part of #24579: the wave anchor's second dispatch (round 1, #24622,
landed §1's five rows). This PR lands three parts: (a) the §1 row round
2 added, (b) the rider from the #24622 review, and (c) §3's
checklist-accuracy findings for platform-core, access-security,
attachments-storage, identity-auth and approvals. The card stays open
for §2, §4, the other areas' §3 bullets and round 2's other additions.
The diff edits checklist content only
(`docs/qa/platform-checklist/areas/`, seven files). No product code,
test or pin changes. Every finding below was re-derived from source at
the base `8fbbd5082f` (and, for console claims, objectui at the console
pin `4016370a`) before the item was edited. A finding that did not hold
is in the left-alone list with the reading that refuted it. Each edited
item takes one `revision` bump and one `history` row that names its run
record(s) and carries this PR as `ref`. Several findings on one item
make one revision.
## (a) §1 — the round-2 row
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `studio-authoring.expression-editors` | `acceptance[2].clause`,
`acceptance[2].verify`, `acceptance[4].clause`,
`acceptance[4].evidence`, `acceptance[4].verify`,
`fixtures.knownGaps[3]` (added), `steps[0]`, `steps[4]`, `variants[2]` |
3 → 4 | #24604, #24571 |
acceptance[2] and acceptance[4] required a non-pushdownable USING read
filter to be an advisory WARNING with Save enabled and fail-open
framing. The engine refuses that predicate at ERROR tier:
`packages/lint/src/validate-rls-predicate-enforceability.ts` emits
`rls-predicate-unenforceable` with severity `error` (ADR-0056 D4), the
rule `os build` and publish run, and the runtime fails CLOSED (the
dropped policy grants no access). negative[0] already fails any editor
verdict that differs from the engine, so the item contradicted itself
(#24604 scored acceptance[4] "pass (as written)" beside a negative[0]
FAIL). Both clauses now expect the error tier. Four more fields ride the
same re-point so the item stays consistent:
- steps[4] and variants[2] expect the error tier.
- steps[0] names the build/publish gate as the RLS probes' engine truth,
because `validate_expression` has no RLS site.
- acceptance[4] names the Studio package door's autosave-held status
beside the environment door's disabled Save (#24604: the package door
has no Save button).
- A new knownGap records that at the console pin the editor still warns
(objectui `celAuthoring.ts` `lintCelPredicate`). The clauses therefore
FAIL until objectstack-ai/objectui#13061 lands.
## (b) the #24622 rider
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `cli.organization-ownership-ceremony` | `source`: the path entry
`.changeset/pre/15212-180-guards-fresh-single-only.md` removed,
`15212-180-guards-fresh-single-only` appended to the prose entry "v18
changesets (.changeset/pre/, consumed into 18.0.0-next.*): …" | 2
(unchanged — no history row) | the #24622 review |
The path entry dangles once 18.0.0 is versioned, because the version
render consumes `.changeset/pre/*.md`. Ledger rule, measured:
`check:platform-checklist` requires only `revision` equal to the last
`history` row's revision, and the README bumps "on any semantic edit",
meaning one that would let an old run result read as valid against
changed clauses. A citation fold changes no clause, step or fixture a
run judges, and this item already took a revision today for #24622, so
no revision and no history row. Counter-reading, for the record: the
ledger has bumped for a source-only addition before
(`platform-core.boot-health`, its "source-ref addition" row). If the
seat reads the rule that way, the fix is a revision-3 row naming this
PR. The item's `fixtures.knownGaps[0]` prose also names
`.changeset/pre/15212-180-guards-fresh-single-only.md` in a sentence,
and that mention was left as it is: the ruling names the source entry
only.
## (c) §3 — five areas
Run records: platform-core #24557 (with round 2's #24603, whose accuracy
section is empty); access-security #24559 (with #24601);
attachments-storage #24560; identity-auth #24538; approvals #24542. Each
area stays at or below 15 edited items: 12, 13, 2, 8 and 6.
### platform-core
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `platform-core.builtin-apps-nav-render` | `steps[2]`, `steps[5]` | 6 →
7 | #24557 |
| `platform-core.package-lifecycle-enable-disable` | `steps[0]` | 1 → 2
| #24557, #24571 |
| `platform-core.notification-center` | `acceptance[0].verify`,
`acceptance[5].clause`, `acceptance[5].verify`, `steps[0]`, `steps[7]` |
2 → 3 | #24557 |
| `platform-core.docs-audience-gate` | `acceptance[3].clause`,
`acceptance[3].verify`, `fixtures.knownGaps[0]` | 1 → 2 | #24557 |
| `platform-core.manifest-install-contract` | `fixtures.knownGaps[3]`,
`negative[2]` | 3 → 4 | #24557 |
| `platform-core.activation-ledger-row-contract` |
`acceptance[4].clause`, `acceptance[4].verify`, `fixtures.knownGaps[0]`,
`fixtures.requires[1]`, `negative[5]`, `steps[0]`, `steps[2]`, `title`,
`variants[4]` (added) | 4 → 5 | #24557, #24601 |
| `platform-core.marketplace-install-local-lifecycle` |
`fixtures.requires[0]`, `personas[1]`, `steps[3]` | 4 → 5 | #24557 |
| `platform-core.runtime-config-boot-read` | `steps[1]` | 1 → 2 | #24557
|
| `platform-core.url-overlay-contract` | `acceptance[4].clause`,
`acceptance[4].evidence`, `acceptance[4].verify`, `automated.ref`,
`steps[5]` | 1 → 2 | #24557 |
| `platform-core.home-admin-cluster-links` | `acceptance[3].clause`,
`acceptance[3].verify` | 3 → 4 | #24557 |
| `platform-core.v18-boot-refusals` | `acceptance[1].clause`,
`acceptance[1].verify`, `acceptance[3].verify`, `steps[1]` | 2 → 3 |
#24557 |
| `platform-core.serve-composition-v18` | `fixtures.requires[1]` | 1 → 2
| #24557 |
### access-security
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `access-security.record-access-explain` | `steps[1]` | 2 → 3 | #24559
|
| `access-security.fls-mask-and-strip` | `steps[5]` | 4 → 5 | #24559 |
| `access-security.scope-depth-asymmetry` | `automated.ref`, `steps[0]`
| 2 → 3 | #24559, #24598 |
| `access-security.sharing-rules-widen` | `acceptance[4].clause`,
`acceptance[4].evidence`, `acceptance[4].verify`, `steps[6]` | 2 → 3 |
#24559, #24601 |
| `access-security.record-share-grant-revoke` | `acceptance[6].clause`,
`acceptance[6].evidence`, `acceptance[6].verify` | 5 → 6 | #24559 |
| `access-security.audit-log-browser` | `acceptance[5].verify`,
`steps[7]` | 6 → 7 | #24559 |
| `access-security.permission-matrix-edit-loop` | `steps[0]`,
`steps[1]`, `steps[3]` | 3 → 4 | #24559 |
| `access-security.capability-declaration-lifecycle` |
`acceptance[1].verify`, `steps[7]` | 4 → 5 | #24559 |
| `access-security.anonymous-floor-v18-doors` | `fixtures.knownGaps[1]`
| 1 → 2 | #24559 |
| `access-security.meta-authoring-trail-and-audience-gates` |
`acceptance[2].clause`, `acceptance[2].verify`, `steps[1]` | 1 → 2 |
#24559 |
| `access-security.grant-table-write-contract` | `acceptance[2].clause`,
`acceptance[2].verify` | 1 → 2 | #24559 |
| `access-security.deployment-tables-platform-only` | `automated.ref`,
`steps[2]` | 1 → 2 | #24559 |
| `access-security.share-link-combined-gates` | `automated.ref` | 2 → 3
| #24559 (round 1 note) |
### attachments-storage
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `attachments-storage.orphan-tombstone-reap` | `acceptance[0].verify`,
`automated.ref` | 1 → 2 | #24560 |
| `attachments-storage.chunked-upload-integrity` |
`acceptance[0].clause`, `fixtures.knownGaps` (new, one entry) | 2 → 3 |
#24560 (round 1 note) |
Area-level edit, no item: the `qa-media-constraints` recipe's
`provenance` said "not yet proven by a live run". QA run #24560 replayed
it cleanly and scored
`attachments-storage.field-accept-maxsize-server-enforced` on it, and
the provenance now says so. Recipes carry no `revision` or `history` of
their own (the validator's #10885 note), so this edit has no history
row.
### identity-auth
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `identity-auth.invitation-scope-gates` | `automated.ref`,
`fixtures.requires[0]`, `fixtures.requires[1]` | 4 → 5 | #24538 |
| `identity-auth.api-key-ui-lifecycle` | `source[2]` | 3 → 4 | #24538 |
| `identity-auth.self-service-profile-password` |
`fixtures.knownGaps[0]`, `fixtures.requires[2]`, `steps[7]` | 1 → 2 |
#24538 |
| `identity-auth.org-membership-team-management` |
`acceptance[3].clause`, `steps[5]` | 4 → 5 | #24538 |
| `identity-auth.self-service-password-reset` | `acceptance[0].oracle` |
2 → 3 | #24538 |
| `identity-auth.self-signup-gate` | `steps[0]` | 4 → 5 | #24538 |
| `identity-auth.auth-gate-held-session-raw-host-families` |
`fixtures.requires[1]` | 1 → 2 | #24538 |
| `identity-auth.default-organization-boot-invariant` |
`acceptance[1].verify`, `steps[0]` | 1 → 2 | #24538 |
### approvals
| item | fields edited | revision | run record |
|:--|:--|:--|:--|
| `approvals.per-group-signoff` | `acceptance[3].verify` | 7 → 8 |
#24542 |
| `approvals.quorum-m-of-n` | `fixtures.requires[1]` | 4 → 5 | #24542 |
| `approvals.decision-action-matrix` | `acceptance[1].verify`,
`steps[7]` | 5 → 6 | #24542 |
| `approvals.account-app-entry` | `acceptance[6].verify`,
`fixtures.requires[2]` | 2 → 3 | #24542 |
| `approvals.approver-resolution-matrix` | `acceptance[3].verify`,
`acceptance[4].verify`, `acceptance[5].verify`, `steps[6]`, `steps[7]` |
4 → 5 | #24542 |
| `approvals.request-page-reply-and-reader-visibility` |
`automated.ref`, `steps[1]` | 1 → 2 | #24542 |
Pin-coverage additions (PM hypothesis 2: added only where the file
exists, reports at least 1 test under its package's vitest at the base,
and asserts a clause the item states). Each was run singly under the
shared verify lock after building the dependency closure (`turbo run
build`, 34 tasks, exit 0):
| added to `automated.ref` | item | vitest |
|:--|:--|:--|
| `packages/runtime/src/domains/share-links-messages-audience.test.ts` |
access-security.share-link-combined-gates (acceptance[3]) | 1 file, 85
passed |
|
`packages/services/service-automation/src/sys-flow-dispatch.object.test.ts`
| access-security.deployment-tables-platform-only (acceptance[0]) | 1
file, 4 passed |
|
`packages/services/service-realtime/src/objects/sys-presence.object.test.ts`
| access-security.deployment-tables-platform-only (acceptance[0]) | 1
file, 12 passed |
| `packages/services/service-storage/src/attachment-lifecycle.test.ts` |
attachments-storage.orphan-tombstone-reap (acceptance[0]) | 1 file, 47
passed |
|
`packages/plugins/plugin-approvals/src/request-read-gate.integration.test.ts`
| approvals.request-page-reply-and-reader-visibility (acceptance[2]) | 1
file, 16 passed |
`attachments-storage.chunked-upload-integrity` gets no pin: no test
drives a chunked door after an organization switch. The guard's only
door-level pin is the presigned commit door's in
`error-envelope.conformance.test.ts`. So acceptance[0] stops claiming
the org-switch guard, and a knownGap records the unpinned leg.
## Findings left alone, each with the reading that refuted or excluded
it
- `platform-core.boot-health`, round 2's "the check-console-injection
replay line still says 'not the published one'": no area file carries a
check-console-injection line. At the base, a search of all 16 area files
for `check-console-injection`, `console-injection` and `published one`
finds zero matches. The sentence is the output of
`scripts/check-console-injection.mjs` (its success line), which is
product text and outside this checklist-only ruling.
- `platform-core.settings-hub-roundtrip` (`value_domain`; no user-scoped
namespace): excluded, because open PR #24590 holds the item.
- `platform-core.settings-organization-isolation-and-platform-rung`,
plus the walled legs of
`access-security.walled-environment-metadata-operator-only`,
`activation-write-operator-gate`, `grant-table-write-contract`
acceptance[4] and `parent-and-organization-write-guards`: §2 (walled
posture), so not this round. The record's "the minimal object body must
declare sharingModel" note sits on
`walled-environment-metadata-operator-only` steps[0], a walled-boot
step, and is left for that item's §2 revision.
- `platform-core.metadata-authoring-roundtrip` (the objectui
`studio-record-page` / `studio-object-designer` specs are red at their
own pin): §2's "objectui live e2e is not green at its pin" theme.
- `platform-core.docs-audience-gate` acceptance[2] (the
unknown-audience-shape branch is unreachable live and has no test),
`access-security.rls-both-sides` acceptance[5],
`access-security.crud-permission-matrix` acceptance[5], the
marketplace-browse egress gap,
`access-security.parent-and-organization-write-guards` (no
controlled_by_parent fixture),
`access-security.platform-owner-email-anchor` (no HTTP verified-email
path), every identity-auth "Fixture gaps" row, and every approvals
"Fixture gaps" row (including `request-page-reply-and-reader-visibility`
acceptance[2]/[3] being unreachable on stock): §4, not this round.
- `attachments-storage.chunked-upload-integrity` acceptance[1] (chunk
numbering base): already corrected on main by #24622 (revision 2 numbers
chunks from 0 and expects `missingChunks` [1]). Its second-organization
fixture is §2.
- `access-security.share-link-combined-gates`, "showcase has no
ai_conversations object": already in acceptance[3] since #24622 ("the
stock showcase has no ai_conversations object, so 400 UNSUPPORTED is the
open answer there"). The item is otherwise one of the round-1 items
excluded by the ruling.
- `access-security.owd-save-gate` negative[0] "skipped": a run note
(that runner booted before the console build landed), not a statement
the item gets wrong.
- `access-security.capability-declaration-lifecycle`, "DELETE
/api/v1/meta/capability/NAME is a 200 no-op": no clause or step asserts
the DELETE door, so nothing in the item is inaccurate. The
200-that-deletes-nothing answer is a product observation and is not
encoded here (see Acceptance notes).
- `attachments-storage.inline-grid-receipt-cells` (objectui-only pin
scored by hand): a run-method note under RUNNER's objectui-pin protocol,
not an inaccuracy.
- identity-auth, accurate as written: `auth-method-matrix` (discovery
also answered under /api/v1/auth, which the record calls harmless; the
item requires only the root mount) and `two-factor-enrollment-reveal`
(the record calls the anonymous 400 "consistent with the clause").
`admin-lifecycle-operations`'s impersonation-banner note is a UX
observation outside every clause.
- identity-auth, suggestions rather than errors:
`two-factor-verify-to-activate` / `-backup-codes` / `-disable-lifecycle`
("worth naming" a SQLite-file rig as an alternative to the in-process
read, which still works). `auth-gate-held-session-raw-host-families`
boots with `pnpm dev -- --fresh`, AGENTS.md's documented backend-only
boot.
- approvals, suggestions rather than errors: `inbox-metadata-actions` (a
simpler persona path; the reassign path the item names works).
`decision-only-via-service` steps[6] (the run drove the trigger API
instead of the row action; the step is accurate).
`request-page-reply-and-reader-visibility`'s boot line (accurate).
- `approvals.email-action-token-door` (all three of its rows): excluded,
because it turns on #24620.
- `approvals.act-door-and-admin-rescue-slate` fixtures.requires ("no
mail harness needed — the raw links sit in
sys_notification.payload.actions after a remind"): refuted since #24620
landed (`65a8eeb7d4`, merged into this branch). A reminder's
notification payload carries no one-tap action token any more, so that
alternative no longer exists. It belongs with email-action-token-door's
#24620 follow-up.
- Round 2 part 1's Tier 1 `automated.ref` quality list:
`access-security.scope-depth-asymmetry` is taken above. The other named
items (`flow-node-type-matrix`, `trigger-type-matrix`, `crud-roundtrip`,
`connector-declarative-boot`, the `hook-wrappers` / `hook-binder` refs)
are in other areas and not this round's.
## PM hypotheses, measured
1. **Stale findings because main moved — partly confirmed.** Diffed
between run subject `5b14b7f3` and base `8fbbd5082f`, the cited sources
changed in three files. `packages/objectql/src/registry.ts` (#24526) and
`packages/plugins/plugin-auth/src/auth-manager.ts` (#24587) changed, but
not in the cited symbols (NamespaceConflictError, the org-MFA cache).
`packages/plugins/plugin-approvals/src/approval-service.ts` changed with
#24527 and then #24620 (merged here); neither touches `rowFromRequest`
or `comment`. Main's movement staled one finding (act-door, by #24620).
Two more were already handled on main (chunked numbering and share-link
ai_conversations, both by #24622). One was wrong at the base itself
(boot-health).
2. **"automated.ref omits X" is a pin-coverage claim — confirmed.** Five
pins were added after measurement (table above). One claim had no pin to
add (chunked-upload-integrity), and the item records the gap instead.
3. **Symbol-anchor count must not drop — confirmed.**
`check:platform-checklist` read 860/870 resolved at the base and 872/882
at head: 12 anchors added, none lost, the 10 on the named #16898
residual unchanged, 18 file floors held. No re-pointed anchor was
refused.
## Gates
Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` from the merge-base (13 families), run at
head `0b5ec6bc9e`, each exit code captured before any pipe:
| command | exit |
|:--|:--|
| `node scripts/check-ci-filter-parity.mjs` | 0 |
| `node scripts/check-closing-keyword-parity.mjs` | 0 |
| `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 |
| `node scripts/check-comment-mask-corpus.mjs` | 0 |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
0 |
| `pnpm check:cross-package-test-inputs` | 0 |
| `pnpm check:doc-authoring` | 0 |
| `pnpm check:driver-memory-census` | 0 |
| `pnpm check:gitlink-declared` | 0 |
| `pnpm check:nul-bytes` | 0 |
| `pnpm check:platform-checklist` | 0 |
| `pnpm check:refd-timer-probe` | 0 |
| `pnpm check:watch-hint-literal` | 0 |
`--ran` reconciliation: "13 derived famil(ies) accounted for — 13 run, 0
NOT-MEASURED (a DERIVED zero — all 13 recorded an exit code and none of
them is 3)". `check:platform-checklist` runs in no per-PR CI, so its
local reading is the evidence: "check-platform-checklist: OK — 16 areas,
327 items (322 active, 1 planned) … symbol anchors: 872/882 resolved …
10 on the named #16898 residual, 18 file floors held". The history `ref`
of the 42 revised items is a placeholder until this PR has a number. The
fill commit after creation changes exactly those 42 strings, and the
gates are re-run on that head (reported on the card). No exported symbol
was renamed or removed, so `check-platform-checklist.mjs --changed-from`
has nothing to judge. Changeset: none. No published package's `files[]`
lists `docs/qa`, so `skip-changeset`.
## Acceptance notes
- `access-security.capability-declaration-lifecycle`: QA run #24559
measured `DELETE /api/v1/meta/capability/NAME` answering 200 while
removing nothing, on a code-only type whose PUT answers 403
NOT_CREATABLE. No clause covers it, and it is noted here for the seat
rather than filed from a checklist PR.
- `platform-core.boot-health`: the "not the published one" wording lives
in `scripts/check-console-injection.mjs`'s success line. Whether it is
stale is a product-text question for the seat that owns that script.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 4ff18d3 commit af1b3f8
7 files changed
Lines changed: 422 additions & 166 deletions
File tree
- docs/qa/platform-checklist/areas
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
138 | | - | |
| 138 | + | |
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
| |||
642 | 642 | | |
643 | 643 | | |
644 | 644 | | |
645 | | - | |
| 645 | + | |
646 | 646 | | |
647 | 647 | | |
648 | 648 | | |
| |||
663 | 663 | | |
664 | 664 | | |
665 | 665 | | |
666 | | - | |
| 666 | + | |
667 | 667 | | |
668 | 668 | | |
669 | 669 | | |
| |||
697 | 697 | | |
698 | 698 | | |
699 | 699 | | |
700 | | - | |
| 700 | + | |
701 | 701 | | |
702 | 702 | | |
703 | 703 | | |
704 | 704 | | |
705 | 705 | | |
706 | 706 | | |
707 | | - | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
708 | 714 | | |
709 | 715 | | |
710 | 716 | | |
| |||
1080 | 1086 | | |
1081 | 1087 | | |
1082 | 1088 | | |
1083 | | - | |
| 1089 | + | |
1084 | 1090 | | |
1085 | 1091 | | |
1086 | 1092 | | |
| |||
1090 | 1096 | | |
1091 | 1097 | | |
1092 | 1098 | | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
1093 | 1102 | | |
1094 | 1103 | | |
1095 | 1104 | | |
| |||
1100 | 1109 | | |
1101 | 1110 | | |
1102 | 1111 | | |
1103 | | - | |
| 1112 | + | |
1104 | 1113 | | |
1105 | 1114 | | |
1106 | 1115 | | |
| |||
1144 | 1153 | | |
1145 | 1154 | | |
1146 | 1155 | | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
1147 | 1162 | | |
1148 | 1163 | | |
1149 | 1164 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1897 | 1897 | | |
1898 | 1898 | | |
1899 | 1899 | | |
1900 | | - | |
1901 | 1900 | | |
1902 | 1901 | | |
1903 | 1902 | | |
1904 | | - | |
| 1903 | + | |
1905 | 1904 | | |
1906 | 1905 | | |
1907 | 1906 | | |
| |||
0 commit comments