Skip to content

Commit acff643

Browse files
docs(qa): 18.0 sweep round 7 — integration-system checklist-accuracy findings and four carried notes (#24717)
Refs #24579 Clause-②: no Round 7 of the 18.0 release sweep's wave anchor (#24579), one PR in two parts. Part (a) takes `integration-system`, the last area §3 had not worked, from its run records #24575 (round 1, `5b14b7f3`) and #24615 (round 2, `ba4afcc2`), plus the rows #24556 and #24558 left for this file. Part (b) takes four notes carried from rounds 5 and 6. These are checklist and runner-doc defects only: no product code, test or pin changes. Every finding was re-derived from `origin/main`'s source before it was edited. Each edited item takes one `revision` bump and one `history` row naming its run record(s). The rows' `ref` is a placeholder in this head; a fill commit replaces exactly those 16 strings with this PR's number. ## Part (a) — `docs/qa/platform-checklist/areas/integration-system.json` 13 items (cap 20). | item | fields edited | revision | run record | |:--|:--|:--|:--| | `datasource-credential-refusal-matrix` | `fixtures.knownGaps[2]`, `fixtures.knownGaps[4]` (new), `steps[0]`, `steps[8]`, `acceptance[6].clause`, `source[2]` | 4 → 5 | #24575, #24556 | | `datasource-admin-lifecycle` | `steps[2]`, `steps[3]`, `steps[4]`, `steps[5]`, `steps[8]`, `acceptance[0].clause`, `acceptance[2].clause`, `acceptance[4].clause`, `acceptance[4].verify` | 3 → 4 | #24615 | | `external-schema-introspection` | `fixtures.knownGaps[0]` | 3 → 4 | #24615 | | `external-schema-browser-ui` | `steps[1]`, `steps[7]`, `acceptance[0].clause` / `.verify` / `.evidence`, `acceptance[3].verify`, `fixtures.knownGaps[3]`, `fixtures.knownGaps[4]` (new) | 3 → 4 | #24615 | | `connector-degraded-recovery` | `fixtures.requires[0]`, `steps[4]`, `steps[6]`, `acceptance[3].verify` | 2 → 3 | #24575 | | `notify-inbox-delivery` | `fixtures.requires[0]`, `fixtures.knownGaps[2]`, `steps[5]`, `acceptance[3].verify`, `acceptance[4].verify` | 4 → 5 | #24575, #24615 | | `job-scheduled-run` | `fixtures.requires[1]`, `steps[4]`, `steps[6]`, `acceptance[3].verify` / `.evidence` | 4 → 5 | #24575 | | `connector-declarative-boot` | `automated.ref` | 2 → 3 | #24598 (round 2 part 1), #24575 | | `inbound-mailbox-association` | `fixtures.requires[1]`, `fixtures.knownGaps[0]` | 1 → 2 | #24558 | | `notification-org-and-redeliver-eligibility` | `fixtures.requires[2]`, `steps[2]`, `steps[3]` | 1 → 2 | #24558 | | `external-datasource-federated-read` | `fixtures.requires[0]`, `steps[4]`, `acceptance[2].oracle` / `.evidence` | 3 → 4 | #24575 | | `external-schema-drift-gate` | `fixtures.knownGaps[0]`, `steps[0]` | 2 → 3 | #24615 | | `connector-auth-kind-application` | `steps[1]`, `fixtures.knownGaps[0]`, `source[5]` | 1 → 2 | #24615 | What each one says now, and the source it was checked against: - **Postgres recipe (§3's bullet).** The credential matrix's knownGap said no recipe is proven and the QA container has no database. The container has PostgreSQL 16 at `/usr/lib/postgresql/16/bin` (re-read in this container), and #24575's recipe scored acceptance[1] and [6] pass. The gap now carries the recipe. - **`mongodb`, not `mongo`.** `DRIVER_CATALOG` serves `mongodb` (`driver-catalog.ts`), and an authored `mongo` is refused by name since 18 (`datasource.zod.ts`). Fixed in both datasource items. - **sqlite `filename`.** `SqliteConfigSchema` declares `filename`; `file` is an alias that authoring refuses with a rename hint. - **`POST /test` order (hypothesis 2).** The item relied on the order: `steps[3]` and `acceptance[2].clause` both stated it. `server.post(root + '/test')` is registered after every `:name` route in `admin-routes.ts`. "test" stays uncaptured only because no POST route takes a bare `:name`. So the ledger text is corrected. The code comment is reported in the acceptance notes below and is not edited. - **`?schema=` on Postgres (hypothesis 1).** #24619 row (c) is now #24664, which is open. The knownGap's claim that a Postgres fixture would make narrowing live-scoreable is false: `introspectSchema` lists `current_schemas(false)` tables with bare names. It is corrected. `acceptance[1]` states the #7955 contract and stays as written, because the defect makes it false live, not the clause. - **Browser UI (round 2's §3 additions).** - The objectui pin is `12dc7b47c340`, and #24615 ran at `4016370a`. Both were read. - `DatasourceResourcePage` rows never open the item, so `steps[1]` names the engine edit route. - The save-first guidance is unreachable: `CREATE_MODE_CANVAS_TYPES` is object / report / dataset / doc. `acceptance[0]` now scores the observable half (no name-less call) and records the guidance half as not-run. - The quoted refusal belonged to `POST /meta/_migrate-stored`. The item save door answers `metaWriteCapabilityVerdict`'s "Saving a metadata item requires…" with 403 `FORBIDDEN`. - A repeated import answers 201 and overwrites: `importObject` makes no existence check. This is recorded as a knownGap that no clause scores. - **Reload backoff (rounds 3 and 4).** `degradeConnectorInstance` restarts attempts at 1 only on a signature change. A `metadata:reloaded` reconcile retries at once and keeps counting. `steps[6]` now names a restart-free reload: `os dev` restarts on a source save, because its `--restart` defaults to true. - **Messaging 501 recipe.** `resolveServedCapabilities` skips the always-on slate under `--preset minimal`. The knownGap carries #24615's scratch app-todo recipe. - **Timeout probe.** `runWithPolicy` retries timeouts. A second probe with a `retryPolicy` is what can show it. - **`connector-declarative-boot` ref.** It is narrowed clause by clause against the two cases of `showcase-declarative-mcp.dogfood.test.ts`, in the shape round 2 used for `scope-depth-asymmetry`. - **#24558's rows.** - The showcase composes `MailboxServicePlugin`, because `requires` lists `mailbox`. What is missing is the IMAP sync composition, a `mailAssociation` field and an IMAP double. - An inactive webhook never gets a delivery: the redeliver guard reads the dispatcher's `active === true` predicate. The item carries the active-then-switch-off recipe. It warns off a pending row, which answers `DELIVERY_NOT_ELIGIBLE` from `assertHttpRedeliverable` for another reason. ## Part (b) — carried notes | item or section | fields edited | revision | source | |:--|:--|:--|:--| | `platform-core.metadata-authoring-roundtrip` | `automated.stale.observedIn` (`#7695` → `#24598`), `.partial`, `.why`, `.ownedBy` | 3 → 4 | Tier 1 run #24598; round 6's note | | `access-security.activation-write-operator-gate` | `acceptance[3].clause`, `acceptance[4].clause`, `acceptance[4].verify`, `acceptance[5].verify`, `negative[3]`, `source[0]` | 4 → 5 | round 5's note | | `access-security.platform-owner-email-anchor` | `steps[0]` | 3 → 4 | round 5's note | | `RUNNER.md` · "Environment facts the runner should not re-derive", the objectui-only `automated.ref` entry | lines 434–439 rewritten (the paragraph runs 434–449) | — | round 6's note | - **(b)1.** `studio-record-page.spec.ts` has the same blob at `4016370af3c9` and `12dc7b47c340` (read in objectui), and #24598 ran it 0 passed / 1 failed. `ownedBy` names objectstack-ai/objectui#13104. The marker also said `studio-object-designer.spec.ts` was unaffected. #24598 ran its F1 and F4 red, so `partial` and `why` now say so. - **(b)2.** Each comma-range citation, re-pointed. The cited lines now hold other code. - `acceptance[3].clause` `,141-147` → `activation-gate.ts#refuseUngrantedActivationWrite`, plus the header's "What it enforces" `single` bullet (prose). - `acceptance[4].verify` `,155-163` → `#refuseUngrantedActivationWrite` (the sentence) and `#FLOW_ACTIVATION_SUBJECT` / `#ACTION_ACTIVATION_SUBJECT` (the remedies). - `acceptance[5].verify` `,190` → `#refuseUngrantedActivationWrite` and `#refuseUngrantedActivationAuthoring` (both `isSystem` arms). - `negative[3]` `,141-147` → `#readEffectiveTenancyPosture`, plus the header's "Fail-open on an ABSENT posture is deliberate" section (prose). - `source[0]` (`#posture`, which resolved only to a local `const posture`, plus five line ranges) → the four symbols above, plus the same header section in prose. - **(b)3.** `serve.ts#walledPostureRefusal` refuses a walled posture before any config is read, and it reads no `OS_PLATFORM_OWNER_EMAIL`. The walled-theme text itself (RUNNER.md's entry and the seven knownGaps) is untouched, waiting for #24667. - **(b)4: my call is to reword, not to count.** The merged tree is `abb111cb4c`: this branch plus `origin/main` `73d4cc7391`, which includes PR #24697. On it, the rule "an `automated.ref` names an objectui path and no path in this checkout" counts **23** objectui-only items, plus 7 mixed. On the pre-#24697 base `d1173825b7` the same rule counts 27. Round 6 counted 28 before and 24 after by its own rule. The old sentence's "23" therefore matches this tree only by coincidence: it was four short a commit earlier, and a second careful reader counts 24 here. The number moves with every pin edit, and no gate reads it. The entry now states the rule, and keeps every other sentence in it. **Bounded in-place fixes** (same defect class, mechanical, same file, same gate): - `activation-write-operator-gate` `acceptance[4].clause`: it said flows recommend the clone path and that the platform_admin POSITION admits. Both remedies name the operator and neither names a clone: `automation-activation-posture-gate.test.ts` asserts `ask your platform operator` with no `clone`, and the action pin asserts no `clone`. The gate reads the PLATFORM_ADMIN posture rung (`ec?.posture === 'PLATFORM_ADMIN'`, #15981). The walled lead of the clause is unchanged. - `external-schema-browser-ui` `acceptance[3].verify` cited `ExternalDatasourcePanel.tsx,108-123`, and `connector-auth-kind-application` `fixtures.knownGaps[0]` and `source[5]` cited `index.ts,103,142` / `,66,103,142`. These are the (b)2 rot class, re-pointed to a symbol or to prose for objectui. - `notify-inbox-delivery` `fixtures.requires[0]` spelled recipients `['{record.assignee}']`. The flow declares one CEL value envelope. ## Findings left alone | finding | refuting reading | |:--|:--| | `notify-inbox-delivery`: the `notify` assignee must be a user id (§3; #24575) | Does not hold. `RecipientResolver.resolveOne` sends an email-shaped recipient to `resolveEmail`, which looks up `sys_user` by email under the fan-out system context and returns its id. It keeps the email verbatim only when nothing matches (`recipient-resolver.ts`). A user id works, but it is not required. | | `external-schema-introspection` `acceptance[1]` and the title's "?schema= honoured" | Product-defect territory (#24664, open). The clause states the #7955 contract. | | credential matrix: `turso` is absent from `GET /drivers` though `POST` accepts it, and the turso edit form shows only Label | Deliberate curation (`driver-catalog.ts` header: turso needs an optional package, which a dropdown cannot arrange). No item text says otherwise. | | credential matrix: the metadata door serves the `credentialsRef` handle and the admin door only `hasSecret`, "say whether intended" | A question for the contract, not an inaccuracy. `acceptance[2]` judges the two shapes consistent, and #24575 scored it pass. The new `knownGaps[4]` describes both doors. | | credential matrix: `schemaMode: "external"` on POST needs an `external` block | No step or clause of this item authors `schemaMode`, so the finding has no target text. | | credential matrix: the console route is `/_console/apps/com.objectstack.setup/metadata/datasource` | No step of this item names a console route. #24575 (federated-read) and #24615 (browser runner) both reached Setup at `/_console/apps/setup/metadata/datasource`, the spelling the edited steps use. | | credential matrix: a PATCH writing the literal mask is accepted and overwrites | Held for the maintainer on #24579 §7 (no declared contract). Recorded in `knownGaps[4]` as scored under no clause; no clause changed. | | `connector-auth-kind-application`: the oauth2 build refusal is a raw zod dump that names no connector | A UX nit. `acceptance[3]` claims a located message only for the inline-`authentication` refusal, which #24615 measured located. | | #24615: a scratch copy booted from `/tmp` prints "Console dist not found" | A RUNNER environment fact, harmless for API items. RUNNER.md is in scope this round only for the count sentence. | Excluded files, named only: `studio-authoring.draft-publish-lifecycle` has clause-free pins. The green `summary-rollup.spec.ts` on `records-forms.master-detail-atomic-save` and `grid-conditional-rules.spec.ts` on `records-forms.conditional-rules-grid` over-claim a clause. `records-forms.json`, `studio-authoring.json` (PR #24697) and `cli.json` (PR #24681) are untouched. ## Acceptance notes (not filed) - `packages/services/service-datasource/src/admin-routes.ts`: the comment above `POST /test` says it is "Registered before the `:name` routes". It is registered after all of them. There is no runtime effect, because no POST route takes a bare `:name`. Noted for the service-datasource lane. - The comma-range line-citation spelling survives in other area files. The line-citation limb refuses only `file:NNN` and a bare `:NNN`, so these do not trip it. Hits: - in scope for a later round: `access-security.record-view-read-audit`, `access-security.share-link-landing-page`, `ai.console-ai-surface-gating`, `attachments-storage.field-accept-maxsize-server-enforced`, three `automation` items, five `identity-auth` items, `platform-core.docs-portal-render`, `search.command-palette-navigation` (15 items); - in this round's excluded files: `cli`, `records-forms`, `studio-authoring`. Same carrier as (b)2: #24579. ## Gates On `abb111cb4c` (the branch merged with `origin/main` `73d4cc7391`), `node scripts/pm/dispatch-gates.mjs --commands` (no paths) derived 13 families. All 13 exited 0, with exit codes captured before any pipe: ```text node scripts/check-ci-filter-parity.mjs :: exit 0 node scripts/check-closing-keyword-parity.mjs :: exit 0 node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 node scripts/check-comment-mask-corpus.mjs :: exit 0 pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 pnpm check:cross-package-test-inputs :: exit 0 pnpm check:doc-authoring :: exit 0 pnpm check:driver-memory-census :: exit 0 pnpm check:gitlink-declared :: exit 0 pnpm check:nul-bytes :: exit 0 pnpm check:platform-checklist :: exit 0 pnpm check:refd-timer-probe :: exit 0 pnpm check:watch-hint-literal :: exit 0 ``` - `--ran`: "13 derived famil(ies) accounted for — 13 run, 0 NOT-MEASURED (a DERIVED zero …)". The first pass of `check:doc-formula-expressions` exited 3 because `@objectstack/lint` was unbuilt. It was built under the verify lock and re-run. - `check:platform-checklist` runs in no per-PR CI, so this reading is its evidence: "OK — 16 areas, 327 items". Symbol anchors went from **886/896** at base to **917/927** resolved, none refused (hypothesis 3); merging #24697 left both totals unchanged. The anchor census moved access-security 96 → 107, integration-system 63 → 83, and platform-core 96 → 96. - Editing discipline: a span-recording textual editor re-parsed each area file. It asserted that only the declared fields of the declared items changed, each with one `revision` bump and one `history` row, and that every other item and top-level key is deep-equal. - Changeset: `docs/qa/**` is in no package's `files[]`, so this PR publishes nothing and takes `skip-changeset`. --- _Generated by [Claude Code](https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 71a8b5e commit acff643

4 files changed

Lines changed: 175 additions & 83 deletions

File tree

‎docs/qa/platform-checklist/RUNNER.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,12 @@ contradicts it, and correct it here when it does.
431431
by name and exits **1**, where it used to exit **0** in silence — the entry point is
432432
`packages/cli/bin/run.js`.
433433

434-
- **23 items carry an `automated.ref` that lives ENTIRELY in the `objectui` repo — from
435-
this checkout they are neither runnable nor pin-evidenced.** Their refs name only
434+
- **Some items carry an `automated.ref` that lives ENTIRELY in the `objectui` repo — from
435+
this checkout they are neither runnable nor pin-evidenced.** No count is kept here: the
436+
set moves with every pin re-point and every `automated` edit, and the count this line
437+
used to carry went stale with nothing to notice it (wave anchor #24579). **Find them by
438+
the rule, not by a number:** an item is in the set when its `automated.ref` names an
439+
objectui path and no path that exists in this checkout. Their refs name only
436440
objectui paths (`e2e/live/*.spec.ts`, `e2e/import-console/*`, `e2e/import-harness/*`,
437441
and unit suites under `packages/plugin-grid`, `plugin-gantt`, `plugin-calendar`,
438442
`plugin-form`, `fields`, `core`, `app-shell`). This repository builds no console bundle

‎docs/qa/platform-checklist/areas/access-security.json‎

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,7 +2469,7 @@
24692469
"title": "Activation-ledger write authority (ADR-0126 §5): the manage_metadata tier refuses first on every posture, and the shared operator gate — INERT on stock `single` — demands the platform_admin POSITION in walled postures, at both the flow and action doors",
24702470
"since": "v17",
24712471
"status": "active",
2472-
"revision": 4,
2472+
"revision": 5,
24732473
"priority": "P1",
24742474
"surface": "api",
24752475
"personas": [
@@ -2522,29 +2522,29 @@
25222522
"evidence": "the ledger reads + the invalid-body trace"
25232523
},
25242524
{
2525-
"clause": "the §5 gate is INERT on `single`, not satisfied: a caller holding manage_metadata but NOT the platform_admin POSITION succeeds at BOTH doors, and each write lands one deployment-level ledger row — install-level and org-level are the same scope on one logical tenant (activation-gate.ts,141-147), and the ledger carries no tenant column to say otherwise",
2525+
"clause": "the §5 gate is INERT on `single`, not satisfied: a caller holding manage_metadata but NOT the platform_admin POSITION succeeds at BOTH doors, and each write lands one deployment-level ledger row — install-level and org-level are the same scope on one logical tenant (the `single` bullet of the header section 'What it enforces' in packages/runtime/src/domains/activation-gate.ts, where packages/runtime/src/domains/activation-gate.ts#refuseUngrantedActivationWrite returns before any check once postureEnforcesWall is false), and the ledger carries no tenant column to say otherwise",
25262526
"oracle": "api",
25272527
"verify": "the scratch-set member's positions are proven server-side to exclude platform_admin (BUILTIN_IDENTITY_PLATFORM_ADMIN = 'platform_admin', packages/spec/src/identity/eval-user.zod.ts), then both toggles answer 200 and GET /api/v1/data/sys_metadata_activation shows the metadata_type 'flow' and 'action' rows with active false and no organization_id key at all; re-enable restores active true. ⛔ Do not score the tenant half from a VALUE read — a check of the shape `row.organization_id ?? null` is `null` for a column that does not exist, so it passes while measuring nothing; read the key set (platform-core.activation-ledger-row-contract owns that probe)",
25282528
"evidence": "the position proof + both 200 traces + the ledger rows"
25292529
},
25302530
{
2531-
"clause": "walled postures (`group`/`isolated`) — pin-scored, since 18.0 refuses the walled boot a live probe needs (knownGaps[0]): an org admin holding manage_metadata is refused 403 PERMISSION_DENIED with a message naming the POSTURE and the per-artifact remedy — flows recommend the clone path, actions deliberately do NOT (operator + sibling authoring instead) — no row is written on refusal, and a caller carrying the platform_admin POSITION (not a capability) is admitted",
2531+
"clause": "walled postures (`group`/`isolated`) — pin-scored, since 18.0 refuses the walled boot a live probe needs (knownGaps[0]): an org admin holding manage_metadata is refused 403 PERMISSION_DENIED with a message naming the POSTURE and the per-artifact remedy — both remedies name the platform operator and NEITHER recommends a clone (ADR-0131 D6 · D12 items 7–8: under a wall a clone is environment authoring, the operator's too; both pins assert the operator and no 'clone') — no row is written on refusal, and a caller at the ADR-0095 PLATFORM_ADMIN posture rung (not a position name, #15981; not a capability) is admitted",
25322532
"oracle": "test",
2533-
"verify": "stands on the unit pins, since 18.0 refuses the walled boot a live probe needs (knownGaps[0]): packages/runtime/src/domains/automation-activation-posture-gate.test.ts (#12157) and action-activation-posture-gate.test.ts (#12160) drive the posture x identity matrix against both doors and assert toggleFlow/the write was never entered on refusal; the refusal sentence and remedies are activation-gate.ts,155-163. Do not tick this clause from an HTTP probe on a faked posture",
2533+
"verify": "stands on the unit pins, since 18.0 refuses the walled boot a live probe needs (knownGaps[0]): packages/runtime/src/domains/automation-activation-posture-gate.test.ts (#12157) and action-activation-posture-gate.test.ts (#12160) drive the posture x identity matrix against both doors and assert toggleFlow/the write was never entered on refusal; the refusal sentence is packages/runtime/src/domains/activation-gate.ts#refuseUngrantedActivationWrite's, and the remedies are the `remedy` of packages/runtime/src/domains/activation-gate.ts#FLOW_ACTIVATION_SUBJECT and packages/runtime/src/domains/activation-gate.ts#ACTION_ACTIVATION_SUBJECT. Do not tick this clause from an HTTP probe on a faked posture",
25342534
"evidence": "the two test runs' output, cited by test name"
25352535
},
25362536
{
25372537
"clause": "engine self-invocation bypasses both tiers (isSystem, never settable from the wire) — the boot pull and ledger hydration must not be refused by the gate that guards the wire",
25382538
"oracle": "test",
2539-
"verify": "the isSystem arms of the same unit pins (activation-gate.ts,190 — both return undefined before any check); corroborate live by the fact that a restart re-hydrates flow activations without error while the gate is armed",
2539+
"verify": "the isSystem arms of the same unit pins (packages/runtime/src/domains/activation-gate.ts#refuseUngrantedActivationWrite and packages/runtime/src/domains/activation-gate.ts#refuseUngrantedActivationAuthoring each open with `if (ec?.isSystem) return undefined`, before any check); corroborate live by the fact that a restart re-hydrates flow activations without error while the gate is armed",
25402540
"evidence": "test output + the boot log line"
25412541
}
25422542
],
25432543
"negative": [
25442544
"the §5 posture-gate sentence ('…this deployment runs the \\'single\\' tenancy posture…') appearing on a stock boot is a FAIL — the gate must not fire where postureEnforcesWall is false",
25452545
"run the refused calls as ADMIN too and confirm 200 (wrong-persona both sides): the denial must come from the missing capability, not a broken route",
25462546
"the two doors' tier sentences must not swap: the flow door owns its own FLOW_ENABLEMENT_DENY_MESSAGE while the action door speaks the shared activation-gate sentence — a run quoting the wrong door's string has probed the wrong door",
2547-
"absent tenancy service fails OPEN by design (activation-gate.ts,141-147): do not file a missing-refusal finding against a deployment with no tenancy service — that is ADR-0093 D4/D5, not a hole"
2547+
"absent tenancy service fails OPEN by design (packages/runtime/src/domains/activation-gate.ts#readEffectiveTenancyPosture answers undefined when no tenancy service is registered, and the gate then refuses nothing; the file header's section 'Fail-open on an ABSENT posture is deliberate' gives the reason): do not file a missing-refusal finding against a deployment with no tenancy service — that is ADR-0093 D4/D5, not a hole"
25482548
],
25492549
"variants": [
25502550
"single (stock — gate inert, tier decides)",
@@ -2561,7 +2561,7 @@
25612561
"ref": "packages/runtime/src/domains/automation-activation-posture-gate.test.ts (#12157, flow door) + packages/runtime/src/domains/action-activation-posture-gate.test.ts (#12160, action door) — the full posture x identity matrix for both doors, including the group/isolated legs this item marks blocked(fixture), the no-write-on-refusal assertion, and the isSystem bypass"
25622562
},
25632563
"source": [
2564-
"packages/runtime/src/domains/activation-gate.ts#posture (the shared §5 gate: posture read 141-147, platform_admin POSITION test 149-150, manage_metadata tier 184-203, per-artifact remedies 100-118, fail-open rationale 50-56)",
2564+
"packages/runtime/src/domains/activation-gate.ts#refuseUngrantedActivationWrite (the shared §5 gate: the posture read through readEffectiveTenancyPosture and the early return where postureEnforcesWall is false, then the PLATFORM_ADMIN posture-rung test, #15981 — never a position name) + packages/runtime/src/domains/activation-gate.ts#refuseUngrantedActivationAuthoring (the manage_metadata tier) + packages/runtime/src/domains/activation-gate.ts#FLOW_ACTIVATION_SUBJECT and packages/runtime/src/domains/activation-gate.ts#ACTION_ACTIVATION_SUBJECT (the per-artifact remedies); the fail-open rationale is the file header's section 'Fail-open on an ABSENT posture is deliberate'",
25652565
"packages/runtime/src/domains/automation.ts#FLOW_ENABLEMENT_DENY_MESSAGE (FLOW_ENABLEMENT_DENY_MESSAGE), (isFlowActivationWrite), (gate ordering ahead of service probe and body checks)",
25662566
"packages/runtime/src/domains/actions.ts (both tiers at the action door)",
25672567
"packages/spec/src/security/tenancy-posture.ts#TenancyPostureSchema (TenancyPostureSchema — the variants source; postureEnforcesWall; the ADR-0105 D12 entitlement note)",
@@ -2592,6 +2592,12 @@
25922592
"date": "2026-10-19",
25932593
"change": "fixtures.knownGaps[0], steps[8], acceptance[4] (clause, verify) and variants[1]–[2] re-grounded — the 18.0 sweep's wave-wide theme '18.0 refuses every walled posture' (wave anchor #24579 §2). The walled legs were blocked(fixture) on an enterprise-runtime gap; re-derived at base bfc1539fe0 that is not what 18.0 does: serve.ts walledPostureRefusal refuses group and isolated before a config is read, ahead of the multi-org runtime load, and that runtime is open code since ADR-0132. Clause 5 keeps its unit pins as its oracle and its wording; no clause deleted",
25942594
"ref": "#24687"
2595+
},
2596+
{
2597+
"revision": 5,
2598+
"date": "2026-10-20",
2599+
"change": "line citations re-pointed — the carried note from round 5 of wave anchor #24579 (its report, comment 6279808387). acceptance[3].clause, acceptance[4].verify, acceptance[5].verify, negative[3] and source[0] cited activation-gate.ts by line number in a comma-range spelling (',141-147', ',155-163', ',190', and source[0]'s five ranges), the rot class the line-citation limb exists for and does not detect; at this base those lines hold other code. Each now anchors the declaring symbol (refuseUngrantedActivationWrite, refuseUngrantedActivationAuthoring, readEffectiveTenancyPosture, FLOW_ACTIVATION_SUBJECT, ACTION_ACTIVATION_SUBJECT) or names the header section in prose. Reading the gate for that, acceptance[4].clause was corrected beside its walled lead, which is unchanged: it said flows recommend the clone path and that the platform_admin POSITION admits; both remedies name the operator and neither a clone (ADR-0131 D6 · D12 items 7–8, as both pins assert), and the gate reads the PLATFORM_ADMIN posture rung, never a position name (#15981). Not loosened: the oracle and the pins are unchanged",
2600+
"ref": "#24717"
25952601
}
25962602
]
25972603
},
@@ -2792,7 +2798,7 @@
27922798
"title": "OS_PLATFORM_OWNER_EMAIL platform-admin anchor: only a VERIFIED stored-email match confers PLATFORM_ADMIN — unset, unverified match, non-match and malformed lists each confer nothing, fail closed",
27932799
"since": "v17",
27942800
"status": "active",
2795-
"revision": 3,
2801+
"revision": 4,
27962802
"priority": "P1",
27972803
"surface": "api",
27982804
"personas": [
@@ -2810,7 +2816,7 @@
28102816
]
28112817
},
28122818
"steps": [
2813-
"boot showcase single (OS_TENANCY_POSTURE=single — also what a deployment with no tenancy configuration resolves to) with the variable UNSET — a walled posture (group / isolated) refuses to boot with it unset (plugin-auth init; out of scope here, see negative) — and keep that posture for every restart below; admin session; sign up fresh member M and record M's email; as M: GET /api/v1/datasources and GET /api/v1/auth/me/permissions (read systemPermissions) — the baseline refusals",
2819+
"boot showcase single (OS_TENANCY_POSTURE=single — also what a deployment with no tenancy configuration resolves to) with the variable UNSET — a walled posture (group / isolated) is out of scope here (see negative), and on 18.0 it does not boot at all: os serve refuses it before a config is read, whether the variable is set or unset (packages/cli/src/commands/serve.ts#walledPostureRefusal; RUNNER.md environment facts) — and keep that posture for every restart below; admin session; sign up fresh member M and record M's email; as M: GET /api/v1/datasources and GET /api/v1/auth/me/permissions (read systemPermissions) — the baseline refusals",
28142820
"restart with OS_PLATFORM_OWNER_EMAIL=<M's email> (M's row is unverified); as M repeat both probes",
28152821
"restart with OS_PLATFORM_OWNER_EMAIL=<an address matching no sys_user row>; repeat M's probes",
28162822
"entitled side (see knownGaps for the verified-member fixture): with M's row verified and the variable naming M, as M repeat the probes and read /api/v1/auth/me/permissions — expect the declared admin envelope; where the fixture is unavailable, run the unit pin and cite its output instead. This step runs BEFORE the malformed variant on purpose: the malformed list's 'the well-formed sibling confers nothing' check only discriminates once M is verified",
@@ -2907,6 +2913,12 @@
29072913
"date": "2026-10-16",
29082914
"change": "steps reordered (#23878 checklist-accuracy finding): the malformed-list variant ran while M was still unverified, so its refusal could not be told apart from the unverified arm, and the 'well-formed sibling confers nothing' check only bites once M is verified. The entitled step now precedes the malformed one, which keeps M verified, and clause 4's verify says so; knownGaps[0] records how the verified fixture was made (the admin update-user door refuses; a direct email_verified stamp on the isolated scratch DB). Re-run on main c91af8ed6, single posture, same DB across restarts: var unset → M 403, systemPermissions []; var = M unverified → 403, []; var = a non-matching address → 403, []; M verified and var = M in another case → datasources 200, 9 system permissions incl. manage_platform_settings; var = 'M, not an address' with M verified → 403, [] and the [authz] whole-variable refusal naming the entry; the admin answered 200 on every boot",
29092915
"ref": "#24036"
2916+
},
2917+
{
2918+
"revision": 4,
2919+
"date": "2026-10-20",
2920+
"change": "steps[0]'s walled parenthetical corrected — the carried note from round 5 of wave anchor #24579 (its report, comment 6279808387). It said a walled posture refuses to boot with the variable unset (plugin-auth init); on 18.0 serve.ts#walledPostureRefusal refuses a walled posture earlier, before any config or plugin, whether the variable is set or unset. The item boots single throughout and no clause scores the walled case, so no clause changed",
2921+
"ref": "#24717"
29102922
}
29112923
]
29122924
},

0 commit comments

Comments
 (0)