Skip to content

feat(iam): let Default users create Agents in the default Namespace and own what they create (RFC-0026 slice 1) - #4231

Open
mrunalp wants to merge 8 commits into
mainfrom
feat/default-users-agent-grants
Open

mrunalp wants to merge 8 commits into
mainfrom
feat/default-users-agent-grants

Conversation

@mrunalp

@mrunalp mrunalp commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Every OCE capability starts with an Installation administrator. Only an administrator can create Namespaces, Agents, and Secrets for other people, and only an administrator can give an Agent's ServicePrincipal operate on its Secrets and credential sources (MEMBER_GRANT_REFUSED). RFC-0026 proposes Default users who create Agents in a shared default Namespace, with creators owning what they create. This PR implements its first slice (TASK-0050 slice 1).

This revision follows the RFC-0026 design update discussed on #4207. Members create Agents in default by default. Creating Namespaces is an opt-in Installation setting. Every creator owns what it creates. The Namespace limit was removed and moved to a separate quota RFC.

Change

  • Built-in IAM rows (migration 0066_default_users).
    • Four immutable Installation-level Roles: Agent Creator (create on Agents, Configurations, Secrets, and credential sources; read on the Namespace and Presets), Namespace Creator (namespace:create), Owner (every Namespace action plus namespace:delete), and Namespace member (Owner without namespace:delete). They match BUILT_IN_ROLES in packages/contracts.
    • The Default users Group.
    • iam_access_bindings_built_in_role_shape limits each built-in Role to one binding shape:
      • Agent Creator binds only Default users, Namespace-wide in one Namespace.
      • Namespace Creator binds only Default users, Installation-wide.
      • Owner binds one identity: Namespace-wide, or to an exact resource that is not a Namespace.
      • Namespace member binds only Namespace-wide.
    • The migration binds Default users to Agent Creator in an existing Namespace named default. A trigger makes that binding immutable.
    • An Installation Group can now be bound inside a Namespace (DB trigger, native IAM validation, and PostgreSQL state validation).
    • Group memberships become deletable; updates stay rejected.
  • Default Namespace. When OCC creates the Namespace named default (Installation bootstrap), it also writes the Agent Creator binding for Default users, audited with reason: default_namespace.
  • Creators own what they create. Creating a Namespace, Agent, Configuration, Secret, credential source, Preset, or ServiceAccount binds the creator to the Owner Role in the same transaction. The binding is Namespace-wide for a Namespace and exact for any other resource. Its ID is binding_owner_<resource-id>, audited with reason: creator. Guided provisioning binds the requester to its Agent and Configuration. This also applies to administrators and ServiceAccounts.
  • Namespace create setting. The Installation configuration field defaultUser.namespaceCreate (false when absent) controls the Namespace Creator binding. OCC writes or deletes it at API startup and right after Installation bootstrap, with the Installation as the actor and reason: installation_configuration.
  • IAM Driver contract.
    • New optional members listGroupMembers, addGroupMember, removeGroupMember, createOwnerBinding, and setDefaultUsersBinding, and the optional parentAgentId on authorize requests.
    • Matching IAMPolicyRepository methods, including createBuiltInBinding and deleteBuiltInBinding.
    • Implemented for the native Driver and PostgreSQL.
    • OCC writes built-in bindings only when the native IAM Driver reads policy from OCC's own State. In-memory State and other policy stores get no Owner bindings instead of failing. A Driver that has the members but does not join the platform transaction returns 503.
    • RFC-0026 (RFC-0026: Default users sign in through identity provider mappings and own their Namespaces #4207) covers the contract change.
  • Default users API. GET, PUT, and DELETE /iam/default-users/{principalId}, for Installation administrators. Each write is audited with groupId, principalId, and changed. Removal stops new creates and keeps everything the person created.
  • Parent checks. AuthorizationRequest gains an optional parentAgentId for agent_revision and sandbox_policy checks, so an owner can read the revisions, deployment status, and sandbox policy of its own Agent. OCC takes the Agent from stored state, or from the route where the later lookup accepts only that Agent's revision, and derives a sandbox policy's parent from its ID (the database ties it to the Agent ID). The native Driver then matches an exact binding on that Agent, and identity access coverage counts those permissions. This moved here from slice 2.
  • Deploy-time grants. When the built-in Owner or Namespace member Role is among the Roles that allow the caller agent:deploy, deploy writes the Agent ServicePrincipal's missing exact operate grants, in the deploy transaction, audited with reason: agent_deploy. It writes a grant only for each Secret or credential source the Agent references where a built-in Role also allows the caller operate; in default, that is a source the caller owns. Deploys allowed only by custom Roles write nothing and are refused as before.
  • Removed from the earlier revision: the per-creator Namespace limit, its lock and 409, namespaces.created_by and Namespace.createdBy (the Owner binding replaces them), and the "Default User" Role. The Namespace create refusal text is the same as on main again.
  • Docs.
    • Reference page docs/reference/authorization/default-users.md, rewritten for the new design.
    • Guide task "Let people create Agents" in docs/guides/topics/iam.md.
    • Updates to the authorization, configuration, Namespaces, and IAM Driver references, the permissions and database cheat sheets, and the namespace-iam-policy flow.
    • Regenerated OpenAPI and API reference.

Not in this PR (later slices in TASK-0050):

  • Bindings without a resource and Group subjects through the Namespace policy API.
  • Grant removal.
  • Identity provider mapping rules and sign-in sync.
  • Team Namespaces, and console or CLI support.

Verification

Tested at fb3b5a1c2 unless noted, locally on Fedora with Node 24.22.1, tools pinned by mise.toml, and disposable PostgreSQL databases and k3d clusters from scripts/ci/prepare.mjs.

  • Integration test. tests/integration/postgres-default-users.test.ts (postgres-platform lane) runs the real Fastify app on PostgreSQL with password accounts that sign in.
    • Agent creation in default:
      • The Agent Creator binding exists, and creates are refused before membership.
      • A member creates a Configuration, Secret, and Agent; the test checks the Owner bindings and audits.
      • The member deploys, and the deploy writes and audits the Agent's Secret grant.
      • A second member is refused every read and write on the first member's resources.
      • Namespace create is refused while the setting is off.
      • A deploy allowed only by a custom Role writes no grant.
      • Removal from Default users keeps the member's resources, and the membership audit is checked.
      • Parent checks: the owner reads the revision and its Agent's sandbox policy, and gets the administrator's answer for deployment status (this app runs no worker). The second member is refused all three. A revision of another Agent behind the owner's Agent route is not found, exactly like an unknown ID.
    • defaultUser.namespaceCreate: with the setting on, a member creates and owns a Namespace. A second controller started on the same database with the setting off deletes the binding, audited with the Installation as actor. The running app then refuses new Namespaces, and the member keeps the one they own.
    • With the Owner-binding writes disabled, both tests fail. With OCC passing no parent, the first test fails.
  • Kubernetes, k3d-model lane (real gpt-6.1-sol). New case "production Default user deploys embedded OpenClaw in the default Namespace with owner grants": an account the administrator only added to Default users creates its model Secret, Configuration, and Agent in default and deploys. The helper asserts its Owner bindings and the deploy-written grant and audit. The owner then reads its deployment status (succeeded), and the Agent answers a real model turn.
  • Live dev stack (occ dev up, Kubernetes control plane, at 74d79cc09). Run by hand: an administrator adds two accounts to Default users. Alice creates a Secret, Configuration, and embedded Agent in default and deploys, and the deploy writes the Agent's grant. The Agent answers a real model turn. Bob is refused every read, deploy, delete, and rotate on Alice's resources. Removing Alice stops her creates and keeps her Agent running. Database rows and audit events match. This run found that owners could not read their deployment status, which the parent checks fix.
  • Lanes:
    • postgres-platform: 56 of 56 files pass. The provisioning file passed on its own after its last test fix.
    • postgres-application: 15 of 15.
    • postgres-auth: 23 of 23, including the Playwright browser cases (at dae3172e3).
    • checks-baseline-1: 129 of 129, including the docs-site, docs-length, plugin-installation, and gh-pinned conformance cases. The IAM conformance oracle and generator now include parent checks; with the parent rule removed from the Driver, the seeded differential fails.
    • checks-baseline-2: all files pass.
  • postgres lane (at dae3172e3): passed in full before the last change, which limits built-in binding writes to Drivers that read OCC's State. postgres-migration-compatibility passed again after that change. The canonical-history digests and restore catalogs were measured on PostgreSQL. The populated-upgrade check seeds a default Namespace before 0066, excludes the seeded built-in rows from the data comparison, and asserts that they exist.
  • Updated existing tests. Owner bindings add rows and audit events, so the platform-state, Agent-deletion audit, runtime-logs, provisioning, and bootstrap-failure tests changed. Each keeps its intent. For example, the runtime-logs test removes the administrator's Owner bindings so it still covers the administer path. The IAM conformance invalid-state case now uses a Namespace Group bound in another Namespace, because an Installation Group in a Namespace is now valid.
  • Checks: typecheck, ESLint, pnpm format:check (bun fmt), openapi:check, openapi:lint, check:workspace, docs:check, docs:check-length, and docs:build pass.
  • Docs length: authorization.md (2,496 words) and configuration.md (2,500) are just under the hard limit. Pages in the 1,500–2,500 review band: docs/testing/kubernetes.md (2,483), the namespace-iam-policy flow (2,427), docs/guides/topics/iam.md (2,127), and namespaces.md (1,742). Each covers one coherent topic.

Risks

  • Who can create. Only Installation administrators add Default users. Only OCC binds the built-in Roles. Database constraints fix their binding shapes, and the Namespace policy API and account provisioning refuse them.
  • Shared default Namespace. Members share one Kubernetes namespace and its ResourceQuota. Lists show each member only what they can read, and NetworkPolicies keep Agents apart. OCC has no per-person limit yet; quotas are a separate RFC.
  • Administrators adding themselves. An administrator can add their own account to Default users; the guide states this.
  • More bindings. Every create now writes an Owner binding and an audit event, including creates by administrators.
  • Migration. 0066 inserts seed rows, replaces the binding-scope trigger function, and changes a membership trigger. Migration-history compatibility is updated and tested.
  • Parent checks widen exact Agent bindings. Any exact Agent binding, including a custom Role's, now also applies its Role's agent_revision and sandbox_policy permissions to that Agent's revisions and policy. A Role that should not read revisions must not include that permission.
  • Contract. This changes the IAM Driver contract; RFC-0026 (RFC-0026: Default users sign in through identity provider mappings and own their Namespaces #4207) covers it.

Implement the first RFC-0026 slice. Migration 0065 adds the immutable built-in
Default User, Namespace member, and Namespace owner Roles, the Default users
Group, the built-in binding-shape constraint, deletable Group memberships, and
namespaces.created_by.

Installation administrators add and remove Default users through
/iam/default-users. A member's POST /namespaces counts against
defaultUser.namespaceLimit under a per-creator lock, records createdBy, and
binds the creator as owner before the default Presets. A deploy allowed by a
built-in Namespace Role writes the Agent's missing exact operate grants in the
deploy transaction; deploys allowed only by custom Roles change no grant.

The IAM Driver gains optional Group membership and Namespace owner binding
members (RFC-0026, PR #4207).
@clawsweeper

clawsweeper Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Oct 30, 2026
@clawsweeper

clawsweeper Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

What this changes

This PR adds administrator-managed Default users, owned Namespaces with a creation limit, and automatic Agent credential grants at deployment.

Example: An administrator adds Alice to Default users with namespaceLimit set to 1.

  • Before: Alice cannot create a Namespace or grant her Agent access to its model Secret.
  • After: Alice can create one owned Namespace and deploy an Agent whose exact Secret operate grant OCC creates automatically.

Review scores

Measure Result What it means
Overall readiness 🧂 unranked krab (1/6) Meaningful integration coverage supports the feature, but persistent-authority races block correctness and the required real workflow and existing-state upgrade proof remain incomplete.
Proof confidence 🧂 unranked krab (1/6) Real behavior proof is necessary before merge. See Before merge.
Patch quality 🧂 unranked krab (1/6) Security review found an item that needs attention.

Product

Kind: Feature · Worth it: Needs a maintainer decision · Fix scope: Complete
User problem: Ordinary provisioned users need administrator intervention to create a Namespace and give their Agents access to credentials.
Reason: The first slice has clear user value, but its new permissions, configuration default and delegation lifecycle still require an owner decision on the submitted RFC.

Merge readiness

⛔ Blocked before merge - 10 items remain

Keep this draft open for maintainer triage: it addresses a real capability gap, but two revocation races block merging.

Priority: P2
Reviewed head: 8cb41dc2bdd84a1b29d6800a138394a2f568889e
Owner decision: Required. See Decision needed.

Decision needed

  • Question: Should this slice introduce the proposed owner/member permissions, default Namespace limit of 1, and deploy-time delegation before generated-grant cleanup ships?
  • Recommendation: Agree the common delegation contract first: IAM owners coordinate this slice with RFC-0025: Optional Namespace Agent author role #4045 and explicitly decide permissions, offboarding, the default limit, and cleanup sequencing.
  • Why: The submitted RFC has no recorded direction approval, its default limit remains an open question, and the overlapping Agent Author proposal uses a different assignment model.

Before merge

  • Add real behavior proof - Authority-chain proof required: supplied evidence covers Fastify/PostgreSQL tests with test runtime Drivers, not an installed owner-to-Agent credential workflow or rejection after membership/session revocation before final grant persistence and runtime I/O; provide redacted terminal output or logs covering those scenarios, excluding API keys, IPs and non-public endpoints. After adding proof, update the PR body, then request a new review with @clawsweeper re-review. The PR author or someone with repository write access can request it.
  • Serialize membership removal with Namespace ownership creation (P1) - A Default user can pass namespace:create and then wait in lockCreatedNamespaceCount while an administrator removes their membership. Removal does not take the creator lock, and creation never repeats the create decision after that wait. Once released below the quota, the request inserts the Namespace and owner binding; subsequent Preset checks succeed through that newly created owner Role. Coordinate membership invalidation with creation and reauthorize under that fence before writing ownership.
  • Retain assigning sessions through automatic grant commits (P1) - The new deploy-time grants run through the ordinary deploy handler, which never calls transactIAM or holds the admitted session. If a deploy waits for a Namespace lock and its caller signs out or the session expires, it can resume and persist Agent operate grants because IAM evaluates the Principal's Roles, not that session. Namespace creation's new owner binding has the same gap. Apply the existing session-retention protection to these grant-writing transactions, while keeping channel validation outside the transaction.
  • Correct the membership flow's session-retention claim (P3) - The flow says membership routes do not hold the human session through COMMIT, but both writes call transactHoldingSession, which retains and rechecks the session. Update this statement to match the implemented security boundary so future changes do not rely on a nonexistent exception.
  • Give the Namespace quota refusal a recovery action (P3) - When creation reaches namespaceLimit, the new message reports only the count and limit. Tell the caller to delete an owned Namespace or ask an administrator to raise the limit, as the Namespace reference already explains; this also gives a useful next action when the configured limit is zero.
  • Resolve security concern: Revoked membership can become durable ownership - The resulting owner binding is independent of Default users membership, so later membership checks cannot undo the authority created by the race.
  • Resolve security concern: Session revocation does not fence automatic delegation - Persisted grants authorize the Agent ServicePrincipal independently of the human session, making transaction-time session retention consequential rather than a request-lifetime detail.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.
  • Add data-model compatibility proof - The review found that existing stored data may not work after upgrade. Show that existing data still loads and works with this change.
  • Explain or restore the original intent of Assigning-session lifetime - 0918f66: fix(auth): retain assigning sessions through IAM commits #2311 prevents policy writes from surviving revoked or expired assigning sessions; this PR gives no reason for bypassing that protection in its automatic grant paths.

Findings

  • [P1] Serialize membership removal with Namespace ownership creation — packages/occ/src/index.ts:4758-4759
  • [P1] Retain assigning sessions through automatic grant commits — packages/occ/src/index.ts:10431-10437
  • [P3] Correct the membership flow's session-retention claim — docs/flows/namespace-iam-policy.md:216-218
  • [high] Revoked membership can become durable ownership — packages/occ/src/index.ts:4759
  • [high] Session revocation does not fence automatic delegation — packages/occ/src/index.ts:10431

Provenance

Tests

  • Missing end-to-end proof: Provide an installed Agent workflow showing allowed and nearest-forbidden callers, revocation before grant commit, and credential delivery through the real runtime.
Agent review details

How this fits together

The controller authenticates HTTP callers, asks the selected IAM Driver for permission, and commits Namespace ownership, Agent grants, deployment work, and audit records to PostgreSQL.

flowchart TD
A[Authenticated caller] --> B[Controller HTTP API]
B --> C[Selected IAM Driver]
C --> D[Platform transaction]
D --> E[Namespace ownership and Agent grants]
D --> F[Audit and queued deployment]
F --> G[Worker and runtime Drivers]
Loading

Technical review

Best possible solution:

Extend the existing IAM authority protocol to automatic grants, serialize membership revocation with creation, and settle the shared delegation contract before landing.

Do we have a high-confidence way to reproduce the issue?

Source establishes both races: delay creation on its creator lock while removing membership, or delay an automatic-grant request while revoking its session; neither path reestablishes the missing authority before committing grants.

Is this the best way to solve the issue?

Using existing IAM Roles, repositories and deployment transactions is coherent, but the automatic writers must inherit the existing revocation protections rather than relying on admission-time decisions.

Full review comments:

  • [P1] Serialize membership removal with Namespace ownership creation — packages/occ/src/index.ts:4758-4759
    A Default user can pass namespace:create and then wait in lockCreatedNamespaceCount while an administrator removes their membership. Removal does not take the creator lock, and creation never repeats the create decision after that wait. Once released below the quota, the request inserts the Namespace and owner binding; subsequent Preset checks succeed through that newly created owner Role. Coordinate membership invalidation with creation and reauthorize under that fence before writing ownership.
    Confidence: 0.98
  • [P1] Retain assigning sessions through automatic grant commits — packages/occ/src/index.ts:10431-10437
    The new deploy-time grants run through the ordinary deploy handler, which never calls transactIAM or holds the admitted session. If a deploy waits for a Namespace lock and its caller signs out or the session expires, it can resume and persist Agent operate grants because IAM evaluates the Principal's Roles, not that session. Namespace creation's new owner binding has the same gap. Apply the existing session-retention protection to these grant-writing transactions, while keeping channel validation outside the transaction.
    Confidence: 0.98
  • [P3] Correct the membership flow's session-retention claim — docs/flows/namespace-iam-policy.md:216-218
    The flow says membership routes do not hold the human session through COMMIT, but both writes call transactHoldingSession, which retains and rechecks the session. Update this statement to match the implemented security boundary so future changes do not rely on a nonexistent exception.
    Confidence: 1
  • [P3] Give the Namespace quota refusal a recovery action — packages/occ/src/index.ts:4761-4763
    When creation reaches namespaceLimit, the new message reports only the count and limit. Tell the caller to delete an owned Namespace or ask an administrator to raise the limit, as the Namespace reference already explains; this also gives a useful next action when the configured limit is zero.
    Confidence: 0.96

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 912ae8433eb5.

Provenance checked

  • Namespace ownership and deploy-time delegation changes intended behavior with a stated reason (0e21e6f: Namespace IAM management authorized administrators to create exact-resource grants; the submitted RFC explicitly proposes broader authority only through immutable built-in Roles.)
  • Group membership immutability changes intended behavior with a stated reason (unknown: Path history reaches the checkout boundary, so the introduction rationale is unknown; the baseline trigger rejects deletion, and this PR explicitly permits it for administrator-managed Default users.)
  • Existing Agent operate-grant helper keeps the original intent (8adfd86: Guided provisioning created exact grants before deployment; the helper retains that behavior and now returns created bindings so the new caller can audit them.)
  • Caller denial guidance keeps the original intent (bcddbea: fix(iam): name the missing grant in a caller's own denial #3699 names the missing permission and who can resolve it; the Namespace-create variant now names Default users membership.)
  • Generated API documentation keeps the original intent (9332b76: docs: add complete API examples and interactive explorer #4017 makes route schemas and validated examples authoritative; the generated changes preserve existing operations while adding the new API surface.)

Testing

Proof path: in-process harness.

Security

Needs attention: Automatic ownership and Agent grants can persist beyond the authority that admitted their creation.

Evidence

Security concerns:

  • [high] Revoked membership can become durable ownership — packages/occ/src/index.ts:4759
    The resulting owner binding is independent of Default users membership, so later membership checks cannot undo the authority created by the race.
    Confidence: 0.98
  • [high] Session revocation does not fence automatic delegation — packages/occ/src/index.ts:10431
    Persisted grants authorize the Agent ServicePrincipal independently of the human session, making transaction-time session retention consequential rather than a request-lifetime detail.
    Confidence: 0.98

What I checked:

  • Pinned change and repository policy: Reviewed the introduced merge-base-to-head changes, original behavior, and current-main context. Read the complete root AGENTS.md; no nested AGENTS.md, maintainer-notes directory, or pr-simplify skill was found. Review remained read-only and used no separate reviewer or autoreview helper. (AGENTS.md:1, 8cb41dc2bdd8)
  • Current-main capability gap: Current main authorizes Namespace creation, creates the Namespace and default Presets, and queues reconciliation without granting the creator ownership; automatic deploy-time grants are absent. (packages/occ/src/index.ts:4680, 912ae8433eb5)
  • Membership revocation race: Namespace creation reads granting Roles before acquiring the creator advisory lock; membership removal neither acquires that lock nor invalidates the saved ownership decision before the owner binding is inserted. (packages/occ/src/index.ts:4752, 8cb41dc2bdd8)
  • Automatic grants bypass session retention: Default-user membership writes use transactHoldingSession, but Namespace creation uses an ordinary controller transaction and the deploy handler invokes deployAgentWithAuthorization directly; their new persistent grants therefore lack the session retention applied to existing IAM writes. (packages/occ/src/index.ts:10431, 8cb41dc2bdd8)
  • Existing security intent: fix(auth): retain assigning sessions through IAM commits #2311 established that a revoked or expired assigning session must not leave a policy mutation or success audit; its retained-session mechanism remains available. (docs/flows/namespace-iam-policy.md:67, 0918f660452a)
  • RFC submission and unresolved direction: RFC-0026: Default users sign in through identity provider mappings and own their Namespaces #4207 submits the Driver changes and staged implementation plan, satisfying the submission-before-code requirement. The proposal remains Proposed; kevinlin-openai asks what happens when membership is revoked, without approving the direction.

Likely related people:

  • kevinlin-openai: Raw commit 0e21e6f adds packages/iam/src/index.ts:957 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 0e21e6fa6985; files: packages/iam/src/index.ts)

Labels

Label changes:

  • add P2: This is a substantive, unmerged IAM feature requiring normal-priority design and security review; no current-main outage is established.
  • add merge-risk: 🚨 security-boundary: New persistent ownership and Agent credential grants can commit after membership or assigning-session authority has been revoked.
  • add rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Label justifications:

  • P2: This is a substantive, unmerged IAM feature requiring normal-priority design and security review; no current-main outage is established.
  • merge-risk: 🚨 security-boundary: New persistent ownership and Agent credential grants can commit after membership or assigning-session authority has been revoked.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

Reviewed October 30, 2026, 2:10 PM ET / 18:10 UTC.

@freeqaz

freeqaz commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf).

Heads-up: #4098 landed 0065_selected_repository_set on main, so this PR's 0065 migration now collides with it. It needs the next free number, and migrations/meta/_canonical-history.json needs requalifying after merging main. #2520, #4174, #4231 and #4232 all claim 0065 right now, so whichever lands next takes 0066 and the others move up.

…into feat/default-users-agent-grants

# Conflicts:
#	migrations/meta/_canonical-history.json
#	migrations/meta/_journal.json
#	packages/occ/src/index.ts
…ators owners

Rework the first RFC-0026 slice after the design review on #4207.

Migration 0066 (renumbered after main's 0065) seeds the immutable Agent
Creator, Namespace Creator, Owner, and Namespace member Roles and the
Default users Group, lets an Installation Group be bound inside a
Namespace, and binds Default users to Agent Creator in an existing
default Namespace. OCC writes that binding when it creates the
Namespace named default.

Every create of a Namespace, Agent, Configuration, Secret, credential
source, Preset, or ServiceAccount, and each guided provisioning request,
binds the creator to the Owner Role in the same unit: Namespace-wide for
a Namespace, exact otherwise. Built-in bindings are written only when the
Native IAM Driver reads policy from the controller's own State.

defaultUser.namespaceCreate replaces defaultUser.namespaceLimit: OCC
writes or deletes the Namespace Creator binding at startup and after
bootstrap. The Namespace limit, its lock, and namespaces.created_by are
removed. Deploy-time grants now follow the Owner or Namespace member
Role. The IAM Driver's createNamespaceOwnerBinding becomes
createOwnerBinding and setDefaultUsersBinding.
@mrunalp mrunalp changed the title feat(iam): let Default users create and own Namespaces (RFC-0026 slice 1) feat(iam): let Default users create Agents in the default Namespace and own what they create (RFC-0026 slice 1) Nov 2, 2026
…ep IAM negative controls reachable

Add a k3d-model case where an ordinary account, added only to Default users, creates its model
Secret, Configuration, and Agent in the default Namespace and deploys with no other grant. The
helper asserts the caller's Owner bindings and the deploy-written Agent grant and audit, then the
case runs a real model turn. It runs first so it gets the fresh Installation's default Namespace.

Creators now own what they create, so the scoped caller owns its Secrets and Agent. The actor
Secret negative control now uses an administrator-owned Secret, and the deploy step asserts the
grants the owner's deploy writes instead of a refusal no creator can reach. The PostgreSQL
Default users test keeps the custom-Role refusal.

Also record that an Agent owner cannot yet read its deployment status, and update the Default
users route summaries for the default Namespace design.
…ox policy

RFC-0026 parent checks, moved into the first Default users slice so an owner can follow its own
deploys. AuthorizationRequest gains an optional parentAgentId for agent_revision and
sandbox_policy checks. OCC names the Agent from stored state, or from the route where the later
lookup is scoped to that Agent, and derives a sandbox policy's parent from its ID, which the
database ties to the Agent ID. The native IAM Driver then matches an exact binding on that Agent
and keeps those permissions for identity access coverage.

The PostgreSQL Default users test reads the owner's revision, deployment status, and sandbox
policy, refuses another member, and shows that a revision of another Agent behind the owner's
route is not found. The k3d Default user case reads its real deployment status. The native IAM
reference oracle and occ-read fixtures follow the new matching rule.
…into feat/default-users-agent-grants

# Conflicts:
#	packages/occ/src/index.ts
#	tests/helpers/harness-topology-k3d-real.mjs
…n the fixture lane

Administrators own what they create, so the fixture's deploys now write the Agent
ServicePrincipal's Secret grants instead of being refused first. Assert those grants for the
model and bound Secrets; the PostgreSQL Default users test keeps the custom-Role refusal. Also
keep the Kubernetes testing guide within the length limit after the merge from main.
@mrunalp
mrunalp marked this pull request as ready for review November 3, 2026 00:08
@mrunalp
mrunalp requested a review from a team as a code owner November 3, 2026 00:08

This branch has not been deployed

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

Labels

merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants