Skip to content

feat(security): ADR-0091 L2 — delegation of duty (职务代理) - #2810

Merged
os-zhuang merged 3 commits into
mainfrom
feat/adr-0091-l2-delegation
Jul 11, 2026
Merged

feat(security): ADR-0091 L2 — delegation of duty (职务代理)#2810
os-zhuang merged 3 commits into
mainfrom
feat/adr-0091-l2-delegation

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

What

ADR-0091 L2 (delegation half). Builds on the L1 validity substrate: a holder of a delegatable position may self-service hand off their own authority, time-boxed — the one branch of the D12 gate open to a non-administrator.

D3 — the self-service delegation branch

A non-admin (no adminScope, no tenant-superuser wildcard) hitting the D12 gate is normally denied. L2 adds a branch: a sys_user_position insert that stamps delegated_from is judged as a delegation and approved iff every invariant holds:

Rule Enforcement
delegated_from = the writer you may only delegate authority you hold yourself
mandatory valid_until, future, ≤ 30-day ceiling an open-ended delegation is a permanent grant with extra steps
mandatory reason dual-audit substrate
writer holds the position directly (validity-filtered) a grant that itself arrived via delegation is not re-delegatable — chains cut
position is delegatable: true opt-in (spec PositionSchema.delegatable, default false)
position distributes no adminScope-carrying set administration is never self-delegated (D12 containment), fail-closed
insert-only not self-renewable — continuing past expiry needs a fresh delegation, leaving a new audit record

Dual audit: granted_by (writer) + delegated_from (authority source), both stamped/recorded.

Explain (D3 rule 5)

buildContextForUser surfaces delegation provenance; the principal layer attributes a delegated position "via delegation from X, until Y".

Proof (ADR-0054)

position.delegatable is registered as a bound high-risk class with an end-to-end dogfood proof (delegation-of-duty): a gated delegation write over the real HTTP API, then the delegate's grant resolving in-window and dying at valid_until via the real resolveAuthzContext — the L1 filter on the real persisted row. Access dies with no cleanup job.

Tests

Suite Result
delegated-admin-gate (16 new delegation cases) 38/38
explain-engine (provenance) 14/14
spec (parse + proof-registry bindings) 6688/6688
core security 94/94
plugin-security (full) 286/286
dogfood delegation-of-duty 5/5

Liveness gate: bound proof resolves. check:role-word, check:authz-resolver, check-changeset-fixed all pass.

Not in this PR

Break-glass activation workflow and recertification campaigns stay enterprise (D7); their community shapes are the L1 substrate. Early revocation of a delegation is an admin/expiry concern, not a self-service affordance in L2.

🤖 Generated with Claude Code

https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H


Generated by Claude Code

A holder of a delegatable position may hand off their OWN authority,
time-boxed, WITHOUT being an administrator — the one self-service branch
of the D12 gate.

- spec: PositionSchema.delegatable (default false) + sys_position.delegatable
- D12 gate: self-service branch on sys_user_position insert — approves iff
  the row is a well-formed delegation: delegated_from = writer, mandatory
  valid_until (future, within the 30-day ceiling), mandatory reason, and the
  writer holds the position DIRECTLY (validity-filtered; a delegated holding
  is not re-delegatable — chains cut). Insert-only → not self-renewable. A
  delegatable position distributing an adminScope set is rejected fail-closed
  (administration is never self-delegated — D12 containment). Dual audit:
  granted_by (writer) + delegated_from (authority source)
- explain: buildContextForUser surfaces delegation provenance; the principal
  layer attributes a delegated position 'via delegation from X, until Y'
- proof (ADR-0054): position.delegatable is a bound high-risk class with an
  end-to-end dogfood proof — a gated delegation write over the real HTTP API,
  then the delegate's grant resolving in-window and dying at valid_until via
  the real resolver
- docs: authorization.mdx delegation section; ADR-0091 phasing L2 landed

Tests: gate 38 (16 new delegation cases), explain 14, spec 6688, core 94,
plugin-security 286 — all green; dogfood delegation-of-duty 5/5; liveness gate
(bound proof resolves); role-word + authz-resolver guards pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 11, 2026 2:45am

Request Review

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
@os-zhuang
os-zhuang marked this pull request as ready for review July 11, 2026 02:37
@os-zhuang os-zhuang closed this Jul 11, 2026
@os-zhuang os-zhuang reopened this Jul 11, 2026
…gistry conflicts

Both this branch and the merged ADR-0057 lifecycle work (#2791) appended a
HIGH_RISK_CLASSES entry and extended the BOUND_PROOF_PATHS expectation:
kept BOTH ('delegation' → position/delegatable, 'data-lifecycle' →
object/lifecycle). proof-registry tests and the spec-liveness gate pass on
the merged tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BNBzMWmSECrbiEDdVzwBt3
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling size/l labels Jul 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/dogfood, @objectstack/plugin-security, @objectstack/spec.

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

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/access-recipes.mdx (via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx (via packages/dogfood, packages/plugins/plugin-security, @objectstack/spec)
  • content/docs/permissions/delegated-administration.mdx (via packages/dogfood)
  • content/docs/permissions/explain.mdx (via @objectstack/plugin-security)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via packages/plugins/plugin-security, @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/audience-based-interfaces.mdx (via packages/plugins/plugin-security)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)

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 merged commit f3035bd into main Jul 11, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the feat/adr-0091-l2-delegation branch July 11, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants