Skip to content

feat(lint): require authored OWD at the runtime object door; retire ADR-0094 R2 external-wider arm; declare object in runtimeTypes - #8600

Merged
qq9340100 merged 6 commits into
mainfrom
claude/issue-8310-object-owd-door
Aug 14, 2026
Merged

feat(lint): require authored OWD at the runtime object door; retire ADR-0094 R2 external-wider arm; declare object in runtimeTypes#8600
qq9340100 merged 6 commits into
mainfrom
claude/issue-8310-object-owd-door

Conversation

@qq9340100

@qq9340100 qq9340100 commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

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-approval is 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

  1. runtimeTypes gains object on the validateSecurityPosture entry (packages/lint/src/authoring-rules.ts) — an active-state object publish with NO authored sharingModel is now refused at the runtime door with the 422 lint envelope (INVALID_METADATA, security-owd-unset in issues). Absence is not a decision. Whole-family registration, no bespoke check.
  2. ADR-0094-seam R2 retired, R1 stays (packages/plugins/plugin-security/src/object-posture-gate.ts): the 403 owd_external_wider arm 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.
  3. Door order re-pinned (packages/rest/src/meta-object-owd-gate.test.ts): the 422 lint door answers first (saveMetaItem runs assertRuntimeAuthoringRules before runAuthoringGate — pinned including a body both doors would refuse); the 403 R1 door answers for writes that pass lint. The former a write with NO OWD keys SAVES pin (ADR-0094 absence-defaults-to-private) is overturned by the ruling and re-pinned as the 422 refusal. The former ?mode=draft 403 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.
  4. Honest fixture repairs — no rule weakening: the 13 objectql files (83 tests, all 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 author sharingModel: 'private' on the object bodies they publish, each annotated [#8310].
  5. Crossing pins extended in validate-security-posture.runtime-surface.test.ts: OWD-less object publish refused at the REAL gate; [1 of #7891] METADATA_CREATE_SEEDS.object gains an authored sharingModel — 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-internal when the internal side is orderable; security-owd-unset / security-owd-alias-or-unknown when 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:

  • System objects (isSystem / sys_*) with unset sharingModel + 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), and security-owd-unset deliberately exempts system objects for the same reason. Pinned executable in the runtime-surface suite (the R2-retirement boundary).
  • Draft saves: R2 fired on drafts; the lint discipline defers draft judgment to the draft→active promotion ([runtime/metadata] 作者时规则只存在于 CLI:Studio/REST/MCP 的运行时授权面是第四扇门,26 条规则一条不跑——#4409 修完后最大的敞口 #4463 D1), which is gated — so no defective body reaches 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 403 owd_external_wider arm; rewritten to the new door order. The other drift-bot pages carry no owd_external_wider / R2 prose (grepped content/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.
  • No corpus changes needed: objectstack validate exits 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 ✓
  • Corpus: showcase / CRM / todo objectstack validate exit 0
  • Gates: all families derived by dispatch-gates.mjs on the final diff run green locally (incl. check:nul-bytes, check:i18n, check:adr-anchors, changeset gates); check-adr-merge-approval is CI-credential-bound (local 401) and is the human-merge guard itself
  • Reverse verification (sources reverted to origin/main, new pins kept, direction predicted first): 13 pins red exactly as predicted — 5 lint crossing pins, 2 R2-retirement pins, 6 rest 422-door pins (incl. the door-order pin) — while the R1 pins, legal-pair pins and the package-author carve-out pin stayed green (the ones that must not move). Restored and re-run green.

Acceptance pins (ruling point → executable)

Ruling point Pin
1 authored-OWD-required rest: an OWD-less publish is refused — 422 security-owd-unset; lint: an OWD-less object publish is REFUSED at the real gate
2 honest repairs 16 fixture files author sharingModel, each annotated [#8310]; zero rule edits in validate-security-posture.ts
3 door order rest: door ORDER: when lint AND R1 would both refuse, the 422 lint door answers first; R1 403 pins unchanged
4 R2 retired / R1 stays plugin-security retirement pins; ADR-0094 amendment; shadowing measurement above
5 object declared lint: seed / permission / book / object all cross

Generated by Claude Code

…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
@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 14, 2026 2:05am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/lint, @objectstack/plugin-security.

14 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/automation/hook-bodies.mdx (via @objectstack/lint)
  • content/docs/deployment/cli.mdx (via @objectstack/plugin-security)
  • content/docs/deployment/validating-metadata.mdx (via packages/lint)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/plugin-security)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/plugin-security)
  • content/docs/permissions/access-recipes.mdx (via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx (via @objectstack/lint, @objectstack/plugin-security)
  • content/docs/permissions/explain.mdx (via @objectstack/plugin-security)
  • content/docs/permissions/permissions-matrix.mdx (via packages/plugins/plugin-security)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/plugin-security)
  • content/docs/plugins/index.mdx (via @objectstack/plugin-security)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-security)
  • content/docs/ui/audience-based-interfaces.mdx (via packages/plugins/plugin-security)
  • content/docs/ui/dashboards.mdx (via @objectstack/plugin-security)

2 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-security)
  • content/docs/releases/v17.mdx (via @objectstack/lint)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…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
@github-actions github-actions Bot added size/l and removed size/m labels Aug 14, 2026
claude added 2 commits August 14, 2026 01:11
…prose, changeset

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MNV7ZSCjNfA38eDCjsXQL
@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling labels Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

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 de2dbcc: 27 checks — 25 success, 1 skipped (Console Pin Gate), 1 failure, and the failure is ADR maintainer approval. Its log states the cause precisely:

❌  This change touches docs/adr/ and this PR is not in a mergeable state under the ADR rules.
      • docs/adr/0094-sys-permission-set-pure-projection.md
    The PR's current review standing is not APPROVED.
    No state-setting review (APPROVED / CHANGES_REQUESTED / DISMISSED) has been submitted at all.
    Fix: anyone with review rights on this repo approves the PR; that approval re-runs this check
    via the pull_request_review trigger. This gate does NOT check who approved.

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 qq9340100, which is the author of this PR — GitHub does not accept a self-approval — and this lane's standing discipline is that the PM does not cast the approval vote on an ADR-touching PR in the first place. That is the point of the gate, not an obstacle to route around.

Two ways forward, both the maintainer's:

  1. Approve the PR → the gate re-runs on the pull_request_review trigger and turns green → merge normally; or
  2. Merge directly with admin rights while the gate is red — the route taken earlier tonight for PR docs(adr): anchor the default-active-org session hook to ADR-0093 D9 (#8474) #8529.

Substance is unaffected either way: every test, build, typecheck, lint, dogfood and conformance job on this head is green, including the @objectstack/runtime and qa/dogfood suites that were red in round 1. The review verdict and the R2-ratification question are in issue comment 5288934424.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[3 of #7891] Flip the registration: runtimeTypes gains object + permission/book — whole rule families cross the publish door

3 participants