diff --git a/canon/standards/service-identity-privilege_v0.1.md b/canon/standards/service-identity-privilege_v0.1.md index ab3455d..bb67aab 100644 --- a/canon/standards/service-identity-privilege_v0.1.md +++ b/canon/standards/service-identity-privilege_v0.1.md @@ -8,7 +8,7 @@ version: "0.1" created: "2026-10-24" updated: "2026-10-24" scope: service-account-governance -revision: "draft-3" +revision: "draft-4" owner: net-kingdom last_reviewed: "2026-10-24" review_interval: 3m @@ -30,9 +30,9 @@ related: ## 0. Status -**Proposed, draft-3. Approved in principle by the founder on 2026-10-24.** It binds nothing until it is ratified -as v0.1 and each owner adopts it. Ratification awaits two owner replies: railiance-platform (finding F-1 and the -`aal2` binding, exceptions SI-X4 and F-1) and security-canon (confirmation of the mode readings in §3). +**Proposed, draft-4 (draft-3 approved in principle by the founder on 2026-10-24).** It binds nothing until it is ratified +as v0.1 and each owner adopts it. Both owner replies are in (§10); ratification as v0.1 awaits the founder's decision on the corrections they +produced. - **draft-1** (2026-10-24): thirteen rules, naming, five initial exceptions, seven open questions. - **draft-2** (2026-10-24): the founder's review decided six points (§10), added the agent class and SI-14. @@ -43,6 +43,10 @@ as v0.1 and each owner adopts it. Ratification awaits two owner replies: railian rules it profiles and states only what NetKingdom adds. New: the estate identities in canon terms (§3) and SI-15, accountable automation. All founder decisions and every rule id from draft-2 are kept. +- **draft-4** (2026-10-24): applies the owner replies. security-canon confirmed all five mode readings and found + citation errors (§4, §8), now corrected; railiance-platform prepared the F-1 and `aal2` role changes (source only); + key-cape, glas-harness and state-hub assessed the agent-identity and attribution gaps (§10). No decision changed. + The offline validator (`tools/service-identity`) implements draft-3 (principal type and grants, NK-WP-0054-T03b). The live health check (T04) does not exist yet. @@ -55,8 +59,9 @@ It is a **profile**, not a second rulebook. Per SecurityCanon SEC-ADR-001, the i InfoTechCanon and security concept definitions to SecurityCanon; NetKingdom holds the security architecture and standards of record for the estate. So this standard: -- **imports** the vocabulary: `principal_type` (InfoTechCanon, via SecurityCanon) and the Mode of Authority - grant notation with its dimensions (SecurityCanon, draft 0.2.0); +- **imports** the vocabulary: `principal_type` as classified by SecurityCanon over the InfoTechCanon Principal + (the canon itself words its ownership two ways; open as SECURITY-IN-0001) and the Mode of Authority grant + notation with its dimensions (SecurityCanon, draft 0.2.0); - **profiles** the DevOps Secrets Management Standard (`SEC-DSM` 1.0.0): it names the rules that apply to NetKingdom accounts and, where NetKingdom is stricter, says so; - **adds** only what is estate-specific: which identities exist, their names, the declarations, the link to @@ -68,7 +73,8 @@ Out of scope: tokens (IAM Profile v0.3), custody procedure (Credential Managemen ## 2. Vocabulary (imported) **Principal type** (`principal_type`): `HUMAN`, `WORKLOAD`, `SERVICE`, `AGENT`, `CONTROLLER`, `DEVICE`. IAM -Profile v0.3 carries the same distinction in tokens in lower case. +Profile v0.3 carries the same distinction in tokens in lower case. `Environment` is cited as a Mode of Authority +dimension without naming an owner, because the canon names two. **Authority grant:** `MODE @ SCOPE`, where the mode is one of `USE`, `OBSERVE`, `OPERATE`, `ADMINISTER`, `GOVERN`, `CONSTRUCT`, `SOVEREIGN`. A grant may state `activation` (`STANDING`, `JUST_IN_TIME`, `SCHEDULED`, @@ -86,7 +92,7 @@ Estate conventions, which are names for recurring grant shapes and not new canon | Bind account `svc-` | a `SERVICE` principal with `USE @ directory`, read-only operations, one consumer | | Service-admin account `-admin` | an account held by a `HUMAN`, `ADMINISTER @ ` | | Break-glass | any grant with `activation = BREAK_GLASS` | -| Agent | an `AGENT` principal with `relation = DELEGATED` and the person it acts for as authority context | +| Agent | an `AGENT` principal with `relation = DELEGATED` and the person it acts for as `authority_context` | Draft-2's classes map as follows: `human` → `HUMAN`; `break-glass` → `activation = BREAK_GLASS`; `bind` and `infrastructure` → `SERVICE` with the matching grant; `service-admin` → the convention above; `workload` → @@ -98,11 +104,11 @@ The founder's model, written in canon terms. This is what the declarations must | Account | Principal | Grants | Activation | Environment | | --- | --- | --- | --- | --- | -| `platform-root` | `HUMAN` | `SOVEREIGN @ platform`; `CONSTRUCT @ platform` (build mode) | `BREAK_GLASS` in production; standing only outside it | `RECOVERY`; `DEVELOPMENT` and `TEST` for build mode, never `PRODUCTION` | +| `platform-root` | `HUMAN` | `SOVEREIGN @ platform`; `CONSTRUCT @ platform` (build mode), a separate grant | `BREAK_GLASS` for `SOVEREIGN`; standing for `CONSTRUCT` | `SOVEREIGN`: `PRODUCTION`, and `RECOVERY` for restored environments; `CONSTRUCT`: `DEVELOPMENT` and `TEST` only, never `PRODUCTION` | | `admin` | `HUMAN` | `OPERATE @ platform`; `OPERATE @ backup-system`; `ADMINISTER @ directory` through an admin group | `STANDING` | `PRODUCTION` | | `tegwick` | `HUMAN` | `CONSTRUCT @ product` | `STANDING` | `DEVELOPMENT`, `TEST` | | `ld-admin` | account held by a `HUMAN` | `ADMINISTER @ lldap` | `BREAK_GLASS` (sealed fallback) | `PRODUCTION` | -| `pi-admin` | account held by a `HUMAN` | `ADMINISTER @ privacyidea` | `STANDING` (exception SI-X5: only a local admin exists) | `PRODUCTION` | +| `pi-admin` | account held by a `HUMAN` | `ADMINISTER @ privacyidea`; `GOVERN @ privacyidea` (its policy `pi-admin-all-rights` can set the policies that bound other admins) | `STANDING` (exception SI-X5: only a local admin exists) | `PRODUCTION` | | `svc-authelia`, `svc-keycape`, `svc-privacyidea` | `SERVICE` | `USE @ directory`, read-only | `STANDING` | `PRODUCTION` | | provisioner account | `SERVICE` | `ADMINISTER @ directory/people,groups`, narrowest working scope | `STANDING` | `PRODUCTION` | | Claude Code, Codex, Grok sessions | `AGENT` | what the tools they can reach allow (SI-14) | per task | that of the person they act for | @@ -110,69 +116,99 @@ The founder's model, written in canon terms. This is what the declarations must `backup operator → OPERATE @ backup-system` and `developer → CONSTRUCT @ product` are the canon's own translations, and match the founder's intent that `admin` operates backups and `tegwick` builds. +Readings confirmed by security-canon on 2026-10-24 (its review, `docs/netkingdom-service-identity-review.md`): +`USE @ directory` for a bind, `SOVEREIGN` with `BREAK_GLASS` for `platform-root` (the canon's vocabulary card has the +same shape), `ADMINISTER` for a local admin (the canon's own example is "break-glass admin → ADMINISTER, +activation=BREAK_GLASS"), and `OPERATE @ backup-system` for `admin`. Notes: `SOVEREIGN @ platform` does not imply +sovereignty over realms nested inside it, so recovering OpenBao, LLDAP or the identity realm is its own scope. The +canon flags `GOVERN` plus `CONSTRUCT` on one actor as a finding, and is silent on `SOVEREIGN` plus `CONSTRUCT`; +the two grants are kept separate and split by environment. Whether break-glass use of production is +`PRODUCTION` or `RECOVERY` is open in the canon (SECURITY-IN-0002); the direct form is used here. + ## 4. Rules -Each rule keeps its draft-2 id. **Profiles** names the SEC-DSM rules it applies; **NetKingdom adds** states -what is stricter or estate-specific. Where nothing is added, the SEC-DSM rule governs as written. +Each rule keeps its draft-2 id. **Canon** names the SEC-DSM rules it rests on, with their strength: *MUST* and +*MUST NOT* bind; *SHOULD* guides. **NetKingdom adds** states what is stricter or estate-specific. A NetKingdom +MUST that rests on a canon SHOULD is said to do so. security-canon checked these references on 2026-10-24 +(`docs/netkingdom-service-identity-review.md` in that repository). -**SI-1 One account, one principal type, one purpose.** Profiles DSM-ID-004, DSM-AP-003. NetKingdom adds: an -account presented by a `HUMAN` and by a `SERVICE` is non-conformant, whatever its privileges. +**SI-1 One account, one principal type, one purpose.** Canon: DSM-ID-004 (MUST: human and machine credentials are +distinguishable). DSM-AP-003 (shared production account) is an anti-pattern and is cited only as an illustration. +NetKingdom adds: an account presented by a `HUMAN` and by a `SERVICE` is non-conformant, whatever its privileges. -**SI-2 People and services never share a credential.** Profiles DSM-ID-004 (MUST). NetKingdom adds: a human's -password MUST NOT be stored where a service reads it, including a Kubernetes Secret. +**SI-2 People and services never share a credential.** Canon: DSM-ID-004 (MUST NOT: human credentials embedded in +automated workloads; SHOULD NOT: machine credentials used interactively). NetKingdom adds: the stronger "never +share", and that a human's password is not stored where a service reads it, including a Kubernetes Secret. -**SI-3 Bind accounts.** Profiles DSM-ID-001 and DSM-AUTH-001. NetKingdom adds: DSM-ID-001's SHOULD becomes MUST. -Each consuming service has its own bind account with read-only `USE @ directory`, never used interactively. A -service that must write gets its own `SERVICE` account with the narrowest working `ADMINISTER` scope, never the -service-admin account. +**SI-3 Bind accounts.** Canon: DSM-ID-001 (SHOULD: each workload its own identifiable identity; MUST NOT: depend on +a shared generic credential where individual identity is practical) and DSM-AUTH-001 (MUST: least authority). +NetKingdom adds: the SHOULD becomes MUST, so each consuming service has its own bind account with read-only +`USE @ directory`; and "never used interactively" strengthens DSM-ID-004's SHOULD NOT. A service that must write gets +its own `SERVICE` account with the narrowest working `ADMINISTER` scope, never the service-admin account. -**SI-4 One local admin per service.** Profiles DSM-AUTH-001. NetKingdom adds: the account is named -`-admin`, the short form belongs to that one service, and its grant is `ADMINISTER @ that service` only. +**SI-4 One local admin per service.** Canon: DSM-AUTH-001 (MUST) supports limiting the grant to that one service. +NetKingdom adds: one local admin account per service, named `-admin`, whose grant is `ADMINISTER @ that +service` and, where the service has a single admin tier, `GOVERN @ that service`. Nothing in the canon requires the +single account or the naming. -**SI-5 Attributed administration first.** Profiles DSM-AUDIT-003 and the reduction of standing authority (SEC-DSM -§4.12). NetKingdom adds: day-to-day administration uses the administrator's own `HUMAN` account through group +**SI-5 Attributed administration first.** Canon: DSM-AUDIT-003 (SHOULD: audit records identify the principal) and +the objective of reducing standing authority (SEC-DSM section 4.12, a statement of objective). NetKingdom adds, as a +MUST resting on those: day-to-day administration uses the administrator's own `HUMAN` account through group membership. The local service-admin account is a sealed fallback listed in the crisis custody list. -**SI-6 Break-glass is an activation.** Profiles DSM-HUM-003, DSM-ROOT-001 to DSM-ROOT-005. NetKingdom adds: -`platform-root` holds `SOVEREIGN @ platform` with `activation = BREAK_GLASS` in production, held offline. It -authorizes and does not operate, and it is never used for routine work, validation or as a drill's test -subject. Its `CONSTRUCT` authority (build mode) is not available in `PRODUCTION`. +**SI-6 Break-glass is an activation.** Canon: DSM-HUM-003 (MUST: break-glass is exceptional, attributable, auditable, +time-bounded where practical); DSM-ROOT-001, -003, -004 (MUST); DSM-ROOT-002, -005 are SHOULD. NetKingdom adds: +`platform-root` holds `SOVEREIGN @ platform` with `activation = BREAK_GLASS` in production, held offline; it +authorizes and does not operate; it is never used for routine work, validation or as a drill's test subject; its +`CONSTRUCT` authority (build mode) is not available in `PRODUCTION`. DSM-ROOT-003 itself requires only that root +credentials not travel through ordinary application delivery. -**SI-7 The developer identity.** Profiles DSM-AP-012. NetKingdom adds: `tegwick` holds `CONSTRUCT @ product` in -`DEVELOPMENT` and `TEST`, no production credential and no recovery custody item. +**SI-7 The developer identity.** Canon: DSM-AP-012 (an anti-pattern: developers routinely holding production +secrets) illustrates the risk; it is not a rule. NetKingdom adds, as its own MUST: `tegwick` holds `CONSTRUCT @ +product` in `DEVELOPMENT` and `TEST`, no production credential and no recovery custody item. -**SI-8 Assurance.** NetKingdom rule, with IAM Profile v0.3 assurance claims. Every `HUMAN` account and every -service-admin account requires a second factor where the service can enforce one. A role that grants -`ADMINISTER` or higher MUST bind the assurance claim itself (for example `aal2` in an OpenBao role); relying on an -upstream check needs an exception. Decided 2026-10-24 for OpenBao `platform-admin`. +**SI-8 Assurance.** NetKingdom rule, using IAM Profile v0.3 assurance claims. Every `HUMAN` account and every +service-admin account requires a second factor where the service can enforce one. A role that grants `ADMINISTER` or +higher MUST bind the assurance claim itself (for example `aal2` in an OpenBao role); relying on an upstream check +needs an exception. Decided 2026-10-24 for OpenBao `platform-admin`. -**SI-9 Every place a credential lives is declared.** Profiles DSM-INV-002, DSM-STORE-002. NetKingdom adds: a -person's password safe MUST NOT hold a `SERVICE`, `WORKLOAD` or `AGENT` credential. +**SI-9 Every place a credential lives is declared.** Canon: DSM-INV-001 (MUST: maintain an inventory of +security-significant persistent credentials); DSM-INV-002 (SHOULD: attributes; it has no location field) and +DSM-STORE-002 (SHOULD: minimize copies). NetKingdom adds: declaring every storage place, and that a person's +password safe MUST NOT hold a `SERVICE`, `WORKLOAD` or `AGENT` credential. -**SI-10 Owner, rotation and coupling.** Profiles DSM-INV-003, DSM-ROT-001, DSM-ROT-003; static binds are governed -residual secrets under DSM-ARCH-002 and DSM-TRANS-002. NetKingdom adds: the coupling (everything that must change -together) is part of the declaration. +**SI-10 Owner, rotation and coupling.** Canon: DSM-INV-003, DSM-ROT-001, DSM-ARCH-002 and DSM-TRANS-002 (MUST); +DSM-ROT-003 (MUST NOT consider rotation complete until adopted) is the basis of coupling. NetKingdom adds: +declaring the coupling. Static binds are governed residual secrets (exception SI-X2). -**SI-11 Declared or it is a finding.** Profiles DSM-INV-005 to DSM-INV-007. NetKingdom adds: an account that exists -and is not declared is `unknown`; a legacy account has a disposition with owner and date. +**SI-11 Declared or it is a finding.** Canon: DSM-INV-006 (MUST treat a discovered, unowned production credential as +a finding); DSM-INV-005 and -007 are SHOULD. NetKingdom adds, stricter: every account that exists and is not +declared is `unknown`, and `unknown` is itself a conformance result. A legacy account has a disposition with owner +and date. -**SI-12 Recovery identities are in the crisis custody list.** Profiles DSM-ROOT-001, DSM-ROOT-004. NetKingdom adds: -each recovery item answers "does it work with SSO and OpenBao down?". An account that cannot be used while its +**SI-12 Recovery identities are in the crisis custody list.** Canon: DSM-ROOT-001 and -004 (MUST). NetKingdom adds: +each recovery item answers "does it work with SSO and OpenBao down?", and an account that cannot be used while its own service is down is never the only recovery path. -**SI-13 Validation is operated by the operator identity.** NetKingdom rule. Restore drills and backup validation -are `OPERATE @ backup-system`, run by `admin` with `admin`'s own token as the test subject, and record which -identity ran each stage. +**SI-13 Validation is operated by the operator identity.** NetKingdom rule. Restore drills and backup validation are +`OPERATE @ backup-system`, run by `admin` with `admin`'s own token as the test subject, and record which identity ran +each stage. -**SI-14 Agents.** Profiles DSM-AGENT-001 to DSM-AGENT-008, DSM-AP-016, DSM-AP-017 and the companion §7. -NetKingdom adds: an agent presents as `AGENT` with its mode (IAM Profile v0.3); its tokens last at most 60 -minutes (3600 seconds; decided 2026-10-24); it is bounded by a named boundary policy; and its **effective -authority includes everything reachable through its tools** (DSM-AGENT-008). An agent running in a person's -terminal therefore holds that person's tool-reachable authority, and declarations say so. +**SI-14 Agents.** Canon: DSM-AGENT-001, -004, -006, -007, -008 (MUST or MUST NOT); DSM-AGENT-002, -003, -005 are +SHOULD; DSM-AP-016 and -017. DSM treats an agent as a kind of workload identity; mapping it to the `AGENT` principal +type is NetKingdom's reading. NetKingdom adds: an agent presents as `AGENT` with its mode (IAM Profile v0.3); its +tokens last at most 60 minutes (3600 seconds, decided 2026-10-24; DSM-AGENT-003 only says "short"); it is bounded by +a named boundary policy; and its **effective authority includes everything reachable through its tools** +(DSM-AGENT-008). **Scope:** the rule can be met in full only for sessions that a harness launches (glas-harness, +GLAS-WP-0018). An interactive Claude Code, Codex or Grok terminal stays at the person's tool-reachable authority +until a session contract exists, and declarations say so (§10). -**SI-15 Accountable automation.** Profiles DSM-AUDIT-001, DSM-AUDIT-003, DSM-DX-002 and companion §7.4. Every -state-changing action by an `AGENT` or `WORKLOAD` is reconstructable: actor, on whose authority, run or session, -operation, result and where the evidence is kept. High-impact actions follow the NetKingdom golden path: +**SI-15 Accountable automation.** Canon: DSM-AUDIT-001 binds the secrets or capability authority and not every +action of an agent, and DSM-AUDIT-003 is a SHOULD; DSM-DX-002 (SHOULD: reusable integrations) is only the generic +basis for having a golden path. The reconstructability claim and the path below are NetKingdom's, resting on the +companion's section 7 ("every action is reconstructable as the caller's action"). Every state-changing action by an +`AGENT` or `WORKLOAD` is reconstructable: actor, on whose authority, run or session, operation, result and where the +evidence is kept. High-impact actions follow the NetKingdom golden path: 1. **Prepare.** The agent writes source-reviewed tooling and tests it on synthetic fixtures. No live effect. 2. **Admit.** A person authorizes the exact action: a signed admission or a recorded decision. @@ -181,8 +217,8 @@ operation, result and where the evidence is kept. High-impact actions follow the 5. **Retain.** The receipt is kept by hash, with no secret values. Evidence available today: commit trailers (`Assistant`, `Assistant-Session`, `Assistant-Process`), safe receipts -with source hashes, signed admissions, and State Hub progress events. Hub authorship is a free-text field that -nothing authenticates; that is a declared gap (§10). +with source hashes, signed admissions, and State Hub progress events. Hub authorship is unauthenticated free text; the +design to attribute it is STATE-WP-0100 (§10). ## 5. Naming @@ -222,27 +258,33 @@ The offline validator decides from a declaration alone: SI-1, SI-2, SI-3, SI-4, SI-12, SI-14 and naming; more than one service-admin account per service is an advisory. SI-5, SI-10, SI-13 and SI-15 are process rules, checked by evidence rather than by declaration. Dates are explicit (`--as-of`). -The health check (T04) is SEC-DSM's automated discovery (DSM-INV-004) applied to accounts. It compares declared -against observed state from owner-provided read-only metadata and repository manifests. It MUST NOT read a Secret. +The health check (T04) is SEC-DSM's automated discovery (DSM-INV-004, a SHOULD) applied to accounts. It compares +declared against observed state from owner-provided read-only metadata and repository manifests. It MUST NOT read a +Secret; that rule is NetKingdom's and is compatible with DSM-AUDIT-002. Its findings are proposals routed to the owner through Posture Feedback, with an evidence-freshness bound. It changes nothing. ## 8. Exceptions Exceptions follow DSM-EXC-001 to DSM-EXC-004: explicit, recorded (rule, account, reason, owner, compensating -control), expiring or revalidated, and carrying an **elimination path**: what change ends the exception. +control), expiring or revalidated. DSM-EXC-002 accepts an elimination path *or* a review trigger; NetKingdom requires +the **elimination path** (what change ends the exception), which is stricter and consistent with DSM-EXC-004. +DSM-EXC-001 binds violations of a canon MUST; an exception against a rule that is only NetKingdom's is NetKingdom's own. | Id | Rules | Account | Reason | Elimination path | | --- | --- | --- | --- | --- | | SI-X1 | SI-1, SI-2, SI-3, SI-4, SI-9, naming | LLDAP `admin` | The human, the super-admin and the shared bind of four services in one account; password in a person's safe and a Kubernetes Secret | NK-WP-0054-T05: `svc-*` binds, provisioner account, `ld-admin`, `admin` human-only | | SI-X2 | SI-10 | LDAP bind accounts | Static long-lived credential; LDAP has no lease | Governed residual secret (DSM-TRANS-002) until a federated directory lookup exists | | SI-X3 | naming, SI-11 | `trigger-admin` (privacyIDEA) | Legacy account, consumers uninventoried | NK-WP-0049-T22 disposition | -| SI-X4 | SI-8 | OpenBao `netkingdom-platform-admin` | Role binds the group claim only | railiance-platform binds `aal2` (decided 2026-10-24) | +| SI-X4 | SI-8 | OpenBao `netkingdom-platform-admin` | Role binds the group claim only | railiance-platform binds `aal2` (decided 2026-10-24); prepared in source as RPF-WP-0065, applied by a founder-run live step | | SI-X5 | SI-4, SI-5 | privacyIDEA | Only a local administrator is supported | Upstream support for attributed administrators | **Findings at adoption, not excepted:** F-1, the OpenBao coding-agent role binds `principal_type: service`, so the -agent presents as a service against IAM Profile v0.3 (SI-14). It stays non-conformant until railiance-platform -changes the role or records an exception with a compensating control. +agent presents as a service against IAM Profile v0.3 (SI-14). railiance-platform has prepared, in source only, +a transitional role that accepts both `service` and `agent`, plus an exception record with compensating controls, +the removal condition and a review date of 2026-12-31 (RPF-WP-0065). KeyCape must first emit `principal_type: agent` +(KEY-WP-0043), because flipping the role alone would lock the agent out. The account stays non-conformant until the +owner accepts that exception or the issuer and role change land. ## 9. Relationship to other documents @@ -278,16 +320,32 @@ through an admin group (§3). Ratification as v0.1 follows the owner replies nam **Settled with draft-3 (not objected to in review):** KeyCape's confidential clients are governed by IAM Profile v0.3 plus a declaration; the reserved-name rule applies to credential-holding accounts, not to federated roles. -**New in draft-3, for the founder and the canon owners:** +**Open in the estate, with the plan that eliminates each gap:** -- The mode readings in §3 are NetKingdom's. In particular: is a directory lookup `USE @ directory` (the directory's - purpose) rather than `OBSERVE`? The SecurityCanon owner should confirm. - **Hub authorship is unauthenticated.** Progress events and decisions carry a free-text `author`. For SI-15 they need an attributable actor and session, as commits already have. - **Agents act under the person's ambient authority.** There is no per-run agent identity yet (DSM-AGENT-002). Until there is, each agent session's effective authority is the person's tool-reachable authority, and that is a declared gap, not conformance. +**Owner replies, 2026-10-24** (all documentary; none applied anything live): + +| Owner | Result | Plan | +| --- | --- | --- | +| security-canon | All five mode readings confirmed; citation errors found and corrected in §4, §8 | SECURITY-IN-0001 (ownership wording), SECURITY-IN-0002 (four canon questions) | +| railiance-platform | F-1 and `aal2` prepared in source, rollback written; nothing applied | RPF-WP-0065; the `aal2` live step is the founder's | +| key-cape | Agent tokens are feasible **with changes**, not today. Autonomous agents: `client_credentials` with a new agent client class (2 to 3 days). Delegated agents: RFC 8693 token exchange (1 to 1.5 weeks). Missing: `principal_type` `agent`, the `agent{id,mode}` claim, `act.sub`. Risks: revocation state is in memory; client registrations are static | KEY-WP-0043 | +| glas-harness | Per-session identity and attribution are feasible **only for sessions the harness launches**. Interactive terminals stay outside | GLAS-WP-0018 | +| state-hub | Option A recommended: record `X-Actor-*` headers in an append-only attribution table, labelled `claimed`, `unattributed` or `legacy`; real authentication needs key-cape tokens (Option C) | STATE-WP-0100; five founder decisions in its design | + +**Needs an amendment:** IAM Profile v0.3 asks for assurance evidence for "any delegated human authority" but defines no +nested claim for it. Delegated agent tokens need one; it belongs in the IAM Profile v0.4 amendments. + +**Open canon questions** (security-canon, SECURITY-IN-0002): whether break-glass use of production is `PRODUCTION` or +`RECOVERY`; whether one actor may hold `SOVEREIGN` and `CONSTRUCT` separated by environment; whether a sealed offline +credential is a `HUMAN` principal or a credential held by a human; and the ownership wording of `principal_type` and +`Environment`. + **To be rehearsed in isolation, not decided:** introducing `ld-admin` as the configured super-admin and demoting `admin` (T06); the provisioner's narrowest scope (T05); whether a bind account can be kept from signing in interactively (SI-3). diff --git a/history/2026-10-24-security-identity-and-agent-review.md b/history/2026-10-24-security-identity-and-agent-review.md index e87727d..f5b7fb6 100644 --- a/history/2026-10-24-security-identity-and-agent-review.md +++ b/history/2026-10-24-security-identity-and-agent-review.md @@ -70,3 +70,28 @@ roster template, and `docs/crisis-custody-list.md` now lists custody items. They | Confirm the mode readings in the standard §3, in particular `USE @ directory` for binds | security-canon | | Converge the custody roster template with the crisis custody list | net-kingdom | | Confirm which instruction file Grok reads; if not `AGENTS.md`, point it there | founder | + +## Outcome of the owner workers (same day) + +Six worker agents, one per repository, were started on the founder's instruction and told to prepare, assess or +review only: no live changes, no secrets, no pushes, local commits. Each report was checked against its repository +before being relied on. All work is local and unpushed. + +| Repo | Commits | Result | +| --- | --- | --- | +| security-canon | 5aa0a64, f844b15 | Five mode readings confirmed. Citation errors found and corrected in the standard (SI-1/7 cited anti-patterns, SI-5 rests on a SHOULD, SI-9 should cite DSM-INV-001, SI-15 goes beyond DSM-AUDIT-001). Four canon questions recorded (SECURITY-IN-0002) | +| railiance-platform | 2126457, bca66d1 | F-1 and aal2 prepared in source (`["service","agent"]` transitional; `/assurance/level: aal2`), rollback written, 7 tests. KeyCape must emit `agent` first. Nothing applied | +| key-cape | 3acc86f, 7190f5d | Agent tokens feasible with changes. `client_credentials` agent class 2 to 3 days; delegated agents need RFC 8693 token exchange, 1 to 1.5 weeks | +| glas-harness | b386b79, 8faa14a | Per-session identity and attribution feasible only for sessions the harness launches | +| state-hub | 0789f9b | Design: Option A, `X-Actor-*` into an append-only attribution table, labelled claimed/unattributed/legacy | +| emergent-security | 8c903af | Start card 0.2.7 live. An agent re-reviewed 12 sources and resealed it; a human has not reviewed it | + +**Process observation.** The emergent-security refresh followed that repository's own procedure, which needs no human +signature, yet the card steers every agent session on the machine. The standard's SI-15 asks that agents prepare and +people accept. The founder is asked to accept or withdraw the card. + +**Delegation limits that worked.** Telling workers to prepare rather than apply kept the one risky change +(role bindings on a live login path) in source with a written rollback. A worker also declined to run +`fix-consistency` where it would have touched another job's uncommitted files. + +Draft-4 of the standard applies the security-canon corrections and records the others; no founder decision changed. diff --git a/tools/service-identity/README.md b/tools/service-identity/README.md index 9735d6f..790db26 100644 --- a/tools/service-identity/README.md +++ b/tools/service-identity/README.md @@ -39,7 +39,7 @@ Draft-3 of the standard is an estate profile of SecurityCanon. Each account decl fact is not established and is reported as a finding. Exceptions carry an `elimination_path` (DSM-EXC-004). Decided from a declaration: SI-1, SI-2, SI-3 (including a credential shared by more than one service), SI-4 -(a service-admin holds `ADMINISTER` over one service only), SI-6 (`SOVEREIGN` is offline and break-glass in +(a service-admin holds `ADMINISTER`, and `GOVERN` where the service has one admin tier, over one service only), SI-6 (`SOVEREIGN` is offline and break-glass in production), SI-7 (`CONSTRUCT` never in production), SI-8 (second factor; admin roles bind the assurance claim), SI-9, SI-11 (overdue legacy disposition), SI-12, SI-14 (an agent presents as an agent, tokens at most 3600 seconds) and naming. More than one service-admin account per service is an advisory. SI-5, SI-10, SI-13 and diff --git a/tools/service-identity/declarations/privacyidea.yaml b/tools/service-identity/declarations/privacyidea.yaml index e32877e..7c9f510 100644 --- a/tools/service-identity/declarations/privacyidea.yaml +++ b/tools/service-identity/declarations/privacyidea.yaml @@ -12,7 +12,9 @@ identities: principal_type: HUMAN conventions: [service-admin] purpose: "privacyIDEA's local administrator; policy pi-admin-all-rights restricted to adminuser=pi-admin" - grants: [{mode: ADMINISTER, scope: privacyidea, activation: STANDING, environments: [PRODUCTION]}] + grants: + - {mode: ADMINISTER, scope: privacyidea, activation: STANDING, environments: [PRODUCTION]} + - {mode: GOVERN, scope: privacyidea, activation: STANDING, environments: [PRODUCTION], note: "pi-admin-all-rights can set the policies that bound other admins"} interactive_login: true second_factor: unknown custody: [personal-safe] diff --git a/tools/service-identity/tests/test_validate.py b/tools/service-identity/tests/test_validate.py index fccf676..e080da3 100644 --- a/tools/service-identity/tests/test_validate.py +++ b/tools/service-identity/tests/test_validate.py @@ -124,6 +124,9 @@ class RuleTests(unittest.TestCase): def test_si4_service_admin_holds_administer_over_one_service(self): self.assertEqual(self.rules(**HUMAN_ADMIN), []) self.assertIn("SI-4", self.rules(**{**HUMAN_ADMIN, "grants": [grant("ADMINISTER"), grant("USE")]})) + # GOVERN over the same service is allowed (a single admin tier can set the policies that bound other admins). + self.assertEqual(self.rules(**{**HUMAN_ADMIN, "grants": [grant("ADMINISTER"), grant("GOVERN")]}), []) + self.assertIn("SI-4", self.rules(**{**HUMAN_ADMIN, "grants": [grant("ADMINISTER"), grant("GOVERN", "other")]})) self.assertIn("SI-4", self.rules(**{**HUMAN_ADMIN, "grants": [grant("ADMINISTER", "a"), grant("ADMINISTER", "b")]})) def test_si6_sovereign_is_offline_and_break_glass_in_production(self): diff --git a/tools/service-identity/validate.py b/tools/service-identity/validate.py index 1c463eb..7c3d5dc 100644 --- a/tools/service-identity/validate.py +++ b/tools/service-identity/validate.py @@ -131,9 +131,9 @@ def _violations(identity: dict[str, Any]) -> tuple[set[str], list[str]]: reads_only = all(g["mode"] == "USE" and g.get("read_only") is True for g in grants) if principal != "SERVICE" or not reads_only or identity["interactive_login"] or persons or len(services) != 1: broken.add("SI-3") - # SI-4 a service-admin account holds ADMINISTER over one service only. + # SI-4 a service-admin account holds ADMINISTER, and GOVERN where the service has one admin tier, over one service only. if "service-admin" in conventions: - if {g["mode"] for g in grants} - {"ADMINISTER", "unknown"} or len({g["scope"] for g in grants}) != 1: + if {g["mode"] for g in grants} - {"ADMINISTER", "GOVERN", "unknown"} or len({g["scope"] for g in grants}) != 1: broken.add("SI-4") # SI-6 SOVEREIGN is offline and break-glass in production; break-glass serves no automation. for grant in grants: diff --git a/workplans/NK-WP-0054-service-identity-policy.md b/workplans/NK-WP-0054-service-identity-policy.md index 9f24aec..5ad4eed 100644 --- a/workplans/NK-WP-0054-service-identity-policy.md +++ b/workplans/NK-WP-0054-service-identity-policy.md @@ -77,8 +77,9 @@ status: wait priority: high assignee: claude-code depends_on: [NK-WP-0054-T01] -blocked_on: message-from:railiance-platform -blocking_reason: "Founder approved draft-3 in principle on 2026-10-24. Ratification as v0.1 awaits replies from railiance-platform (hub message 8da287e2: F-1 and the aal2 binding) and security-canon (28998f18: mode readings)." +needs_human: true +decision_id: "c926a190-8614-40b8-a20f-b017ef728db2" +blocking_reason: "Both owner replies are in (security-canon, railiance-platform). Draft-4 applies them. Await the founder's ratification of v0.1 and answers to the post-review choices in the decision." state_hub_task_id: "5830e2eb-334a-52fa-9c55-a8c00d89c09f" ``` @@ -97,6 +98,12 @@ confirmed, approved in principle. What remains for **done** is the owners' side: security-canon replies (the other four hub messages, to state-hub, key-cape, glas-harness and emergent-security, are recommendations and do not gate ratification). On their replies, set the standard's status to accepted and close T02. +Owner replies received 2026-10-24: security-canon confirmed all five mode readings and corrected the SEC-DSM +citations; railiance-platform prepared F-1 and the aal2 binding in source (RPF-WP-0065, nothing applied); key-cape, +glas-harness and state-hub assessed the agent and attribution gaps (KEY-WP-0043, GLAS-WP-0018, STATE-WP-0100). +Draft-4 of the standard applies all of it without changing a founder decision. What remains for T02 is ratification: +set the status to accepted when the founder decides. + Draft-3 (2026-10-24): realigned as an estate profile of SecurityCanon after a review against the canon (`history/2026-10-24-security-identity-and-agent-review.md`): imported vocabulary, SEC-DSM references per rule, estate identities in canon terms, new SI-15 (accountable automation). Validator migration is T03b.