Skip to content

feat(security): enforce OWD posture on the runtime write path (#3050) + flip 10 verified ADR statuses - #3052

Merged
os-zhuang merged 2 commits into
mainfrom
claude/auth-model-design-eval-xxgzcl
Jul 16, 2026
Merged

feat(security): enforce OWD posture on the runtime write path (#3050) + flip 10 verified ADR statuses#3052
os-zhuang merged 2 commits into
mainfrom
claude/auth-model-design-eval-xxgzcl

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Two commits, both follow-ups from the #2557 re-evaluation session:

1. OWD posture authoring gate — closes#3050

The two OWD posture rules were CLI-lint-only (validateSecurityPosture runs at os compile/os lint, never on saveMetaItem), leaving the runtime write path unguarded (ADR-0049 violation):

  • With OS_METADATA_WRITABLE=object, an environment overlay could widen a packaged object's sharingModel from private to public_read_write with zero validation.
  • externalSharingModel ≤ sharingModel (ADR-0090 D11) existed only as .describe() prose + a lint rule — never enforced at runtime.

Fix, at the right layers:

  • metadata-protocol — implements the ADR-0094-addendum registerAuthoringGate(type, gate) seam: an awaited, throwing pre-persistence hook inside saveMetaItem (after the ADR-0005 overlay/runtime-create authorization and spec validation; both draft and publish-mode saves; environment writes only). publishMetaItem promotes an already-gated draft body, so no second gate.
  • plugin-security — registers the object posture gate (object-posture-gate.ts, feature-detected like the ADR-0094 projector wiring):
    • R1 env-tighten-only (ADR-0086 D1): an env overlay of an artifact-backed object may not set sharingModel/externalSharingModel wider than the packaged declaration → 403 owd_widening_forbidden with a fix-it pointing at the package publish pipeline (ADR-0090 D7).
    • R2 external ≤ internal (ADR-0090 D11) on every runtime object write → 403 owd_external_wider.
  • Write-path only: no zod refine — stored/grandfathered metadata keeps loading unchanged (the ADR-0090 D1 lesson). controlled_by_parent excluded from ordering on either side, mirroring lint's OWD_WIDTH.

Tests: 6 new seam-contract tests (mutation-listeners.test.ts — dispatch, plural normalization, throw propagation, artifact-baseline resolution, replace-on-reregister) + 18 posture-gate unit tests. Full metadata-protocol suite (29) and plugin-security targeted suites green; ESLint clean. Changeset included (minor × 2).

2. ADR status hygiene — flip 10 verified-implemented Proposed ADRs

Continuation of #3032, same per-decision code+test verification method as the ADR-0086 re-evaluation:

  • → Accepted with one-line landing evidence: 0047, 0049, 0053, 0056, 0058, 0062, 0066, 0068, 0081.
  • 0057 (ERP authz) → Accepted in part: D1–D3/D8 landed (scope depth, BU tree, conformance); D4–D7 sys_role/role_and_subordinates decisions superseded by ADR-0090 D3/ADR-0095 (flat positions, rollup on the BU tree) — its own implementation-status table predates that supersession.
  • 0025 stays Proposed with an honest partial note: build/sign/publish CLI landed, install flow + sys_plugin_* registry missing.
  • 0056's status also flags its addendum's stale D6 claim (RoleGraphService never shipped).

Notes for reviewers

  • The gate deliberately does NOT fire for control-plane bootstrap writes (environmentId === undefined) — that channel is the package author's own, mirroring the existing ADR-0005 gate scoping.
  • Protocols predating registerAuthoringGate (minimal embeddings, unit-test stubs) keep legacy behavior — CLI lint remains their only guard, same fallback stance as ADR-0094's projector.

Closes#3050.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits July 16, 2026 11:47
…write path (#3050)
Implements the ADR-0094-addendum registerAuthoringGate seam — an awaited,
THROWING pre-persistence hook in saveMetaItem (draft + publish-mode saves,
environment writes only; control-plane bootstrap bypasses like the ADR-0005
gate) — and registers plugin-security's object posture gate on it:
- R1 env-tighten-only (ADR-0086 D1, ADR-0049): an environment overlay of a
packaged object may not widen sharingModel/externalSharingModel beyond the
packaged declaration. Closes the OS_METADATA_WRITABLE=object hole where the
escape hatch admitted unvalidated OWD widening (private ->
public_read_write) with zero checks.
- R2 external<=internal (ADR-0090 D11): previously .describe() prose + CLI
lint only; now rejected at save time on every runtime authoring surface.
Write-path only: no zod refine, stored/grandfathered metadata keeps loading
(the ADR-0090 D1 lesson). controlled_by_parent excluded from ordering on
either side, mirroring lint's OWD_WIDTH. publishMetaItem promotes an
already-gated draft body, so no second gate. Protocols predating the seam
keep legacy behavior (feature-detected wiring).
Tests: authoring-gate seam contract (metadata-protocol, 6 new) + posture gate
unit suite (plugin-security, 18).
…notate 0057/0025
Per-decision code+test verification (2026-07-16 audit, same method as the
ADR-0086 re-evaluation): 0047, 0049, 0053, 0056, 0058, 0062, 0066, 0068,
0081 flip to Accepted with one-line landing evidence. 0057 (ERP authz)
becomes Accepted-in-part: D1-D3/D8 landed, D4-D7 sys_role/role-hierarchy
decisions superseded by ADR-0090 D3/ADR-0095 positions. 0025 stays Proposed
with an honest partial-implementation note (install flow + sys_plugin_*
registry missing). 0056's status notes its addendum's stale D6
RoleGraphService claim.
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 16, 2026 12:02pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/l labels Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

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

  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/metadata-protocol)
  • content/docs/getting-started/cli.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/access-recipes.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx(via packages/plugins/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/releases/implementation-status.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)

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.

@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 12:34
@os-zhuang
os-zhuang merged commit 7f9a795 into mainJul 16, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/auth-model-design-eval-xxgzcl branch July 16, 2026 12:34
os-zhuang pushed a commit that referenced this pull request Jul 16, 2026
…partial/cloud-owned ADRs
Per-decision code+test verification (same method as #3052's round 1) of the
14 remaining medium/low-density Proposed ADRs:
- Flip to Accepted: 0037 (Live Canvas — all four phases landed incl.
preview-evaluator + objectui surfaces), 0065 (SDUI styling — envelope,
scoped-styles compiler + 4-property test, token lint; cloud half noted).
- Honest partial notes, keep Proposed: 0080 (save-time compile->store not
wired), 0078 (core shared completeness predicate + lint absent), 0052
(context decomposition undone), 0067 (Decision-2 turn-atomicity missing),
0022 (Slack channel->connector delegation unbuilt), 0051 (render side
absent), 0076 (D3 unbuilt, D12 runtime enforcement missing), 0061 (Tier 1
claim verified TRUE; own conformance bar unmet), 0028 (NOT STARTED).
- Cloud-owned banners verified accurate, framework slices noted: 0038, 0063,
0064 (service-ai genuinely absent from framework).
os-zhuang added a commit that referenced this pull request Jul 16, 2026
…atus verification (#3061)
* docs(permissions): document the runtime OWD posture gate (#3050) in the governance section
* docs(adr): round-2 status verification — flip 0037/0065, annotate 12 partial/cloud-owned ADRs
Per-decision code+test verification (same method as #3052's round 1) of the
14 remaining medium/low-density Proposed ADRs:
- Flip to Accepted: 0037 (Live Canvas — all four phases landed incl.
preview-evaluator + objectui surfaces), 0065 (SDUI styling — envelope,
scoped-styles compiler + 4-property test, token lint; cloud half noted).
- Honest partial notes, keep Proposed: 0080 (save-time compile->store not
wired), 0078 (core shared completeness predicate + lint absent), 0052
(context decomposition undone), 0067 (Decision-2 turn-atomicity missing),
0022 (Slack channel->connector delegation unbuilt), 0051 (render side
absent), 0076 (D3 unbuilt, D12 runtime enforcement missing), 0061 (Tier 1
claim verified TRUE; own conformance bar unmet), 0028 (NOT STARTED).
- Cloud-owned banners verified accurate, framework slices noted: 0038, 0063,
0064 (service-ai genuinely absent from framework).
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

2 participants

@os-zhuang@claude