NK-WP-0054-T02: agent ceiling is 60 minutes; ld-admin is LLDAP-only and admin stays the human's name
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Founder clarifications: the SI-14 token ceiling is 60 minutes (3600 s); ld-admin is for
LLDAP only and the name admin remains the human platform administrator's wherever it
appears. The LLDAP rehearsal is now introducing ld-admin by configuration and demoting
admin, not renaming. The validator rejects a service-admin named admin.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 328925@bnt-lap001
Assistant-Session: 14b795fd-c632-4c01-8d28-e7e490c7b0ed
This commit is contained in:
tegwick 2026-10-24 22:57:23 +02:00
parent ca03da52c6
commit a3bab9210b
6 changed files with 26 additions and 19 deletions

View file

@ -32,7 +32,7 @@ It was started on 2026-10-24 from the founder's direction and from the first inv
(`docs/service-identity-inventory.md`, NK-WP-0054-T01).
- **draft-1** (2026-10-24): thirteen rules, naming, five initial exceptions, seven open questions.
- **draft-2** (2026-10-24): the founder's review answered four questions (§10). Added the `agent` class and
- **draft-2** (2026-10-24): the founder's review answered four questions and two clarifications (§10). Added the `agent` class and
SI-14; SI-8 now requires the assurance claim for admin-policy roles; the human administrator keeps
directory admin rights through group membership; declarations start in this repository and move to each
service. Building the offline validator (NK-WP-0054-T03) also made custody a list and broadened SI-X1.
@ -144,7 +144,7 @@ subject, and MUST record which identity ran each stage.
**SI-14 Agents.** An agent identity MUST present as an agent: its tokens carry `principal_type: agent` and
name the agent's mode, autonomous or delegated (IAM Profile v0.3). It MUST NOT use a human's credential, MUST
have short-lived tokens (this draft proposes a ceiling of 3600 seconds) and MUST be bounded by a named
have short-lived tokens (ceiling 3600 seconds, 60 minutes; decided 2026-10-24) and MUST be bounded by a named
boundary policy. A delegated agent names the delegating actor in its tokens.
## 4. Naming
@ -152,13 +152,15 @@ boundary policy. A delegated agent names the delegating actor in its tokens.
| Class | Pattern | Notes |
| --- | --- | --- |
| `bind` | `svc-<service>` | One per consuming service; `svc-<service>-<function>` if one service needs several |
| `service-admin` | `<short>-admin` | The short form is registered per service (see §9): `pi-admin`; `ld-admin` proposed for LLDAP |
| `service-admin` | `<short>-admin` | A short form belongs to exactly one service (see §9): `pi-admin` for privacyIDEA; `ld-admin` for LLDAP only |
| `break-glass` | `platform-root` | The king credential |
| `human` | the person's own login | `tegwick`, `admin` |
| `workload` | the token subject form already in use | for example `service:secrets-engine`; IAM Profile v0.3 governs the token |
| `agent` | the agent's own subject | for example `service:codex:railiance-platform` today; the tokens must carry `principal_type: agent` (SI-14) |
Names are reserved for their class. A `svc-` or `-admin` name MUST NOT be used for a human account. A
Names are reserved for their class. The name `admin` is the human platform administrator's name wherever it
appears (decided 2026-10-24); no service-admin account is called `admin`. A `svc-` or `-admin` name MUST NOT
be used for a human account. A
federated role that holds no credential (custody `none`), such as an OpenBao role that maps a group to a
policy, is not an account and is not bound by this rule (see §10, question 7).
@ -169,7 +171,7 @@ steps are NK-WP-0054-T05 and T06.
| Service | `service-admin` | `bind` and write identities | Human route |
| --- | --- | --- | --- |
| LLDAP | `ld-admin` (the built-in super-admin, renamed or replaced after rehearsal) | `svc-authelia`, `svc-keycape`, `svc-privacyidea` read-only; a scoped provisioner identity | `admin` with directory admin rights through the admin group, own password and OTP |
| LLDAP | `ld-admin` (the directory's configured super-admin, for LLDAP only; `admin` stays the human's account) | `svc-authelia`, `svc-keycape`, `svc-privacyidea` read-only; a scoped provisioner identity | `admin` with directory admin rights through the admin group, own password and OTP |
| Authelia | none (LDAP backend only) | uses `svc-authelia` | none |
| privacyIDEA | `pi-admin` | resolver uses `svc-privacyidea` | none (local administrator only: exception) |
| KeyCape | none | uses `svc-keycape` | none |
@ -239,7 +241,7 @@ declarations carry the exceptions the validator can evaluate (SI-X1, SI-X3, SI-X
must match; that reconciliation is part of ratification.
- **Crisis custody list** (`docs/crisis-custody-list.md`) is the recovery companion to SI-9 and SI-12.
- The registry of `<short>-admin` forms lives with the declarations (T03) and starts with
`pi-admin` and the proposed `ld-admin`.
`pi-admin` and `ld-admin`; each form belongs to one service.
## 10. Decisions and open items
@ -249,20 +251,23 @@ declarations carry the exceptions the validator can evaluate (SI-X1, SI-X3, SI-X
2. The human administrator keeps directory admin rights through an administrative group on their own
account (SI-5); the service-admin account is a sealed fallback.
3. Declarations start in this repository and move to each service repository as owners confirm them (§6).
4. Agents get their own class, with SI-14.
4. Agents get their own class, with SI-14, and the token-lifetime ceiling is 60 minutes (3600 seconds).
5. `ld-admin` is for LLDAP only. `admin` stays the human's account on every service, including LLDAP, where the
directory's configured super-admin becomes `ld-admin` and `admin` keeps its administrative rights through
an admin group on its own password and OTP.
**Settled unless the founder objects:** 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 (§4).
**To be rehearsed in isolation, not decided:**
- Renaming LLDAP's built-in admin to `ld-admin` on an existing directory (NK-WP-0054-T06).
- Introducing `ld-admin` as the configured super-admin on an existing directory and demoting `admin` to an
administrative-group member with its own password. This replaces the earlier idea of renaming (NK-WP-0054-T06).
- The provisioner's narrowest working privilege against the pinned LLDAP image (T05).
- Whether a read-only bind account can be prevented from signing in interactively. If not, SI-3's
"unable to sign in" becomes "has a long random password that nobody uses and a read-only group".
**Open:** the ceiling of 3600 seconds in SI-14 is a proposal; the right figure comes from the existing
agent roles (15 minutes today).
**Open:** nothing is open beyond the rehearsals and the owners' review.
## 11. Adoption

View file

@ -34,7 +34,7 @@ and more than one break-glass identity.
SI-1, SI-2, SI-3 (including a credential shared by more than one service), SI-6, SI-8 (including an
admin policy without a bound assurance claim), SI-9, SI-11 (overdue legacy disposition), SI-12, SI-14
(an agent must present as an agent, with a token lifetime at or below the proposed 3600-second ceiling) and
(an agent must present as an agent, with a token lifetime at or below the 3600-second, 60-minute ceiling) and
the naming rules (`NAMING`). SI-4 (one admin per service) is an advisory. SI-5, SI-7, SI-10 and SI-13 are
not decidable from a declaration. Observed state (what is really configured) is the health check,
NK-WP-0054-T04.

View file

@ -29,7 +29,7 @@ identities:
recovery: {needed: true, works_with_sso_down: false, in_crisis_list: true}
- name: ld-admin
classes: [service-admin]
purpose: "Proposed: LLDAP's own administrator, separate from every bind and every person (renaming needs a rehearsal)"
purpose: "LLDAP only: the directory's configured super-admin, separate from every bind and every person; introduced by configuration after a rehearsal"
privilege_level: admin
interactive_login: true
second_factor: unknown

View file

@ -131,6 +131,7 @@ class RuleTests(unittest.TestCase):
admin = dict(classes=["service-admin"], privilege_level="admin", second_factor="required", interactive_login=True,
consumers=[{"name": "p", "kind": "person"}], custody=["personal-safe"])
self.assertIn("NAMING", self.rules(name="administrator", **admin))
self.assertIn("NAMING", self.rules(name="admin", **admin)) # `admin` is the human's name everywhere
self.assertEqual(self.rules(name="ld-admin", **admin), [])
def test_overdue_legacy_disposition_is_a_violation(self):

View file

@ -40,7 +40,7 @@ SECRET_VALUE = re.compile(
BIND_NAME = re.compile(r"^svc-[a-z0-9]+(-[a-z0-9]+)*$")
ADMIN_NAME = re.compile(r"^[a-z]{2,6}-admin$")
AGENT_MAX_TTL_SECONDS = 3600 # draft-2 proposal (standard section 10); the figure is not settled
AGENT_MAX_TTL_SECONDS = 3600 # 60 minutes, decided 2026-10-24 (standard SI-14)
ORDER = {"non-conformant": 0, "unknown": 1, "excepted": 2, "planned": 3, "conformant": 4}

View file

@ -96,7 +96,7 @@ Profile v0.3, Credential Management v0.2 and the Security Zones standard.
Draft-2 (2026-10-24, after the founder's review): decisions applied are OpenBao `platform-admin` binds
`aal2`; the human administrator keeps directory admin rights through an admin group; declarations start here
and move to the services; agents get their own class and rule SI-14. Rehearsals still to do (not decisions):
renaming LLDAP's built-in admin, the provisioner's narrowest scope, and whether a bind account can be kept
introducing `ld-admin` (LLDAP only) as the configured super-admin and demoting `admin`, the provisioner's narrowest scope, and whether a bind account can be kept
from signing in interactively. Finding F-1: the coding-agent role in OpenBao presents as a service against
IAM Profile v0.3. Draft-1 was delivered earlier the same day: `canon/standards/service-identity-privilege_v0.1.md` (proposed). Thirteen
rules (SI-1 to SI-13), naming, a target shape for today's services, the declaration fields, the
@ -174,9 +174,10 @@ Create `svc-authelia`, `svc-keycape` and `svc-privacyidea` as read-only director
narrowly scoped provisioner account that can create users and groups without being the
directory super-admin (the inventory found these four consumers beside the human; the
narrowest working privilege for the provisioner must be tested against the pinned LLDAP image
first). Per the founder's decision the human `admin` keeps directory admin rights through an admin group
on its own account; because today's `admin` is also LLDAP's built-in super-admin, the migration must state
which of the two accounts keeps the name `admin` and rehearse it before any change. Switch the Authelia, KeyCape and privacyIDEA resolver configurations and the
first). Per the founder's decisions the human `admin` keeps its name and its administrative rights through an admin
group on its own password and OTP, and `ld-admin` is LLDAP's configured super-admin only. The migration
therefore introduces `ld-admin` by configuration on the existing directory and demotes `admin`; this is
rehearsed in isolation before any change. Switch the Authelia, KeyCape and privacyIDEA resolver configurations and the
provisioner to them, make `admin`'s password
human-only and rotate it, and remove the shared secret from the service Secrets. Update
the backup profile, the restore adapters (`isolated-lldap.py`, `isolated-authelia.py`,
@ -205,8 +206,8 @@ state_hub_task_id: "8072b5cf-4161-58b9-8dfc-62fa102ccd16"
For each service decide whether a dedicated admin account exists and what it is called:
LLDAP (`ld-admin`), privacyIDEA (`pi-admin`, existing), Authelia, KeyCape (client
registry), OpenBao (the `platform-admin` role) and others. Record the result in the
inventory and the standard. LLDAP's built-in admin name is configurable but renaming it
on an existing directory is untested here, so it needs a rehearsal before any decision. Also rehearse
inventory and the standard. `ld-admin` is for LLDAP only; `admin` stays the human's name on every service. Introducing `ld-admin` as the
configured super-admin on an existing directory is untested here, so it needs a rehearsal first. Also rehearse
whether a read-only bind account can be kept from signing in interactively (SI-3).
**Done when:** every service has a recorded disposition and a custody location.