NK-WP-0056: founder decisions folded in; runtime split into T11 and T12
Window-scoped write role (CCR-2026-0058 approved as amended), bind self-rotation (pilot step is OPERATE on the one bind; svc-executor-pw dropped), pilot without the PDP gate (not-evaluated), started event plus one receipt per run, rapp Job in sso, owner workplans approved. New tasks: T11 core runner, T12 pilot operations and packaging; T06 depends on T12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 994874@bnt-lap001 Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
This commit is contained in:
parent
c9ab01e23e
commit
cdf0d9bf25
11 changed files with 107 additions and 36 deletions
|
|
@ -353,6 +353,8 @@
|
|||
| task | NK-WP-0056-T08 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T09 | done | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T10 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T11 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| task | NK-WP-0056-T12 | todo | — | workplans/NK-WP-0056-bounded-executor-path.md |
|
||||
| intake | NK-IN-0001 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md |
|
||||
| intake | NK-IN-0002 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md |
|
||||
| intake | NET-IN-0001 | open | — | intakes/intakes.md |
|
||||
|
|
|
|||
|
|
@ -193,6 +193,26 @@ once Railiance declarations exist for it.
|
|||
The receipt adds the outcome per step, check results, whether a revert ran, and the budget used. It
|
||||
never holds a secret value.
|
||||
|
||||
Founder decision 2026-10-31, agreed with audit-core (AUDIT-WP-0018):
|
||||
|
||||
- When the executor consumes the admission, before its first step, it emits a separate
|
||||
`execution.run.started` event, so a run that crashes before its receipt is still detectable.
|
||||
- It then emits one `execution.attribution.receipt` per run:
|
||||
- `target` and `action` at the admission level (`admission:<spec.id>`, `bounded-execution`);
|
||||
- per-step detail in `steps[]`;
|
||||
- `decision_refs` labelled `admission`, `admission_digest` and `approval`.
|
||||
- Envelope ids are `run:<run_id>:started` and `run:<run_id>:receipt`.
|
||||
|
||||
**Policy decision point.** access-engine's gate (FLEX-WP-0040) has two decisions: `start` before
|
||||
consume, and `execute-step` after it. The T06 pilot runs without the gate: its receipt records the
|
||||
gate as `not-evaluated` and claims no allow. Any further admission needs the gate, or an exception
|
||||
the founder records (founder decision 2026-10-31).
|
||||
|
||||
**Credentials during a run.** Write roles exist only during the admitted window: the platform creates
|
||||
them when an admission is approved and deletes them after the receipt (CCR-2026-0058). A directory
|
||||
bind rotates its own password, so no password-manager account is needed (founder decisions
|
||||
2026-10-31).
|
||||
|
||||
## 7. The bind split as admissions
|
||||
|
||||
NK-WP-0056 tagged each step of the 2026-10-30 LLDAP bind split. The examples express them:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ spec:
|
|||
scope: openbao/platform/workloads/net-kingdom/directory-binds/svc-authelia
|
||||
environments: &id001
|
||||
- PRODUCTION
|
||||
- mode: ADMINISTER
|
||||
- mode: OPERATE
|
||||
scope: lldap/people/svc-authelia
|
||||
environments: *id001
|
||||
- mode: OPERATE
|
||||
|
|
@ -49,7 +49,7 @@ spec:
|
|||
plan:
|
||||
source:
|
||||
repo: net-kingdom
|
||||
commit: 43a78907593a
|
||||
commit: c9ab01e23e92
|
||||
files:
|
||||
- path: tools/service-binds/bind-lane.py
|
||||
sha256: 5b31b3567af07bba09530c6d3b0ed8b5c947df22bd13ac0442dc33c0d9b420c0
|
||||
|
|
@ -69,13 +69,13 @@ spec:
|
|||
- kv-advanced
|
||||
revert: restore-kv
|
||||
- id: set-directory
|
||||
operation: lldap.user.set-password-from-kv
|
||||
operation: lldap.user.change-own-password-from-kv
|
||||
target: lldap:svc-authelia
|
||||
consumer: authelia
|
||||
class: delegable
|
||||
mutates: true
|
||||
requires:
|
||||
mode: ADMINISTER
|
||||
mode: OPERATE
|
||||
scope: lldap/people/svc-authelia
|
||||
checks_after:
|
||||
- bind-signs-in
|
||||
|
|
@ -115,13 +115,13 @@ spec:
|
|||
mode: OPERATE
|
||||
scope: openbao/platform/workloads/net-kingdom/directory-binds/svc-authelia
|
||||
- id: restore-directory
|
||||
operation: lldap.user.set-password-from-kv
|
||||
operation: lldap.user.change-own-password-from-kv
|
||||
target: lldap:svc-authelia
|
||||
consumer: authelia
|
||||
class: delegable
|
||||
mutates: true
|
||||
requires:
|
||||
mode: ADMINISTER
|
||||
mode: OPERATE
|
||||
scope: lldap/people/svc-authelia
|
||||
- id: redeliver
|
||||
operation: eso.force-sync
|
||||
|
|
@ -141,7 +141,7 @@ spec:
|
|||
requires:
|
||||
mode: OPERATE
|
||||
scope: k8s/sso/deployment/authelia
|
||||
plan_digest: sha256:47de5fcaa09fdadb4ea501e47f85fc12da5b6ce31b28c2ccad34a25ca9599d0f
|
||||
plan_digest: sha256:36328096076c71ade582173092511be6aee546281ef5edb3c2acaadaf7c9e1fb
|
||||
checks:
|
||||
- id: kv-advanced
|
||||
description: KV svc-authelia has exactly one new version, CAS on the previous one
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ spec:
|
|||
plan:
|
||||
source:
|
||||
repo: net-kingdom
|
||||
commit: 43a78907593a
|
||||
commit: c9ab01e23e92
|
||||
files:
|
||||
- path: sso-mfa/k8s/lldap/bind-split.py
|
||||
sha256: 4decc3bbe65120ff6c4cef5613b9a41a60168ae64ecd4c1380f61a2fcd37b6b3
|
||||
|
|
@ -93,7 +93,7 @@ spec:
|
|||
requires:
|
||||
mode: OPERATE
|
||||
scope: openbao/platform/workloads/net-kingdom/directory-binds
|
||||
plan_digest: sha256:be02f6850b329e2e2262bc720a70f881a146183ff70fb3ac20ae72e3a5ae70e8
|
||||
plan_digest: sha256:139e7b874d8d8ba9419f141bf9e10341a9a0057bb75fa47eee32c2ee19b396ce
|
||||
checks:
|
||||
- id: accounts-read-only
|
||||
description: each account exists in lldap_strict_readonly only and cannot write
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ spec:
|
|||
plan:
|
||||
source:
|
||||
repo: net-kingdom
|
||||
commit: 43a78907593a
|
||||
commit: c9ab01e23e92
|
||||
files:
|
||||
- path: sso-mfa/k8s/lldap/bind-split.py
|
||||
sha256: 4decc3bbe65120ff6c4cef5613b9a41a60168ae64ecd4c1380f61a2fcd37b6b3
|
||||
|
|
@ -73,7 +73,7 @@ spec:
|
|||
scope: k8s/sso
|
||||
checks_after:
|
||||
- split-shape
|
||||
plan_digest: sha256:c07dd58e6581049441d512edb60753bfe7102e3c89ea28d55081141373844d0d
|
||||
plan_digest: sha256:0459999b93bb8aee0dacb1b36ea95d114ac74d0ed775095f3ee5dc2ee66203cd
|
||||
checks:
|
||||
- id: split-shape
|
||||
description: every consumer binds as its own svc- account; no service binds as admin
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ spec:
|
|||
plan:
|
||||
source:
|
||||
repo: net-kingdom
|
||||
commit: 43a78907593a
|
||||
commit: c9ab01e23e92
|
||||
files:
|
||||
- path: sso-mfa/k8s/lldap/bind-split.py
|
||||
sha256: 4decc3bbe65120ff6c4cef5613b9a41a60168ae64ecd4c1380f61a2fcd37b6b3
|
||||
|
|
@ -93,7 +93,7 @@ spec:
|
|||
requires:
|
||||
mode: OPERATE
|
||||
scope: k8s/sso/deployment/lldap
|
||||
plan_digest: sha256:60578e013b23fd3d68fead65956c939cde1eb9230d9f9fdbe1aaa677e8e0de11
|
||||
plan_digest: sha256:5f51601ce96a07da5fa56b5b00c2066c572e3b19a4677b1a16cee3178295cae0
|
||||
checks:
|
||||
- id: ld-admin-administers
|
||||
description: ld-admin signs in and administers; admin keeps lldap_admin membership
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ spec:
|
|||
plan:
|
||||
source:
|
||||
repo: net-kingdom
|
||||
commit: 43a78907593a
|
||||
commit: c9ab01e23e92
|
||||
files:
|
||||
- path: sso-mfa/k8s/lldap/bind-split.py
|
||||
sha256: 4decc3bbe65120ff6c4cef5613b9a41a60168ae64ecd4c1380f61a2fcd37b6b3
|
||||
|
|
@ -104,7 +104,7 @@ spec:
|
|||
requires:
|
||||
mode: OPERATE
|
||||
scope: k8s/sso/deployment/lldap
|
||||
plan_digest: sha256:33063248bed00c84b640a37344a4c9e52285e76cacb68b92d08872cd9b7c77db
|
||||
plan_digest: sha256:139f0ca7564184290c7cb1f6b20bdb9807db98e5609a79083ac6f7aea13bb50c
|
||||
checks:
|
||||
- id: ld-admin-administers
|
||||
description: ld-admin signs in and administers; admin keeps lldap_admin membership
|
||||
|
|
|
|||
|
|
@ -52,17 +52,17 @@ rotation = doc(
|
|||
"Pilot shape for NK-WP-0056-T06: generate a new bind password into OpenBao, set it in LLDAP, let ESO deliver it, restart Authelia, prove sign-in with the synthetic journey; revert on any failed check.",
|
||||
"medium", {"not_before": "2026-11-03T09:00:00Z", "not_after": "2026-11-03T11:00:00Z"},
|
||||
[{"mode": "OPERATE", "scope": KV, "environments": P},
|
||||
{"mode": "ADMINISTER", "scope": "lldap/people/svc-authelia", "environments": P},
|
||||
{"mode": "OPERATE", "scope": "lldap/people/svc-authelia", "environments": P},
|
||||
{"mode": "OPERATE", "scope": "k8s/sso/externalsecret/authelia-secrets", "environments": P},
|
||||
{"mode": "OPERATE", "scope": "k8s/sso/deployment/authelia", "environments": P}],
|
||||
{"unit": "consumer", "consumers": ["authelia"], "max_concurrent": 1},
|
||||
[LANE, JOURNEY],
|
||||
[step("generate", "openbao.kv.write-next-version", "openbao:" + KV[len("openbao/"):], "authelia", "delegable", True, "OPERATE", KV, ["kv-advanced"], "restore-kv"),
|
||||
step("set-directory", "lldap.user.set-password-from-kv", "lldap:svc-authelia", "authelia", "delegable", True, "ADMINISTER", "lldap/people/svc-authelia", ["bind-signs-in"], "restore-directory"),
|
||||
step("set-directory", "lldap.user.change-own-password-from-kv", "lldap:svc-authelia", "authelia", "delegable", True, "OPERATE", "lldap/people/svc-authelia", ["bind-signs-in"], "restore-directory"),
|
||||
step("deliver", "eso.force-sync", "k8s:sso/externalsecret/authelia-secrets", "authelia", "delegable", True, "OPERATE", "k8s/sso/externalsecret/authelia-secrets", ["eso-synced"], "redeliver"),
|
||||
step("restart", "k8s.rollout-restart", "k8s:sso/deployment/authelia", "authelia", "delegable", True, "OPERATE", "k8s/sso/deployment/authelia", ["synthetic-journey"], "restart-again")],
|
||||
[step("restore-kv", "openbao.kv.write-previous-value-as-next-version", "openbao:" + KV[len("openbao/"):], "authelia", "delegable", True, "OPERATE", KV),
|
||||
step("restore-directory", "lldap.user.set-password-from-kv", "lldap:svc-authelia", "authelia", "delegable", True, "ADMINISTER", "lldap/people/svc-authelia"),
|
||||
step("restore-directory", "lldap.user.change-own-password-from-kv", "lldap:svc-authelia", "authelia", "delegable", True, "OPERATE", "lldap/people/svc-authelia"),
|
||||
step("redeliver", "eso.force-sync", "k8s:sso/externalsecret/authelia-secrets", "authelia", "delegable", True, "OPERATE", "k8s/sso/externalsecret/authelia-secrets"),
|
||||
step("restart-again", "k8s.rollout-restart", "k8s:sso/deployment/authelia", "authelia", "delegable", True, "OPERATE", "k8s/sso/deployment/authelia")],
|
||||
[check("kv-advanced", "KV svc-authelia has exactly one new version, CAS on the previous one", LANE, 30),
|
||||
|
|
|
|||
|
|
@ -95,7 +95,10 @@ class RuleTests(unittest.TestCase):
|
|||
{"mode": "GOVERN", "scope": "lldap", "environments": ["PRODUCTION"]}))))
|
||||
# whole-directory ADMINISTER for a delegable step at medium risk
|
||||
def widen(s):
|
||||
s["scope_ceiling"][1]["scope"] = "lldap"
|
||||
s["scope_ceiling"][1].update(mode="ADMINISTER", scope="lldap")
|
||||
for step in s["plan"]["steps"] + s["plan"]["revert_steps"]:
|
||||
if step["requires"]["scope"].startswith("lldap/"):
|
||||
step["requires"]["mode"] = "ADMINISTER"
|
||||
self.assertIn("BEA-5", rules(mutate(ROTATION, widen)))
|
||||
|
||||
def test_bea6_least_privilege(self):
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ identities:
|
|||
principal_type: WORKLOAD
|
||||
conventions: [executor]
|
||||
executor_subject: "service:nk-bind-executor"
|
||||
purpose: "OpenBao Kubernetes-auth role for sso/nk-bind-executor: write the next version of the svc-authelia bind (CAS) and read it for checks; lane shape pending secrets-engine and railiance-platform answers (T02)"
|
||||
purpose: "OpenBao Kubernetes-auth role for sso/nk-bind-executor (CCR-2026-0058, approved, window-scoped): write the next version of the svc-authelia bind (CAS) and read it; holding the current value is what lets the executor change the bind's own password in LLDAP"
|
||||
grants:
|
||||
- {mode: OPERATE, scope: openbao/platform/workloads/net-kingdom/directory-binds/svc-authelia, activation: APPROVED, environments: [PRODUCTION], note: "KV data read and CAS write; 15 min TTL"}
|
||||
- {mode: OPERATE, scope: openbao/platform/workloads/net-kingdom/directory-binds/svc-authelia, activation: APPROVED, environments: [PRODUCTION], note: "KV data read and CAS write; 15 min TTL; role exists only in the admitted window (CCR-2026-0058)"}
|
||||
- {mode: OPERATE, scope: lldap/people/svc-authelia, activation: APPROVED, environments: [PRODUCTION], note: "self-rotation: signs in as the bind with the KV value and changes its own password (hub 3d0c8f86)"}
|
||||
interactive_login: false
|
||||
second_factor: not_applicable
|
||||
custody: [openbao-lease]
|
||||
|
|
@ -41,20 +42,6 @@ identities:
|
|||
owner: "railiance-platform (OpenBao role) for NetKingdom"
|
||||
rotation: {path: "OpenBao lease per run; no standing secret", coupling: [bounded-executor]}
|
||||
status: planned
|
||||
- name: svc-executor-pw
|
||||
principal_type: SERVICE
|
||||
conventions: [executor]
|
||||
executor_subject: "service:nk-bind-executor"
|
||||
purpose: "LLDAP account in lldap_password_manager: set svc-authelia's password from KV. LLDAP cannot narrow it to one account (it can reset any non-admin user); each admission narrows it to the accounts it names"
|
||||
grants:
|
||||
- {mode: ADMINISTER, scope: lldap/people, activation: APPROVED, environments: [PRODUCTION], note: "lldap_password_manager; admission ceiling narrows to lldap/people/<account>"}
|
||||
interactive_login: false
|
||||
second_factor: not_applicable
|
||||
custody: [openbao-lease]
|
||||
consumers: [{name: bounded-executor, kind: service}]
|
||||
owner: "NetKingdom directory and User Engine owners"
|
||||
rotation: {path: "Its own password held in OpenBao; lane shape pending secrets-engine (T02)", coupling: [bounded-executor]}
|
||||
status: planned
|
||||
- name: svc-executor-read
|
||||
principal_type: SERVICE
|
||||
conventions: [bind]
|
||||
|
|
|
|||
|
|
@ -121,6 +121,18 @@ NetKingdom proved on the pinned LLDAP; audit-core holds receipts plus a `run.sta
|
|||
creates the rapp, the image is built in net-kingdom, one Job per admission; glas-harness: agent executors after
|
||||
GLAS-WP-0018-T04.
|
||||
|
||||
**2026-10-31, founder decisions after the answers** (hub c29c6eda, 3d0c8f86, 19afd15e):
|
||||
|
||||
- The executor's OpenBao write role is window-scoped. CCR-2026-0058 was amended, approved and pushed.
|
||||
- The bind rotates its own password, so `svc-executor-pw` is dropped and RPF-WP-0069-T06 is cancelled.
|
||||
- The pilot runs without the policy gate (`not-evaluated`); later admissions need the gate or a recorded exception.
|
||||
- Packaging is `rapp-bounded-executor`, one Job per admission in `sso`, with the image built in net-kingdom.
|
||||
- Receipts are a started event plus one receipt per run.
|
||||
- These owner workplans are approved: APPROVAL-WP-0007, FLEX-WP-0040, SECRETS-WP-0017, RPF-WP-0069, AUDIT-WP-0018 and
|
||||
GLAS-WP-0018. glas-harness owns agent executors later.
|
||||
|
||||
Runtime work is split into T11 (core runner) and T12 (pilot operations and packaging).
|
||||
|
||||
## Executor identity and authority ceiling
|
||||
|
||||
```task
|
||||
|
|
@ -396,6 +408,53 @@ check between consumers; failure triggers the revert path.
|
|||
**Done when:** the journey runs unattended against live with no person involved, and fails closed
|
||||
against a deliberately broken bind on a synthetic directory (T08).
|
||||
|
||||
## Executor runtime: core runner
|
||||
|
||||
```task
|
||||
id: NK-WP-0056-T11
|
||||
status: todo
|
||||
priority: high
|
||||
assignee: claude-code
|
||||
depends_on: [NK-WP-0056-T01, NK-WP-0056-T03]
|
||||
```
|
||||
|
||||
The executor itself, in net-kingdom (founder decision 6d1adce9):
|
||||
|
||||
- consume one admission through the approval-engine carrier (independent GET, digest check, aal2 check, consume once);
|
||||
- refuse outside the window or ceiling;
|
||||
- run the pinned steps one consumer at a time, with checks after each mutating step, settle times, revert on
|
||||
failure, the budget (wall time, attempts) and an `on_unknown: stop`;
|
||||
- emit `execution.run.started` and the receipt (PDP `not-evaluated` for the pilot).
|
||||
|
||||
Tested against in-process fakes for the carrier, operations and audit sink.
|
||||
|
||||
**Done when:** the runner passes its tests, including revert on a failed check, budget exhaustion, a stale or
|
||||
reused approval, and a step outside the ceiling. Every refusal must happen before any effect.
|
||||
|
||||
## Executor runtime: pilot operations and packaging
|
||||
|
||||
```task
|
||||
id: NK-WP-0056-T12
|
||||
status: todo
|
||||
priority: high
|
||||
assignee: claude-code
|
||||
depends_on: [NK-WP-0056-T11, NK-WP-0056-T08]
|
||||
```
|
||||
|
||||
The pilot's operations:
|
||||
|
||||
- OpenBao read and CAS write of the next version;
|
||||
- LLDAP self-rotation of the bind;
|
||||
- ExternalSecret force-sync and its status check;
|
||||
- Deployment restart and rollout check;
|
||||
- the synthetic journey.
|
||||
|
||||
Run them on the T08 synthetic stack, including a revert. Add the Containerfile and image workflow in
|
||||
net-kingdom. The `rapp-bounded-executor` package is created with `rmgr rapp wrap`, and the founder creates the
|
||||
Forgejo remote. It runs one Job per admission in `sso` with an egress-only NetworkPolicy.
|
||||
|
||||
**Done when:** a synthetic rotation completes and a deliberately failing one reverts, with receipts; the image builds.
|
||||
|
||||
## Pilot: unattended bind rotation under one admission
|
||||
|
||||
```task
|
||||
|
|
@ -405,7 +464,7 @@ priority: high
|
|||
assignee: claude-code
|
||||
needs_human: true
|
||||
intervention_note: "Founder signs the admission for the single live pilot rotation."
|
||||
depends_on: [NK-WP-0056-T01, NK-WP-0056-T03, NK-WP-0056-T04, NK-WP-0056-T05, NK-WP-0056-T10]
|
||||
depends_on: [NK-WP-0056-T01, NK-WP-0056-T03, NK-WP-0056-T04, NK-WP-0056-T05, NK-WP-0056-T10, NK-WP-0056-T12]
|
||||
state_hub_task_id: "6c3939f8-23a9-5f70-a3b1-94f4b291706b"
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue