Repository navigation
docs(qa): checklist item for public-form withdrawal layering (17.7 security follow-up) - #21964
Merged
objectstack-fleet[bot] merged 2 commits intoOct 6, 2026
Conversation
access-security.public-form-withdrawal-layers asserts how a public form's withdrawal composes across metadata layers: an organization overlay cannot re-open a form the env-wide definition withdrew (both anonymous doors and the org-scoped write door), only an explicit false withdraws, a package's schema-parsed false withdraws, and the env-wide definition may open a package-closed form. The ruled known limit (name-anchored doors; overlays stored before the withdrawal or restored by rollback or revert) is recorded as a knownGap, not a clause. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 6, 2026
objectstack-fleet
Bot
deleted the
claude/issue-21932-checklist-public-form-layering
branch
October 6, 2026 07:40
This was referenced Oct 6, 2026
Merged
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
… of objectui#10202 (objectstack-ai#21969) Fixes objectstack-ai#21957 Clause-②: no ## What changes `docs/qa/platform-checklist/areas/studio-authoring.json` gains one item, `studio-authoring.picklist-bound-select`: rev 1, `since: v17.7`, P2, surface `mixed`. It is appended after `studio-authoring.doc-on-app-menu`. It is part (d) of the director ruling 6006062645 on objectui#10202 (letter A′). No other item changes, no item index moves, and no other file is touched. ## Changes from the card's draft, and why 1. **`since` is `v17.7`, not `v17.6`.** - 17.6.0 has already shipped: the `@objectstack/*@17.6.0` tags point at `617f25f8` (2026-10-02). - objectui PR 11669 merged later, on 2026-10-06, as objectui `c3623eb1`. - No 17.7 tag exists yet. Of the 315 pending changesets, 146 declare a minor bump and none a major, so the next release is 17.7. - This week's sibling item `access-security.public-form-withdrawal-layers` (PR objectstack-ai#21964) also sets `v17.7`. - One condition: the feature ships in 17.7 only if `.objectui-sha` moves past `c3623eb1` before the 17.7 cut. See "The console pin" below. 2. **The draft's third clause is split in two.** Its `"oracle": "mixed"` is not in the gate's oracle set (`api`, `network`, `screenshot`, `dom`, `log`, `test`, `build`). The draft's words are kept in both halves: - the picker half is `dom`: picker options against `GET /meta/picklist`; - the PUT half is `api`: the captured PUT body and status. 3. **The picklist fixture line now spells the recipe**, so a runner can write it from the item's text alone: - the file to edit, `examples/app-showcase/objectstack.config.ts`, and the `defineStack` keys `picklists` and `picklistExtensions`; - `definePicklist`, exported from `@objectstack/spec`; - the extension's one value must be new: a repeated value is refused at load with `INVALID_METADATA`; - the extension may sit in the list's own package. `packages/objectql/src/engine-picklist.test.ts` pins this: its nested-plugin case merges an extension registered under the list's own package; - boot with `--compile`. Otherwise `os dev` serves an existing `dist/objectstack.json`; it warns that the artifact is stale, but it boots. The fixture stays uncommitted, and nothing is added to `examples/`. 4. **The console fixture line names the merge it must carry**: objectui PR 11669, merged as `c3623eb1`. A runner can then check whether the console under test carries it. 5. **The spec citations are now anchors the gate resolves** (README, "Write the symbol as an ANCHOR"): - `PicklistSchema`, `PicklistExtensionSchema`, `PicklistServedFieldSchema` and `definePicklist`; - `FieldSchema.picklist`; - the stack keys `picklists` and `picklistExtensions`. This file's anchor census goes from 29 to 36, and all of them resolve. The producer-obligation citation now also names objectui#10202, where comment 5925784898 lives. 6. The history entry carries `"ref": "objectstack-ai#21957"` and lists these changes. ## The console pin On `main` (`80f9f7e6`), `.objectui-sha` is `0abd4f9f`. That pin does **not** contain `c3623eb1`, the merge of objectui PR 11669. The reading was taken in a shallow objectui checkout: - `git merge-base --is-ancestor c3623eb1 0abd4f9f` exits 1; - the control leg, `0abd4f9f~30` (`b65aa5e`) against `0abd4f9f`, exits 0; - the reverse also exits 0: `0abd4f9f` is an ancestor of `c3623eb1`, 21 commits behind it. So the console fixture line is load-bearing until the pin moves. That line asks for `pnpm objectui:refresh` from an objectui at or after the merge. ## Verification (at `eed17a88b`) `dispatch-gates.mjs --commands` derives 13 gates for this diff, and all 13 were run. Exit codes were captured before any pipe. `--ran` reconciles the list as 13 derived, 13 run, 0 NOT-MEASURED (a derived zero). | gate | exit | verdict | |---|---|---| | `pnpm check:platform-checklist` | 0 | OK: 15 areas, 275 items (271 active, 2 planned); symbol anchors 683/693 resolved (676/686 on the base) | | `node scripts/check-ci-filter-parity.mjs` | 0 | OK | | `node scripts/check-closing-keyword-parity.mjs` | 0 | OK: 3 parsers agree on all 9 keywords | | `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | 40 assertions | | `node scripts/check-comment-mask-corpus.mjs` | 0 | 8297 files, 0 disagree | | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` | 0 | clean (see below) | | `pnpm check:cross-package-test-inputs` | 0 | OK | | `pnpm check:doc-authoring` | 0 | clean | | `pnpm check:driver-memory-census` | 0 | OK | | `pnpm check:gitlink-declared` | 0 | OK | | `pnpm check:nul-bytes` | 0 | OK: no raw ASCII control bytes | | `pnpm check:refd-timer-probe` | 0 | OK | | `pnpm check:watch-hint-literal` | 0 | OK | - `check:doc-formula-expressions` first exited 3: its prerequisite was not met, because `@objectstack/formula` and `@objectstack/lint` were not built. After `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint`, it was re-run and exited 0. - `checklist-select.mjs` resolves the item as runnable under both `studio-authoring.picklist-bound-select` and `since:v17.7`. The diff is checklist JSON only and changes nothing a published package ships, so the PR takes `skip-changeset`. ## Acceptance notes - **Not run yet.** This PR writes the item; no run record exists. The first run needs a console that carries objectui PR 11669 (see "The console pin"). - **`coverage.json` is unchanged; the `picklist` kind stays waived.** - The checklist's rules do not require a mapping for a new item. - The waiver also names its own retirement edit: the promotion of the planned `records-forms.picklist-shared-across-objects`. - The waiver's premise, "No runtime reads a picklist", no longer holds. The runtime half (objectstack-ai#19519) has landed: see objectui#10202 comment 5925784898 and `packages/objectql/src/picklist-resolution.ts`. - So the next sweep's waiver re-audit should rewrite or retire it. Carrier: none. - **The showcase has the same stale premise.** Its own coverage waivers for `picklist` and `picklistExtensions` in `examples/app-showcase/src/coverage.ts` say "declared ahead of its runtime reader". Carrier: none. - **Scope held.** The item's steps go only through the two designers objectui#10202 repaired: Setup → Metadata → Object, and the Studio data page. They never go through Studio → Access → OWD overview, a writer known to fail that is filed on the objectui side. --- _Generated by [Claude Code](https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw)_ Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
…ce row no longer displaces a code-defined datasource at boot, and the metadata door refuses edits to the host default (objectstack-ai#21965) Part of objectstack-ai#21922 Fixes objectstack-ai#21944 Clause-②: no (narrowing) ## What changes A code-defined datasource (a `*.datasource.ts` the installed artifact declares, or the host's own `default`) is read-only by published contract: `DatasourceSchema.origin` says "code — authored as `*.datasource.ts`, GitOps-owned, read-only in the UI", the datasource registry entry in `metadata-plugin.zod.ts` says code-defined datasources "win on name collision", and `datasource-admin-service.ts` says "A runtime datasource never shadows a code one (code wins on collision)". The datasource-admin plugin's boot restore broke all three, and the metadata door could not see `default` at all. The fix is the one host-owned set of code datasources the two cards' triage asked for ("One set serves both, so do not build two"): - **The set** (`packages/runtime/src/code-datasource-names.ts`, new). One in-memory `Set` of the datasource names the host registers from code, on the kernel service `code-datasource-names`. `contributeCodeDatasourceNames` registers it on first use and adds to it after that, the shape `seed-summary` uses. - **Its producers, both in `init()`.** `AppPlugin.init()` adds every datasource the artifact declares: the same list its `start()` registers in the MetadataService, now memoized so the two phases read one answer. `DefaultDatasourcePlugin.init()` adds `default`. Phase 1 completes before any `start()`, so the set is whole before the restore runs, whatever order the plugins were composed in. - **The restore** (`restoreRuntimeDatasources`, `packages/services/service-datasource/src/datasource-admin-plugin.ts`). A stored row under a name in the set is not registered over the code definition. It is kept, and one boot warning names it with the repair. The warning goes to the host's `options.logger`, or to the kernel logger when the host passes none (`os serve` passes none). - **The resolver** (`isDeclaredCodeDatasource`, `packages/metadata-protocol/src/protocol.ts`, nothing else in that file). It reads the same set beside the installed packages, so the metadata door answers `default` the way it answers every code-defined datasource since PR objectstack-ai#21942. ⛔ "Code" is never read from a stored row's `origin`, the MetadataService slot's `origin`, the connection service's `ConnectResult`, or a request body's `origin`. ## Measured on a booted showcase The harness is the `@objectstack/verify` `bootStack` with the datasource-admin routes mounted the way `serve.ts` mounts them, in a temp cwd. The stored rows assert `origin: 'runtime'` and their own `config.filename` (the cards' case (b)). They were written through the metadata door's repository on the runtime-only intent, then the stack restarted. BEFORE is `76fec88b16`; AFTER is this branch at `1d840709ae`. The readings come from a throwaway probe that was never committed; the committed pins below assert the AFTER column. | Reading after the restart | BEFORE | AFTER | |---|---|---| | admin list, `showcase_external` | `origin: runtime`, label "Shadow 21922" | `origin: code`, "External Analytics (SQLite)" | | `PATCH /api/v1/datasources/showcase_external` | 200 | 400 `DATASOURCE_ADMIN_ERROR` "… is code-defined and cannot be edited at runtime." | | live pool named `default` | a second pool opened on the stored row's file; verdict `already-registered` became `connected` | none; verdict stays `already-registered` | | `showcase_ext_customer` read | 3 rows (code fixture) | 3 rows (code fixture) | | boot warning naming each stored row | none | one per row | | `PUT /api/v1/meta/datasource/default` | 200 "Saved datasource 'default'" | 403 `NOT_OVERRIDABLE` | | `DELETE /api/v1/meta/datasource/default`, no stored row | 200 | 403 `NOT_OVERRIDABLE` | | `DELETE /api/v1/meta/datasource/showcase_external` (repair), then meta `GET` in the same boot | 200, but the meta `GET` kept serving the stored edit until the next restart | 200, and the meta `GET` serves the code definition | ## The dispatch's mechanism hypotheses - **H1, start order.** In all three compositions that load `service-datasource` (`serve.ts`, `standalone-stack.ts`, the verify harness), `DefaultDatasourcePlugin` and `AppPlugin` are `use()`d before `DatasourceAdminServicePlugin`. None of the three declares an ordering edge to another, so their `start()`s run in insertion order: the code registrations did land before the restore, but by list position alone, which ADR-0116 says proves nothing. The answer is the first branch: the set is filled by a phase that precedes the restore (`init()`). It is pinned by a boot whose reader plugin is composed first, ahead of every producer. The restore pin also covers a code registration that lands after it. - **H2, the seam.** It is a kernel service read through the services registry the protocol already resolves (`getServicesRegistry()`), with no `packages/spec` change. The ObjectQL registry was rejected: the engine's datasource definitions mix both origins, and a host package record would be a fabricated provenance. - **H3, the admin refusal.** Measured, not assumed. The pins' stored rows carry `origin: 'runtime'`, and the slot the refusal reads holds AppPlugin's explicit `origin: 'code'`. Under ablation A the admin door served the stored row as `origin: runtime`, so the refusal cannot come from the admin read's `origin ?? 'code'` default. - **H4, the live pool.** For `default`: yes. The restored row reached `rehydratePools`, which opened a second pool named `default` on the row's file. Routing did not move, because the engine never routes to a driver named `default`; the default driver keeps its natural name. It is the same defect and the same decision fixes it, pinned by `getDriverByName('default')` and the connect verdict. For `showcase_external`, nothing was re-pointed at boot in this composition: AppPlugin's connect ran first, so the rehydrate answered `already-registered`. The admin `PATCH` 200 was the open door to a re-point (an update that changes connectivity rebuilds the pool), and it is now refused. ## Seam and the Clause-② limb (for the seat) - **Published exports added: none.** `code-datasource-names.ts` is not re-exported from `packages/runtime/src/index.ts`. `service-datasource` and `metadata-protocol` spell the service name privately and read the value structurally as `has(name)`, the way `'datasource-connection'` is read today. - **What the seam does add is one kernel service entry**, `code-datasource-names`, which two packages read by name. Whether that is the claim's "service contract" limb is the seat's call. The line above stays as the claim wrote it, and the changeset grades all three packages `minor`, which holds under either reading. ## Named gap: the metadata door's read while a stored row exists `GET /api/v1/meta/datasource/:name` still serves a stored row under a code-defined name for as long as the row exists. The door reads its stored overlay first (ADR-0005's read order), whatever the MetadataService holds. The AFTER boot measured it: the admin door served the code definition while the meta `GET` served the stored row, for `showcase_external` and for `default`. So triage's pins "both doors serve the code definition" and "removes it with no change to what is served" hold for the admin door. For the metadata door they hold once the repair `DELETE` has run, in the same boot. That read lives in `getMetaItem`'s overlay step, outside `isDeclaredCodeDatasource`, and `protocol.ts` is held by objectstack-ai#21934 in other regions, so it is left to the seat. `meta-door-code-datasource.dogfood.test.ts` already pins that read as it is. objectstack-ai#21922 stays open for that read: this PR is `Part of` it, and the seat routes the remaining half through triage when it merges. ## Landing beyond the claim's named files `packages/runtime/src/app-plugin.ts` is the producer of the packages' half of the set, in the declared `runtime` package. The memo also makes its residual-owner warning print once instead of once per phase. `packages/runtime/src/code-datasource-names.ts` is new in the same package. ## Patch round 1 (head `d77e150701`) Review `6011282321` on objectstack-ai#21922. The Tests, Ablations and Gates sections below are round 0's, at `80fbcfdea6`; this section carries the readings on the current head. - **The plugin-dev pin (CI red on round 0).** `AppPlugin.init()` now contributes its datasource names as a function that the host's code-datasource set resolves at its first read. The set is still contributed to only in Phase 1, before any `start()`. The resolution is deferred because the names come from the artifact's `collections`, which walk `packages[]`. `AppPlugin.init()`'s manifest registration is the one thing in `init()` allowed to touch `packages[]`, pinned by `plugin-dev`'s malformed-stack falsifier, which this PR's first head turned red. The kernel service now holds a `CodeDatasourceNames`, a set with pending contributions; readers still use `has(name)` only. A contribution that throws stays pending and rethrows to every reader. - **The `default` refusal names what defines it**: the host's database configuration (the database URL the server starts with). It names no `*.datasource.ts`, because none declares `default`. Every package-declared datasource's sentence is byte-identical, and `code`, `status` and the refused set are unchanged (`packaged-base-regime.ts`, the datasource row's `hostOwned`). - `const listOf = (` spacing restored in `app-plugin.ts`. Merged `origin/main` `80f9f7e6ba` as `49421a8fe6`. - **Ablation D:** the old sentence put back for `default` turned 6 unit cases and 1 dogfood case red, and was restored by blob. - **Tests at `d77e150701`** (each `VERDICT command-exit 0`): - `service-datasource`: 748 / 748; - `metadata-protocol`: 27978 passed, 19 skipped; - `runtime` local: 4668 passed, 19 skipped; - `plugin-dev`: 86 / 86; - the two dogfood files: 11 / 11; - downstream consumers of `runtime` (cli, client, verify, http-conformance, cloud-connection): all passed; - typechecks for the five packages: green. - **Gates at `d77e150701`:** `dispatch-gates --commands` derived 72, reconciled with `--ran` as 72 run and 0 not measured, plus `check:init-service-contract` and `check:startup-registry-verdict`. All exit 0. - **Docs:** the 18 hand-written pages the Docs Drift Check lists were read page by page. None states anything this PR makes false, so no docs are edited. ## Tests (head `80fbcfdea6`) - `pnpm --filter @objectstack/service-datasource exec vitest run --maxWorkers=2`: 41 files, 748 passed. - `pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2`: 218 files passed, 3 skipped; 27976 tests passed, 19 skipped. - `pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 --project local`: 331 files, 4658 passed, 19 skipped. - Dogfood, `--project isolated`: `datasource-restore-code-wins.dogfood.test.ts` (new) and `meta-door-code-datasource.dogfood.test.ts`, 2 files, 11 passed. - `typecheck` green for `service-datasource`, `metadata-protocol`, `runtime` (including its `check:test-typecheck` ledger, held) and `dogfood`. `tsc --listFiles` counts each touched test file once in its program. - Each package's run includes its new pins: 5 in `datasource-admin-plugin.test.ts` (the restore), 4 in `code-datasource-names.test.ts` (the set and its phase), and 2 resolver plus 8 door cases in `protocol.code-defined-datasource-door.test.ts` (`default`, on both kernel shapes). ## Ablations Each one was committed first and mutated with `scripts/ablation-replace.mjs` in wrap mode, under a shell trap. For subjects resolved through `dist/`, the package was rebuilt and `ablation-dist-preflight.mjs` proved the marker was present. The restore leg was rebuilt and proven `--absent`, the blob equalled HEAD, `git diff HEAD` was empty, and the tree was clean. - **A, the restore registers over a code name** (`datasource-admin-plugin.ts`; marker in 2 files of `service-datasource/dist`). Unit: 3 failed, 16 passed. The slot served the stored row, the warning was not called, and the order-independent case registered the row. Dogfood: 2 failed, 3 passed. The admin list served `showcase_external` as the stored row, and the repair case read the same. - **B, the resolver does not know the set** (`protocol.ts`; marker in 2 files of `metadata-protocol/dist`). Unit: 5 failed, 30 passed (the resolver case, and `PUT` plus no-row `DELETE` of `default` on both kernels). Dogfood: `PUT /meta/datasource/default` answered 200. The next case then failed as a cascade, because the row that `PUT` stored made the seed conflict. The repair `DELETE` and runtime controls stayed green, as expected. - **C, AppPlugin's `init()` contribution deleted** (`app-plugin.ts`; the subject resolves from source). The reader-first boot saw `['default']`, not `['app_wh', 'default']`. So the set comes from `init()`; the `start()` registration never fills it. ## Gates (head `80fbcfdea6`) `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 72 commands on the actual change, a superset of the 52 at dispatch. All 72 ran with exit codes captured before any pipe. `--ran` printed "72 derived famil(ies) accounted for — 72 run, 0 NOT-MEASURED". - `check:dual-build-cjs-loads` first answered `PREREQUISITE NOT MET` (exit 3) because eight packages outside this diff had no `dist/`. After building them it measured green. - Two families the derivation does not name were also run, both green: `check:init-service-contract` ("34 declared / 1 self-provided / 3 without a workspace provider") and `check:startup-registry-verdict` ("none recording a verdict the boot can contradict"). - `check-changeset-no-major`'s level axis needs a PR payload, so CI reads it. - Lint is a proven narrowing, not the repo-wide run. `eslint --no-inline-config --format json` on the 9 touched source and test files reported 9 files, 0 errors and 0 warnings. `eslint.config.mjs` never enables type-aware linting (no `parserOptions.project`, no typed rules, as its own comment states), so this diff cannot move any untouched file's verdict. ## Acceptance notes - **The `default` refusal's remedy** names the host's database configuration (patch round 1). - **Cluster convergence.** `convergePool` reads a stored row directly and is unchanged. Its signals come from peer admin writes, and the admin door now refuses those for code names. - **The restore's other warnings** (a failed read, a failed register) still go only to `options.logger`, which `os serve` does not pass. They are unchanged here. - **objectstack-ai#21923 remains open.** This diff does not touch `listDatasourceRecords`, `getDatasourceRecord` or `persistDatasourceRow`. One interaction: a metadata-door-created datasource with no `origin` still restores, and is still read as `code` by the admin door's default. - **Main drift.** `origin/main` gained objectstack-ai#21956, objectstack-ai#21964 and objectstack-ai#21961 (spec and docs-qa only) after the round-1 merge. None touches a file here, and the queue's merged generation is the check. --- _Generated by [Claude Code](https://claude.ai/code/session_01WMQprn46CND82KmY8sZWBu)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21932
Clause-②: no
What
This PR adds one checklist item,
access-security.public-form-withdrawal-layers, todocs/qa/platform-checklist/areas/access-security.json. It sits right afteraccess-security.public-form-intake. Its fields are rev 1,since: v17.7, P1, surfaceapi. No other file changes.This delivers the last two rows of #21932. The first five rows and both re-checks landed in PR #21943.
The #21835 / PR #21864 row: public-form withdrawal layering
The item is written against what PR #21864 landed on
main. Its merge,3c7785d4ab, is an ancestor of this branch's base01e0f71a. Each rule on the card maps to a clause:FORM_NOT_FOUNDand no row lands. acceptance[1]: an org-scoped save that would leave the form open answers 403NOT_OVERRIDABLErest-server.ts#registerFormEndpoints,anonymous-form-intake.ts#anonymousFormIntakeWithdrawnIn,protocol.ts#anonymousFormIntakeReopenRefusalallowAnonymous, or nopublicLink, env-wide, the org save that opens the form is accepted and both doors serve itanonymous-form-intake.ts#anonymousFormExplicitWithdrawals. Premise:protocol.ts#projectStorableViewBodyanonymousFormExplicitWithdrawals. Pins:protocol.org-scoped-write-refused.test.ts('single: a package-shipped form') andanonymous-form-intake.test.tsprotocol.ts#envWideRawViewRows, with the same protocol pinfixtures.knownGaps[0], plus a negative saying it is not a FAILsaveMetaItemand the draft promotion, never fromrollbackMetaItemorrevertCommitacceptance[3] is the control pair, which the dogfood also pins:
automated.refleads withpackages/qa/dogfood/test/showcase-public-form-withdrawal-layers.dogfood.test.ts. That dogfood covers acceptance[0], [1] and [3] end to end. The ref also names the rest, metadata-protocol and metadata-core unit pins.The steps drive the stock showcase form,
showcase_inquiry.contactat/forms/contact-us. The admin saves it at two scopes: env-wide, and in the Default Organization the doors read. Both doors are probed anonymously.Where the code is narrower than the card's wording
Where they differ, the item follows the code:
defineStack, the default). There the schema defaultenabled: falsecounts as an explicit false. An artifact loaded unparsed (strict: false, or a hand-built manifest) is judged as written, so a switch it omits is absent and withdraws nothing. acceptance[4] says so.publicLink. A sharing with no link withdraws nothing, even with both switches false. acceptance[2] says so.maincarries "Known limit: packages and names" besides the ruled one. Cases where two packages ship the same view name are outside this item's fixture. The item points at that docs section as it reads at the run's commit, rather than restating it.The #21867 / PR #21928 row
Confirmed on
mainwith no change. The item isautomation.paused-run-trigger-record-maskedindocs/qa/platform-checklist/areas/automation.json, at rev 1,status: active. Itsautomated.refispackages/qa/dogfood/test/flow-trigger-record-credential-mask.dogfood.test.ts, which is on disk. PR #21928 merged as1f0469655f, an ancestor of this branch's base.Overlap with #21934
#21934 is not addressed here. Its PR #21962 was an open, unmerged draft when this PR was opened, so the item is written against
mainas it stands.envWideRawViewRowsnote holds either way. It is scoped to "a form one package ships", which is true before and after PR fix(metadata-protocol): org overlay withdrawal and publish gate follow-ups (package identity, judged draft, lock key, row anchor) #21962. That PR keeps the symbol and resolves it per package.content/docs/ui/public-data-collection.mdxnor any package source.Tests
All results are at head
2d51effa.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 13 commands, the same 13 the dispatch named. All 13 exited 0, with each exit code captured before any pipe. The--ranreconciliation reads 13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN.pnpm check:platform-checklistansweredOK — 15 areas, 275 items (271 active, 2 planned)with 690/700 symbol anchors resolved. At the base01e0f71ait read 274 items and 676/686. All 14 new anchors resolve, and the 10 that do not are the named [finding] the platform-checklist corpus resolves symbol anchors with its OWN rule, not the shared resolver — a permissive token match where the ruling says there is to be exactly one implementation #16898 residual.pnpm --filter @objectstack/lint run check:doc-formula-expressionsfirst exited 3 (PREREQUISITE NOT MET, because formula and lint were unbuilt), so that run measured nothing. I built both underos-verify-lock(VERDICT command-exit 0), and the gate then exited 0.main. The pins themselves were not re-run here; they ran in CI on PR fix(rest,metadata-protocol): a public form's intake withdrawal at any metadata layer holds; layering can only narrow intake #21864 and PR fix(trigger-record-change)!: a record-change flow's trigger record carries the credential mask and omits internal fields #21928.Acceptance notes
coverage.jsonis untouched. The claim's file surface isareas/*.json, and theviewkind is already mapped. Mapping the new item toviewis optional, and is left to whoever next ownscoverage.json.access-security.public-form-intakeclause 7 says "republishing restores service" but does not name the scope of the republish. With layering, republishing in an organization over an env-wide withdrawal is refused with a 403. The new item covers that case. The old item is unchanged, with no revision bump, to keep this PR to the card's rows.docs/qa/platform-checklist/areas/access-security.json, which no published package ships: the root package is private, and no packagefilesentry namesdocs/qa.skip-changesetapplies.Generated by Claude Code