feat(lint): require authored OWD at the runtime object door; retire ADR-0094 R2 external-wider arm; declare object in runtimeTypes - #8600
Conversation
…etire plugin-gate R2 external-wider arm The #8310 maintainer ruling (option A): an authored OWD is required at the runtime object door — an object publish with no authored sharingModel is refused with the 422 lint envelope (security-owd-unset). The plugin gate's R2 owd_external_wider arm is retired as duplicate of the lint door; R1 (env-tighten-only) stays. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 2 package(s): 14 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also reference the affected code. These are read-only:
|
…t meta-object-owd-gate to the ruled door order Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
…prose, changeset Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
|
How to clear the one red check — recording the exact cause, quoted from the failing job's log, so the merger doesn't have to dig. CI on head So the gate is not reporting a defect in the change — it is reporting that no approving review exists yet, which is exactly the human floor for an ADR-touching PR (the ruling it enforces: 「门禁改成只要求「APPROVED review 存在」」/「不要指定具体的人」, maintainer 2026-08-12, #8161). Its own message notes drafting and pushing were fine; only the MERGE is gated. Why this seat cannot clear it itself: every agent in this repo posts as Two ways forward, both the maintainer's:
Substance is unaffected either way: every test, build, typecheck, lint, dogfood and conformance job on this head is green, including the Generated by Claude Code |
… on validateSecurityPosture's reach (objectstack-ai#8547) (objectstack-ai#8866) Two test comments justified the `package-author` carve-out with a claim about where `validateSecurityPosture` is enforced, and that claim rotted twice. `protocol.runtime-authoring-gate.test.ts` still said the rule is `CLI_ONLY` in `AUTHORING_RULES`. The entry declares `surfaces: CLI_AND_RUNTIME` with `runtimeTypes: ['seed', 'permission', 'book', 'object']` — false since PR objectstack-ai#8390, and the `object` limb landed with PR objectstack-ai#8600. `meta-object-owd-gate.test.ts` had already lost the words `CLI_ONLY` but still concluded package authoring is "gated at build time instead", contradicting its own file header and the sibling comment 214 lines above, both of which say the rule now runs for `object` writes at that door. Neither site is repaired by a word swap. The carve-out is intact and was never the defect: both doors skip the `package-author` channel deliberately — `assertRuntimeAuthoringRules` returns early on it at every call site and the single `runAuthoringGate` call is guarded by the same check. The reason is re-founded on that channel rather than on the rule's reach, which moves with every objectstack-ai#7891 slice. Door order and ADR-0094's R1-stays / R2-retired outcome are pointed at where they are already pinned rather than restated a second time, and the surviving `isSystem` / `sys_*` exemption is recorded as fact with a pointer to the open decision card. Comment prose only: the diff touches `//` and ` *` lines exclusively. No behaviour, assertion, pin or test-count change. Claude-Session: https://claude.ai/code/session_01XeQRiAa7vYRVX5Fog7Zby8 Co-authored-by: Claude <noreply@anthropic.com>
Fixes #8310
HUMAN-MERGE ONLY (docs/adr touched) — per the reconciled ruling (issue comment 5287986058) this PR amends ADR-0094 text, so the PM reviews and the maintainer merges. Do not enable auto-merge. (
check-adr-merge-approvalis the CI guard for exactly this.)Implements the #8310 maintainer ruling (option A, reconciled scope, comments 5287702149 + 5287964032 + 5287986058), completing the #7891 flip set.
What changed
runtimeTypesgainsobjecton thevalidateSecurityPostureentry (packages/lint/src/authoring-rules.ts) — an active-state object publish with NO authoredsharingModelis now refused at the runtime door with the 422 lint envelope (INVALID_METADATA,security-owd-unsetinissues). Absence is not a decision. Whole-family registration, no bespoke check.packages/plugins/plugin-security/src/object-posture-gate.ts): the403 owd_external_widerarm is removed as the lint door's duplicate;403 owd_widening_forbidden(env-tighten-only over a packaged declaration) survives — no lint rule can judge the packaged baseline. ADR-0094 carries a dated amendment recording the retirement and its rationale, citing the ruling.packages/rest/src/meta-object-owd-gate.test.ts): the 422 lint door answers first (saveMetaItemrunsassertRuntimeAuthoringRulesbeforerunAuthoringGate— pinned including a body both doors would refuse); the 403 R1 door answers for writes that pass lint. The formera write with NO OWD keys SAVESpin (ADR-0094 absence-defaults-to-private) is overturned by the ruling and re-pinned as the 422 refusal. The former?mode=draft403 pin is re-pinned to the lint discipline ([runtime/metadata] 作者时规则只存在于 CLI:Studio/REST/MCP 的运行时授权面是第四扇门,26 条规则一条不跑——#4409 修完后最大的敞口 #4463 D1): the dirty draft saves; the draft→active promotion refuses 422.security-owd-unset) and 3 rest files (12 tests) measured red by PR feat(lint): permission/book cross the runtime publish gate; object measured dirty stays behind; security-role-word splits to stay behind whole (#8310) #8546 now authorsharingModel: 'private'on the object bodies they publish, each annotated[#8310].validate-security-posture.runtime-surface.test.ts: OWD-less object publish refused at the REAL gate; [1 of #7891]METADATA_CREATE_SEEDS.objectgains an authoredsharingModel— or an explicit default-OWD ruling (blocker A) #8308's create seed clean; clean write not blamed for pre-existing context defects; builder/gate parity; and the R2-retirement boundary pin (below).R2 shadowing measurement (the ruled falsification check)
Point 4's stop-condition was checked, not assumed. On the active publish path every semantically-correct R2 refusal is refused by the lint door first (
security-external-wider-than-internalwhen the internal side is orderable;security-owd-unset/security-owd-alias-or-unknownwhen it is not). Two literal divergence classes exist and both were judged NOT to falsify the retirement premise — flagged here for the maintainer's merge-time review:isSystem/sys_*) with unsetsharingModel+ explicit external: R2 refused them via its hardcoded private baseline, but the runtime's own default for exactly that shape is public (effectiveSharingModel, plugin-sharing) — R2's refusal contradicted the platform's runtime semantics (a false positive), andsecurity-owd-unsetdeliberately exempts system objects for the same reason. Pinned executable in the runtime-surface suite (the R2-retirement boundary).active, and nothing enforcement-reads a draft. Pinned in the rest suite (draft saves; promotion refuses 422).Declared surface (deltas vs the dispatch list)
content/docs/permissions/authorization.mdx— PM-relayed docs-drift fold-in: the governance section described the retired 403owd_external_widerarm; rewritten to the new door order. The other drift-bot pages carry noowd_external_wider/ R2 prose (greppedcontent/docs/permissions/,content/docs/kernel/runtime-services/sharing-service.mdx,docs/design/permission-model.md— the design doc's mention is the lint rule id, still accurate).content/docs/releases/**untouched.objectstack validateexits 0 on showcase / CRM / todo (every corpus object already authors its posture; remaining warnings are pre-existing advisories unrelated to OWD).Measurements
@objectstack/lint: build ✓, 72 files / 2018 tests ✓, typecheck ✓@objectstack/objectql: 202 files / 3559 tests ✓ (was 83 red / 13 files before repair, measured on this tree), typecheck ✓@objectstack/rest: 114 files / 1883 tests ✓ (was 8 red / 3 files before repair on this tree), typecheck ✓@objectstack/metadata-protocol: 84 files / 1261 tests ✓@objectstack/plugin-security: 55 files / 1075 tests ✓, typecheck ✓objectstack validateexit 0dispatch-gates.mjson the final diff run green locally (incl.check:nul-bytes,check:i18n,check:adr-anchors, changeset gates);check-adr-merge-approvalis CI-credential-bound (local 401) and is the human-merge guard itselfpackage-authorcarve-out pin stayed green (the ones that must not move). Restored and re-run green.Acceptance pins (ruling point → executable)
an OWD-less publish is refused — 422 security-owd-unset; lint:an OWD-less object publish is REFUSED at the real gatesharingModel, each annotated[#8310]; zero rule edits invalidate-security-posture.tsdoor ORDER: when lint AND R1 would both refuse, the 422 lint door answers first; R1 403 pins unchangedobjectdeclaredseed / permission / book / object all crossGenerated by Claude Code