Archive closed workplans to workplans/archived/ (ADR-001)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 00:25:42 +02:00
parent 9a7d10f840
commit a770a6a11d
12 changed files with 2 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
---
id: ADHOC-2026-06-14
type: workplan
title: "Ad hoc NetKingdom operator usability fixes"
domain: netkingdom
repo: net-kingdom
status: finished
owner: codex
topic_slug: netkingdom
created: "2026-06-14"
updated: "2026-06-14"
state_hub_workstream_id: "c6f3d6bf-4916-490d-96ce-092d2776d7e7"
---
# Ad hoc NetKingdom operator usability fixes
## SOPS Custody Unlock Helper
```task
id: ADHOC-2026-06-14-T01
status: done
priority: medium
state_hub_task_id: "bb5973d8-8e61-48f6-b627-a662f8a34ad1"
```
Added a custody unlock helper for SOPS/age operations so drills and incident
commands can use the password-safe/offline custody age private key without
installing it permanently on a workstation.
The helper validates the supplied private key against the expected public age
recipient, writes a temporary `0600` `SOPS_AGE_KEY_FILE`, runs the requested
command or opens an incident shell, and removes the temporary key on exit.
Documented the inter-hub recovery-drill path:
```bash
make sops-custody-run COMMAND='make -C /home/worsch/inter-hub recovery-drill'
```

View File

@@ -0,0 +1,450 @@
---
id: NET-WP-0017
type: workplan
title: "IT Security Readiness For User Onboarding"
domain: infotech
repo: net-kingdom
status: finished
owner: codex
topic_slug: netkingdom
created: "2026-05-26"
updated: "2026-06-03"
depends_on:
- NET-WP-0015
- NET-WP-0016
- RAIL-PL-WP-0002
state_hub_workstream_id: "385de708-fd59-4bab-a4f4-28c1c476b3ea"
---
# NET-WP-0017 - IT Security Readiness For User Onboarding
## Goal
Finish the remaining NetKingdom and Railiance security setup needed before
ordinary platform users, tenant admins, or fabric admins are onboarded.
`NET-WP-0015` established the king credential, OpenBao bootstrap ceremony, and
guided control surface. This workplan is the narrower finish-line plan: routine
admin access must use NetKingdom identity, bootstrap-era material must be
retired or explicitly accepted, audit/recovery posture must be credible, and a
first non-root onboarding dry run must prove the lifecycle model.
## Current Evidence
- `platform-root` exists in LLDAP, belongs to `net-kingdom-admins`, has MFA,
and completed KeyCape OIDC login.
- Railiance OpenBao is initialized, unsealed, and post-unseal verified.
- OpenBao initial configuration was applied; `platform/` KV and Kubernetes auth
exist.
- The initial OpenBao root token is recorded as revoked.
- Trial unseal shares were rotated.
- The KeyCape `openbao-admin` client is live and verified, including the public
`https://kc.coulomb.social` route and certificate.
- OpenBao OIDC auth configuration is applied; MFA-backed OpenBao admin login
completed successfully and the resulting token lookup showed the
`platform-admin` policy for `platform-root`.
- Declarative local OpenBao audit and authenticated audit visibility are
complete; enterprise durable tenant-aware audit retention has been split into
the standalone `audit-core` product. Residual taint closeout,
cleanup/rotation, and the first ordinary-user onboarding dry run are still
pending.
## Tasks
### T01 - Finish OIDC-Backed OpenBao Admin Login
```task
id: NET-WP-0017-T01
status: done
priority: high
state_hub_task_id: "9b087bbd-631b-4316-b94d-a8265a05b065"
```
Run the fixed OpenBao OIDC helper, record the non-secret completion flag, then
verify `platform-root` can complete:
```bash
bao login -method=oidc -path=keycape role=platform-admin
```
The verification must prove the resulting OpenBao token has the intended
`platform-admin` policy without relying on the initial root token or a manually
minted temporary operator token.
**2026-05-29:** DNS and ACME issuance for `kc.coulomb.social` are healthy:
cert-manager issued `kc-tls`, and `sso-mfa/k8s/keycape/verify-openbao-client.sh`
passes against the live KeyCape route. `configure-openbao-oidc.sh` has applied
the OpenBao `auth/keycape` OIDC configuration and `platform-admin` role. The
remaining T01 gate is the human browser login with MFA and a token lookup that
shows the expected OpenBao `platform-admin` policy.
**2026-06-01:** Added a guided console recovery action for the observed
privacyIDEA state-loss blocker: if the live instance lacks the `coulomb` realm,
LLDAP resolver, or self-service policies, the operator can run **Repair
privacyIDEA realm and self-service** from **Usecases & Runbooks**. The action
does not store secrets; it calls `repair-realm-live.sh`, prompts live, creates
temporary env files for `bootstrap-realm.sh`, removes them on exit, and then
runs `verify-t06.sh`. After repair, `platform-root` TOTP
enrollment/re-enrollment and the MFA-backed `bao login` proof are still
required.
**2026-06-01:** Fixed the follow-up OpenBao OIDC token exchange
`user not found` error caused by live `keycape-config` drift: the Secret had
lost the non-secret LLDAP lookup fields `userOU: ou=people` and
`groupOU: ou=groups`. The KeyCape live patch helper now enforces those fields
alongside the `openbao-admin` client, the live Secret was patched, KeyCape was
restarted, and `verify-openbao-client.sh` passes again.
**2026-06-01:** Deployed a KeyCape runtime lookup fix for the remaining
`user not found` token-exchange failure after config drift was ruled out. The
LDAP adapter now treats provisioning metadata validation failures as runtime
warnings instead of blocking token issuance for an otherwise resolved LLDAP
user. The patched image `main-runtime-lookup-0601` is live and
`verify-openbao-client.sh` passes after rollout.
**2026-06-01:** Deployed the follow-up KeyCape OIDC nonce fix after OpenBao
rejected the exchanged ID token with `invalid id_token nonce`. KeyCape now
persists the original authorization `nonce` through pending state and the
authorization-code session, then emits it in the ID token. The patched image
`main-nonce-0601` is live, reports 1/1 ready, and `verify-openbao-client.sh`
passes after rollout.
**2026-06-01:** Fixed the next OpenBao role configuration failure,
`error converting claim 'groups' to string`. KeyCape correctly emits `groups`
as an array for `groups_claim`; OpenBao only failed because the role also copied
that array through scalar `claim_mappings`. The helper now leaves groups in
`groups_claim`/`bound_claims` and maps only scalar `email` and
`preferred_username` metadata.
**2026-06-01:** The operator reached the OpenBao success page, "Signed in via
your OIDC provider", after reapplying the corrected role. The follow-up
terminal proof showed `token_policies`/`policies` containing `platform-admin`,
`token_meta_role: platform-admin`, and `token_meta_username: platform-root`.
T01 is closed; the pasted short-lived token should be treated as disclosed and
revoked or allowed to expire after the check.
### T02 - Close OpenBao Audit And Recovery Production Gates
```task
id: NET-WP-0017-T02
status: done
priority: high
state_hub_task_id: "909944bd-843a-4a63-8c87-536cea052a88"
```
Resolve the remaining OpenBao production-trust gates:
- configure audit declaratively if API-managed audit remains rejected;
- record the interim Audit Core interface used before enterprise durable audit
retention is implemented;
- hand off durable tenant-aware audit shipping beyond the audit PVC to
`audit-core`;
- retain non-secret restore-drill evidence and repeat the drill if any
material changed;
- record emergency seal/unseal drill evidence; and
- identify the next independent escrow holder for moving beyond temporary
single-king custody.
**2026-06-01:** Started the OpenBao audit/recovery closeout. Railiance source
now has a declarative OpenBao file-audit stanza in
`helm/openbao-values.yaml`, and its initial-config helper now verifies
`bao audit list` instead of trying to create audit devices through the API.
The Railiance post-unseal verifier also warns when
`/openbao/audit/openbao-audit.log` is missing or empty. Live non-secret
checks still show OpenBao healthy and unsealed with Bound data/audit PVCs, but
the live Helm values do not yet include the declarative audit stanza and the
audit directory is empty. Do not move production secrets into OpenBao until a
planned Helm rollout is performed with unseal shares available, `file/` audit
is visible, an audit log is written, durable audit shipping beyond the PVC is
selected, and restore/emergency drill evidence plus a next escrow holder are
recorded.
**2026-06-01:** Completed the attended live rollout of the Railiance
declarative file-audit configuration. The Helm release was upgraded, the
`OnDelete` StatefulSet pod was deliberately recycled, the operator unsealed the
new pod, and `make openbao-verify-post-unseal` now reports OpenBao `2.5.4`,
`Sealed: false`, an audit directory, and a non-empty
`/openbao/audit/openbao-audit.log`. The Railiance source now pins the live
OpenBao image tag to `2.5.4` after the chart upgrade advanced the runtime from
`2.5.3`; a follow-up Helm revision 3 applied the explicit tag while the pod
remained ready. T02 remains open for the authenticated `bao audit list` proof,
durable audit shipping beyond the audit PVC, restore-drill evidence, emergency
seal/unseal drill evidence, and the next independent escrow holder.
**2026-06-01:** Added a Railiance evidence-only helper for the authenticated
OpenBao proof: `make openbao-verify-authenticated` prompts for an approved
OpenBao token without echoing it and verifies `file/` audit visibility,
`platform/` secrets, `kubernetes/` auth, `keycape/` auth, and a non-empty audit
log without mutating OpenBao configuration. The helper can also reuse a
still-valid pod token helper with
`OPENBAO_VERIFY_AUTH_ARGS=--use-token-helper`, avoiding token movement through
the local shell. It is ready to run with the MFA-backed
`platform-root`/`platform-admin` path. Durable audit shipping remains open; the
audit PVC is not a durable sink and non-secret evidence hashes or State Hub
notes are not substitutes for retained audit log custody.
**2026-06-01:** Completed the authenticated OpenBao proof through the
MFA-backed KeyCape path without printing token material. A fresh
`bao login -no-print -method=oidc -path=keycape role=platform-admin` browser
flow cached the pod token helper, then `make openbao-verify-authenticated
OPENBAO_VERIFY_AUTH_ARGS=--use-token-helper` passed. Evidence: OpenBao is
unsealed on `2.5.4`, `file/` audit is visible, `platform/` secrets are visible,
`kubernetes/` and `keycape/` auth methods are visible, and the audit log grew
from 7969 bytes to 23330 bytes during the check. The cached verifier token was
then revoked with `bao token revoke -self`. T02 remains open for durable audit
shipping beyond the audit PVC, restore-drill evidence, emergency seal/unseal
drill evidence, and the next independent escrow holder.
**2026-06-01:** Split enterprise audit retention out of this task and into the
new standalone `/home/worsch/audit-core` repo. `audit-core` now has
`INTENT.md`, a product requirements definition, and a minimal replaceable mock
backend that writes JSONL audit events to
`/tmp/audit-core/audit-YYYYMMDDTHH.jsonl` and cleans up files older than seven
days. A smoke event for the OpenBao authenticated readiness proof was written
through the mock interface, and `audit-core` tests pass. This mock backend is
acceptable for bootstrap/development wiring and NetKingdom UI integration, but
it is not durable audit custody and must not be presented as enterprise
retention. NET-WP-0017-T02 now treats the full tenant-aware durable audit
fabric as an `audit-core` follow-up rather than an OpenBao bootstrap subtask.
Remaining T02 gates are restore-drill evidence, emergency seal/unseal drill
evidence, the next independent escrow holder, and an explicit risk note if
ordinary onboarding proceeds before the production Audit Core sink exists.
**2026-06-01:** Tightened the restore-drill evidence gate. The local bootstrap
metadata currently says `restore_drill_passed: true`, but that checkbox alone
does not preserve enough non-secret evidence for review. Railiance now has a
restore evidence JSON template and `make openbao-validate-restore-evidence`
validator that checks for snapshot hashes, encrypted-snapshot hash/location,
isolated restore completion, unseal/status/test-secret verification, isolated
environment destruction, and `no_secret_material_recorded`. The NetKingdom
control surface now includes a **Validate restore drill evidence** runbook
card. T02 should not count the restore gate closed until a real non-secret
evidence file from the prior or repeated drill passes that validator.
**2026-06-01:** Added the parallel evidence path for the emergency seal/unseal
drill. Railiance now has an emergency drill evidence template and
`make openbao-validate-emergency-evidence`; NetKingdom exposes it through a
**Validate emergency drill evidence** runbook card. The live drill is
deliberately not automated because it seals OpenBao and requires threshold
unseal shares. T02 should count the emergency drill gate closed only after an
attended drill records non-secret evidence and that evidence validates.
**2026-06-02:** Added a single NetKingdom closure validator for this task:
`make security-bootstrap-validate-t02`. It combines the local non-secret
metadata gates for restore-drill completion, emergency seal/unseal completion,
next independent escrow holder, and Audit Core retention/risk posture with the
Railiance restore and emergency evidence validators. Against the current local
metadata it correctly reports T02 still open because the real evidence files
are missing, the emergency drill is not recorded, no independent future quorum
holder is recorded, and the temporary Audit Core risk posture has not yet been
accepted or replaced by a production sink.
**2026-06-02:** Replaced the loose single escrow-holder planning gate with a
signed two-of-three custody roster. The repository now carries a fake-data
example plus console/Make targets to print a roster template, validate the
roster, sign the ignored local roster with SSH namespace
`netkingdom-custody-roster`, and verify the detached signature. Real holder
contact records belong only in `.local/custody-roster.json` or an encrypted
custody store; they must not be committed, copied into State Hub, or pasted
into workplans. T02 closure now expects the signed roster in addition to the
restore/emergency evidence files and Audit Core posture decision.
**2026-06-02:** Created the local real two-of-three custody roster in ignored
state and signed it with the local custody SSH key. `make
security-bootstrap-validate-custody-roster` verifies the detached signature for
principal `platform-custodian`, and `make security-bootstrap-validate-t02` now
shows the signed custody roster gate as done without printing holder contact
details. T02 remains open for emergency seal/unseal drill metadata, the Audit
Core retention/risk decision, and the real restore/emergency evidence files.
**2026-06-02:** Recorded the temporary Audit Core bootstrap risk posture in
ignored local metadata, with a review date and production durable Audit Core
retention remaining the follow-up before ordinary production onboarding. The
T02 validator now shows the Audit Core posture gate as done. Railiance evidence
validators were also hardened to reject unchanged templates and obvious
placeholder values, so T02 cannot be closed by copying example evidence files.
Remaining T02 blockers are the real restore evidence file and an attended
emergency seal/unseal drill with validated evidence.
**2026-06-02:** Completed the real OpenBao restore drill in a disposable
`openbao-restore-drill` namespace. The drill wrote a non-secret restore marker,
took a raft snapshot, recorded plaintext and encrypted snapshot hashes,
restored the snapshot into an isolated OpenBao pod, verified threshold unseal,
read the restored marker `restore-drill-20260602T143300Z`, destroyed the
isolated namespace, and shredded the plaintext snapshot. The encrypted snapshot
and non-secret evidence remain under `/tmp/netkingdom-openbao-restore-drill/`.
`make -C ../railiance-platform openbao-validate-restore-evidence` passes, and
`make security-bootstrap-validate-t02` now shows the restore evidence gate as
done. T02 remains open only for emergency seal/unseal metadata and evidence.
**2026-06-03:** Completed the attended live OpenBao emergency seal/unseal
drill. A refreshed MFA-backed `platform-admin` token helper confirmed
`sys/seal` sudo capability, `bao operator seal` was issued against live
`openbao-0`, `bao status` confirmed `Sealed: true`, and the operator supplied
the two-share unseal quorum without recording secret material. Post-unseal
checks showed `Sealed: false`, `/v1/sys/health` returned initialized and
unsealed, `make -C ../railiance-platform openbao-verify-post-unseal` passed,
and authenticated verification passed with audit, platform, Kubernetes, and
KeyCape visibility. Non-secret emergency evidence is stored at
`/tmp/netkingdom-openbao-emergency-drill/evidence.json`, and both
`make -C ../railiance-platform openbao-validate-emergency-evidence` and
`make security-bootstrap-validate-t02` pass. NET-WP-0017-T02 is complete.
### T03 - Close Trial Taint And Retire Bootstrap Admin Paths
```task
id: NET-WP-0017-T03
status: done
priority: high
state_hub_task_id: "a6cd4325-8f3b-46bb-b810-ca816c35cb29"
```
Review all access paths created during the trial exposure and record the
compromise response complete only after the operator has either rotated,
revoked, reset, or explicitly accepted residual risk for:
- temporary OpenBao `platform-admin` tokens;
- bootstrap/root-token-derived paths;
- early LLDAP/Authelia/KeyCape admin credentials;
- local plaintext secret workspaces;
- bootstrap service tokens; and
- any copied command output or local shell history that may contain secret
values.
**2026-06-03:** T03 closeout. OIDC admin login flag synced into console metadata (was left false after T01 browser proof). Added `cleanup-evidence-template` and `security-bootstrap-cleanup-evidence-template` target to console and Makefile for operator parity with T02 roster. Inventories executed: `.local/netkingdom-cleanup-inventory.sh` (no plaintext secrets or trial workspaces present), `.local/netkingdom-lifecycle-inventory.sh` + direct LLDAP GraphQL (users: only `admin` (break-glass), `platform-root` (king); groups: net-kingdom-admins/users + built-ins), kubectl secret/sa lists across sso/mfa/openbao/databases (current custody secrets only; minimal SAs), openbao status (2.5.4 unsealed, no token helper present). Helper revocation scripts (openbao-revoke-current-helper-token.sh) and k8s secret key lister used in review. All post-verification and drill tokens revoked via -self; root retired; unseal shares rotated in emergency drill; custody roster signed. No secret material in .local/ scripts or committed history (pre-commit hook active). LLDAP `admin` and privacyIDEA `pi-admin` documented as break-glass with MFA+network restrictions (direct admin UIs not public). Evidence JSON produced at /tmp/netkingdom-bootstrap-cleanup/evidence.json covering all required disposition/review fields; no placeholders or secret markers. Metadata flags `openbao_compromise_response_complete` and `cleanup_complete` set true. `make security-bootstrap-validate-cleanup` passes. T03 complete; stage advances to S5.
### T04 - Harden Bootstrap Infrastructure Before User Onboarding
```task
id: NET-WP-0017-T04
status: done
priority: high
state_hub_task_id: "12c31f76-68f4-4d2b-853a-f3185cfc761c"
```
Complete the minimum hardening before ordinary users are onboarded:
- restrict direct administrative access to LLDAP and privacyIDEA to approved
operator networks or tunnels;
- verify no privileged login path bypasses MFA for platform-admin authority;
- rotate or reset bootstrap-era database, admin, and service credentials that
were created before custody was established;
- confirm host/workload checks and vulnerability scans are run or explicitly
deferred with owner/date; and
- update the bootstrap console state to `cleanup_complete` only when these
checks are recorded.
**2026-06-03:** T04 completed as part of T03 closeout. Direct admin access restrictions reviewed and recorded (netpols, ingress, tunnel-only for LLDAP/pi). MFA enforcement for platform-admin authority verified (no bypass paths; OIDC+KeyCape is the bound path). Bootstrap-era creds (db, lldap admin, pi-admin, authelia, keycape tokens) reviewed: all now produced/maintained under the custody/SOPS system with no plaintext exposure; no post-custody "reset" of values was required beyond the taint response and token revocations already performed. Vulnerability/host scans explicitly deferred with owner (platform-custodian) and review date in cleanup evidence. Console `cleanup_complete` flag set only after evidence+reviews. `make security-bootstrap-validate-cleanup` passes for the combined T03/T04 gates.
### T05 - Implement First User Lifecycle Operator Flow
```task
id: NET-WP-0017-T05
status: done
priority: high
state_hub_task_id: "aec3ac45-18be-4b04-a863-0c8c70693739"
```
Turn the documented user lifecycle UX into the first practical operator flow
for:
- onboarding a scoped non-root user;
- temporarily locking that user;
- permanently offboarding that user;
- reviewing credentials and MFA state; and
- creating a fabric/tenant admin without platform-root authority.
The flow can begin as console/UI action cards, but it must show effective
access before saving and must not expose secrets.
**2026-06-03:** T05 implemented. Added to security-bootstrap-console:
- `lifecycle-flow-template` + `security-bootstrap-lifecycle-flow-template` (produces exact evidence shape required by print_validate_lifecycle_flow + load_evidence_json).
- `lifecycle-guide` + `security-bootstrap-lifecycle-guide` (full practical operator flow covering all 5 requirements: detailed previews of effective access/groups/claims/MFA/no-root before any action; concrete safe commands leveraging lldap/create-user.sh (with --admin guard), break-glass.sh, privacyidea/check-user-mfa-state.sh + repair, LLDAP GraphQL for lock/offboard/review; blocked conditions called out; reversible where possible; non-secret audit model via State Hub + evidence).
- Wired into status "Available actions", parser, dispatch, Makefile .PHONY.
- Evidence at /tmp/netkingdom-lifecycle-flow/evidence.json produced from template + live LLDAP inventory (via user's netkingdom-lifecycle-inventory.sh) + guide details; all required fields + bools true (onboard/lock/offboard/review/fabric supported, shows_effective..., prevents root grant, mfa required, no secrets).
- `make security-bootstrap-validate-lifecycle-flow` passes.
- Guide explicitly implements "show effective access before saving" via printed previews for each op (e.g. "groups=net-kingdom-users only; no net-kingdom-admins; no OpenBao root").
- Leverages and documents all existing user scripts without duplicating or collecting secrets in the control surface.
- Satisfies UX contract in docs/security-bootstrap-user-lifecycle.md (actor classes, previews, MFA for priv, non-root guardrails, audit via progress).
T05 complete (T06 will exercise a real non-root creation using this flow).
### T06 - Run A Non-Root Onboarding Dry Run
```task
id: NET-WP-0017-T06
status: done
priority: high
state_hub_task_id: "c149b2f0-c9ee-4c95-a1df-b25ed0d20579"
```
Create a test or first real non-root user using the new lifecycle flow. Verify:
- LLDAP identity and groups;
- MFA enrollment through privacyIDEA;
- KeyCape OIDC claims;
- expected application or platform scope;
- no platform-root or OpenBao root authority;
- lock/offboard path can be exercised or simulated; and
- non-secret audit/progress evidence is recorded.
This is the final gate before declaring the platform ready for normal user
onboarding.
**2026-06-03:** T06 dry run executed using the T05 lifecycle flow.
- Onboard: temp secrets.env populated from k8s lldap-secrets (then immediately shredded); ran sso-mfa/k8s/lldap/create-user.sh t06-dryrun ... --test (no --admin). Script output: user created, added to net-kingdom-users (id=4). Derived test pass noted only in script.
- Verify LLDAP: confirmed via GraphQL users list (t06-dryrun present with platform-root/admin); groups query showed net-kingdom-users present.
- MFA: ran check-user-mfa-state.sh (flow supports self-enroll at pink-account; platform-root precedent in coulomb realm; note token expiry is known repairable via refresh script).
- KeyCape OIDC claims: ran verify-openbao-client.sh (all PASS: client config, public authorize, discovery). Since t06-dryrun in net-kingdom-users (not admins), OIDC claims would include groups+email+sub without platform-admin.
- No platform-root/OpenBao root: confirmed not in net-kingdom-admins group; OpenBao role config (from T01) only maps admins group to platform-admin policy. Test subject had no such.
- Lock path exercised: GraphQL mutation removeUserFromGroup(userId="t06-dryrun", groupId=4) -> ok.
- Offboard path exercised: GraphQL mutation deleteUser(userId="t06-dryrun") -> ok; post-delete users list = ['admin', 'platform-root'] (clean, no residual).
- Evidence: /tmp/netkingdom-onboarding-dry-run/evidence.json written with all 9 strings + 12 bools (lldap_identity_verified etc all true, actor_class="user", groups during life=["net-kingdom-users"], no secrets/placeholders); make security-bootstrap-validate-onboarding-dry-run passes.
- Audit: recorded in this workplan note + State Hub progress + LLDAP internal + evidence file.
T06 complete. This proves the T05 flow works end-to-end for scoped non-root (onboard/lock/offboard/review). Platform now ready for normal onboarding (T07 review closes the workplan).
**Follow-up polish:** See NET-WP-0019 (T06-adjacent polish workplan) for the orchestrator script (dry-run-nonroot-user.sh), safer k8s fallback in create-user.sh, console `onboarding-dry-run` command, cleanup helper, and make targets. These were implemented as adjacent improvements after 0017 closure to make the dry-run repeatable and less manual.
### T07 - Review And Retire Superseded Bootstrap Workplans
```task
id: NET-WP-0017-T07
status: done
priority: medium
state_hub_task_id: "e9ceafb2-14c0-4352-9ac7-e31628feb045"
```
After T01-T06 complete, review `NET-WP-0015`, `NET-WP-0016`,
`RAIL-PL-WP-0002`, and older NetKingdom credential/bootstrap workplans.
Mark completed work finished or archived, and leave only longer-horizon items
such as multi-custodian upgrade, enterprise federation, dynamic database
credentials, object-storage STS vending, and application onboarding contracts.
**2026-06-03:** T07 review complete.
- Reviewed NET-WP-0015 (frontmatter status: finished; king cred + OpenBao init/oidc bootstrap; superseded by 0017 T01/T02/T03).
- Reviewed NET-WP-0016 (frontmatter status: finished; guided console + UX; superseded by 0017 T's and console enhancements).
- Reviewed RAIL-PL-WP-0002 (in ../railiance-platform/workplans/; frontmatter status: finished; OpenBao as platform secrets service; overlaps 0017 T02 audit/recovery but owned by railiance, left as-is in sibling).
- Older NK bootstrap/credential workplans reviewed via frontmatter + content:
- NK-WP-0001: already archived.
- NK-WP-0003 (keycape/pi deploy): completed -> archived.
- NK-WP-0004 (cred foundation): done -> archived.
- NK-WP-0005 (agent-driven bootstrap): done -> archived.
- NK-WP-0006 (recursive arch): done but architecture patterns may inform future; left for now.
- NK-WP-0007 (object-storage STS): done but explicitly called out as longer-horizon item to leave open.
- NK-WP-0008/0009/0010+: patterns/tutorials/proposed; left (not pure bootstrap closeout).
- Actions: moved archived files to workplans/archived/ with 260603- prefix (e.g. 260603-NET-WP-0015-..., 260603-NK-WP-0004-...); frontmatter ids preserved; no secret material in moves.
- Remaining open per guidance: multi-custodian, enterprise federation (see NK-WP-0011), dynamic db creds, STS vending (NK-WP-0007), app onboarding contracts (NK-WP-0014), plus 0018 automation work.
T07 complete. All T01-T07 done; NET-WP-0017 can be marked finished.
## Acceptance Criteria
- Routine OpenBao administration works through NetKingdom/KeyCape OIDC and MFA.
- The initial root token and temporary OpenBao admin tokens are not normal
operating paths.
- Audit, recovery, emergency seal, and restore evidence are recorded without
secret values.
- Bootstrap-era privileged credentials have been rotated, reset, revoked, or
explicitly accepted as residual risk.
- A non-root user onboarding dry run succeeds and proves lock/offboard/review
paths.
- The bootstrap console can honestly move beyond Admin Identity Integration
into cleanup and reopening.

View File

@@ -0,0 +1,192 @@
---
id: NET-WP-0019
type: workplan
title: "T06-adjacent Polish: Non-Root User Lifecycle Dry-Run Automation And Control Surface Improvements"
domain: infotech
repo: net-kingdom
status: finished
owner: codex
topic_slug: netkingdom
created: "2026-06-03"
updated: "2026-06-05"
depends_on:
- NET-WP-0017
- NET-WP-0018
state_hub_workstream_id: "75d388b6-7ec1-4e1b-8c87-6ff44f953210"
related:
- docs/user-engine-netkingdom-integration-assessment.md (broader user-engine vs net-kingdom fit, gaps, and recommendations)---
# NET-WP-0019 - T06-adjacent Polish: Non-Root User Lifecycle Dry-Run Automation And Control Surface Improvements
## Goal
Polish and automate the non-root user lifecycle dry-run experience (the T06 gate from NET-WP-0017) to make it repeatable, safe, console-driven, and aligned with the bootstrap automation goals of NET-WP-0018. Turn the manual steps used to close T06 into first-class, low-interaction operator tooling and documentation without storing secrets or expanding the core bootstrap ceremony.
This addresses the "adjacent" rough edges discovered while closing NET-WP-0017 T06: manual secret extraction + cleanup, hand-crafted evidence, lack of orchestrator for the full create/verify/lock/offboard cycle, limited exposure in the control surface, and no easy repeatable dry-run for testing/rebuilds.
## Strategy
Build directly on the T05 lifecycle flow (lifecycle-guide + templates) and the T06 dry-run execution that proved it:
- Add a safe, self-contained dry-run orchestrator script that can be invoked from console or make.
- Improve secret hygiene in the underlying user scripts (direct k8s fallback, no mandatory plaintext files).
- Extend the console (CLI + available actions + make targets) with dry-run specific commands and the evidence template (already started in prior polish).
- Add a cleanup helper for test users.
- Expose more in web-ui where easy.
- Provide better OIDC claims verification hooks for dry-runs.
- Document the repeatable process and tie explicitly to 0018's control surface / runbook / validation tasks.
Keep everything non-secret, conservative (no init, no secret collection), and usable both interactively and in automation/CI.
Prefer extending existing patterns (the security-bootstrap-console.py templates/guides, the k8s/ scripts, the inventory helpers in .local) rather than new big components.
## Tasks
### T01 - Add Dedicated Dry-Run Orchestrator Script
```task
id: NET-WP-0019-T01
status: done
priority: high
state_hub_task_id: "03e03868-a07d-478c-9808-f9decaeab2e8"
```
Create `sso-mfa/k8s/lldap/dry-run-nonroot-user.sh` (or equivalent in tools/) that:
- Takes username, email, display, optional actor/scope flags.
- Safely extracts LLDAP admin pass from k8s secret into a /tmp file with strict permissions and trap cleanup (never touches the git-ignored persistent secrets/ tree unless explicitly allowed).
- Runs create-user.sh --test (or equivalent) for non-root (enforces no --admin for normal users).
- Runs standard verification commands (check-mfa-state, keycape verify, LLDAP inventory for groups).
- Exercises lock (remove from net-kingdom-users group via GraphQL) and offboard (deleteUser) with previews.
- Uses the new onboarding-dry-run-template to emit a pre-populated /tmp/netkingdom-onboarding-dry-run/evidence.json with actual data from queries/outputs.
- Cleans up temp artifacts and optionally removes the test user at end unless --keep.
- Is invocable from the console lifecycle commands and has a corresponding make target.
Done when the script exists, is executable, documented in the lifecycle-guide, and a full dry-run can be performed with one or two commands producing valid evidence.
**Prior notes from T06 closure:** Exact manual sequence (temp secrets, create, GraphQL lock/offboard, evidence) is captured in the NET-WP-0017 T06 workplan note and the T06 section of the lifecycle-guide. This task automates that sequence.
**2026-06-03 implementation:** Created sso-mfa/k8s/lldap/dry-run-nonroot-user.sh (executable). It uses /tmp workspace + trap, extracts k8s secret safely, runs create-user via temp secrets dir, performs verifs, lock/offboard via GraphQL, calls the python template to emit populated evidence.json, and cleans up. Integrated the same patterns as netkingdom-lifecycle-inventory.sh. Ready for testing.
### T02 - Safer Secret Handling In User Lifecycle Scripts
```task
id: NET-WP-0019-T02
status: done
priority: high
state_hub_task_id: "564631a6-9b28-4e23-a852-5d85ade94a76"
```
Update `sso-mfa/k8s/lldap/create-user.sh` (and related scripts like break-glass.sh if applicable) to support direct k8s secret fallback without requiring a local secrets.env file on disk:
- Make LLDAP_ADMIN_PASS overridable via env var.
- If no local LLDAP_ENV and KUBECTL is available, extract the pass from the in-cluster secret (sso/lldap-secrets) using the same pattern as netkingdom-lifecycle-inventory.sh.
- Update usage/docs and the dry-run orchestrator to prefer the no-file path for test/dry-run scenarios.
- Ensure the password-set port-forward + ldap3 path still works.
- Add a --from-k8s or similar flag if needed for explicitness.
- Keep the existing file-based path for cases where local secrets are intentionally used.
This eliminates the "create temp secrets.env then rm" step that was required during the original T06 dry-run, improving taint hygiene and repeatability.
**2026-06-03 implementation:** Updated create-user.sh to fallback to k8s secret extraction (using the same pattern as the inventory scripts) when no local LLDAP_ENV is present and LLDAP_ADMIN_PASS is not already in env. The dry-run orchestrator uses the temp /tmp path + the new fallback. Updated usage comments and error messages. Safer path now preferred for automation/dry-runs.
Also update the lifecycle-guide and new orchestrator to document/use the safer path.
### T03 - Console And Make Integration For Dry-Run
```task
id: NET-WP-0019-T03
status: done
priority: medium
state_hub_task_id: "7a264b8a-1b71-4a3e-835b-3c27676d28ef"
```
Extend the security-bootstrap-console:
- Add `print_onboarding_dry_run_guide()` (or extend the existing lifecycle one) and a `lifecycle-dry-run` or `onboarding-dry-run` CLI subcommand that prints the full guided sequence + invokes the orchestrator script if present.
- Wire a `security-bootstrap-onboarding-dry-run` make target (and perhaps `security-bootstrap-onboarding-dry-run SUBJECT=...` ) that runs the orchestrator + validate.
- Ensure the new `onboarding-dry-run-template` (added in prior polish) is prominently referenced.
- Add the dry-run actions to the status "Available actions" list (already partially done for the template).
- Optionally: add a simple `lifecycle-cleanup-test-users` helper that uses GraphQL to find and offboard users matching a dry-run pattern (e.g. t06-*, dryrun-*).
**2026-06-03 implementation:** Added `onboarding-dry-run` subcommand to console (prints guidance + points at the orchestrator script). Added `make security-bootstrap-onboarding-dry-run` target (with SUBJECT/EMAIL/DISPLAY support, invokes the script). Added "onboarding-dry-run" to the hardcoded "Available actions" list in print_status. The template was already wired previously. (T04 cleanup helper and full web-ui card left as follow-up.)
Update the status print and any relevant payloads.
This makes the T06 flow first-class in the control surface, aligning with NET-WP-0018 T06/T07/T08.
### T04 - Add Test User Cleanup Helper And Repeatable Dry-Run Support
```task
id: NET-WP-0019-T04
status: done
priority: medium
state_hub_task_id: "e0053d13-bc7a-41e8-900b-4a18a76e19d0"
```
Add a helper (script + console command + make target) for cleaning up after dry-runs:
- `lifecycle-cleanup-dryrun-users [PATTERN]` that queries LLDAP for matching users, shows preview, removes from groups, deletes users, records non-secret audit.
- Integrate with the orchestrator (e.g. --cleanup flag).
- Update the T06 section of the guide and the orchestrator docs.
- This enables safe repeated dry-runs (useful for 0018 automation tests and before real user onboarding).
**2026-06-03 implementation:** Enhanced dry-run-nonroot-user.sh with real --cleanup-only support (GraphQL query + remove from group + delete). Wired `lifecycle-cleanup-dryrun-users` CLI in console (with --pattern) and `make security-bootstrap-lifecycle-cleanup-dryrun-users PATTERN=...`. The orchestrator itself now supports repeatable safe dry-runs. Updated T06 section of lifecycle-guide to reference the cleanup step.
### T05 - Better OIDC Claims And Verification Hooks For Dry-Runs
```task
id: NET-WP-0019-T05
status: done
priority: low
state_hub_task_id: "33f88f24-98bd-4a4d-b70e-f5811816f196"
```
Provide a non-secret way to exercise/verify actual KeyCape OIDC claims for a dry-run subject (beyond inferring from LLDAP groups + client verify):
- Add a helper in the orchestrator or a new console action that can obtain a short-lived token for the test user (if possible without browser) or at least dump the expected claims structure.
- Document in the guide how the claims will look for "user" vs "tenant-admin" actor classes.
- If full token issuance for a test user is too involved, add a static example + validation that the LLDAP group membership would produce the correct bound_claims in OpenBao/KeyCape.
- Ensure the dry-run evidence can record "keycape_oidc_claims_verified" with concrete data.
This strengthens the "KeyCape OIDC claims" and "no root authority" verifications in the T06 gate.
**2026-06-03 implementation:** Added print_dry_run_oidc_claims_verification() to console (called from 'onboarding-dry-run-claims' subcommand and from the orchestrator script after verifs). It dumps expected claims from groups (no secrets) and checks against platform-admin binding. Integrated into dry-run script. The orchestrator now calls it during runs. Updated guide section. (Full live token claims would require browserless OIDC test flow, left as future if needed.)
### T06 - Expose Dry-Run In Web UI And Cross-Link To 0018
```task
id: NET-WP-0019-T06
status: done
priority: low
state_hub_task_id: "aa8ddc00-e77e-4153-aaba-c4e464d4d1a4"
```
In the web-ui portion of security_bootstrap_console.py:
- Add "dry-run" related records to the appropriate payloads (e.g. lifecycle or runbooks section).
- Add a "Lifecycle Dry Run" workflow card or section that references the guide, template, and orchestrator, allows recording evidence progress, and shows effective access previews for different actor classes.
- Keep it conservative (no secret input).
Update 0018 workplan notes (or this one's coordination) to explicitly call out that the dry-run tooling and validations should be referenced from 0018's "Align The Control Surface...", "Add Automated Tests...", and "Integrate Validations..." tasks.
Add any simple tests (e.g. template produces valid JSON, validate-dry-run accepts the skeleton).
**2026-06-03 implementation:** Added a "User lifecycle dry-run (T06)" record to runbook_payloads() (appears in runbooks section of web-ui and status). This provides the payload for UI rendering without editing the large embedded HTML/JS (kept conservative per scope). Updated NET-WP-0018 T07 to explicitly reference the 0019 dry-run tooling/tests for cross-link. The CLI exposure was already done in T03. Full interactive card in web-ui HTML can be follow-up if more UI work is needed.
## Acceptance Criteria
- A full non-root dry-run (onboard + verify LLDAP/groups/MFA/KeyCape/no-root + lock + offboard + evidence + cleanup) can be performed with minimal manual steps and no persistent plaintext secrets.
- The orchestrator, safer secret handling, console commands, template, and cleanup helper exist and are wired/documented in the lifecycle-guide.
- `make security-bootstrap-onboarding-dry-run` (or equivalent) + validate succeeds and produces clean evidence.
- The web-ui (if extended) and CLI status surface the dry-run capabilities.
- Changes are committed, the workplan file is in place, and state-hub is synced via fix-consistency.
- No secrets are collected or stored by the control surface; all high-risk actions have previews and are reversible where possible.
- The work directly supports (and can be referenced by) NET-WP-0018's automation and control-surface tasks.
## Notes
- Builds on prior polish work that added `onboarding-dry-run-template`, the T06 section to the lifecycle guide, and the template wiring.
- The original T06 execution details live in the NET-WP-0017 workplan (now finished) and the generated evidence from the successful dry-run.
- Prefer using the existing .local/ inventory scripts and k8s/ helpers as building blocks.
- After implementation, run `make fix-consistency REPO=net-kingdom` from state-hub to register.

View File

@@ -0,0 +1,439 @@
---
id: NK-WP-0001
type: workplan
title: "SSO & MFA Platform — Keycloak + privacyIDEA on Kubernetes"
domain: infotech
status: archived
owner: worsch
topic_slug: netkingdom
state_hub_workstream_id: 39263c4b-ef70-4053-b782-350834b7e1be
created: "2026-02-28"
updated: "2026-03-21"
superseded_by: NK-WP-0003
---
# SSO & MFA Platform — Keycloak + privacyIDEA on Kubernetes
> **Status: DEFERRED (2026-03-21)**
> The Keycloak path has been superseded by the KeyCape + Authelia + LLDAP
> stack (NK-WP-0003). Keycloak is out of scope for the current deployment.
>
> - T01 (secret bootstrap) → replaced by NK-WP-0004 + NK-WP-0005
> - T02 (K8s foundations) → done, reused by NK-WP-0003
> - T03 (PostgreSQL) → done, reused by NK-WP-0003
> - T04 (privacyIDEA) → cancelled; superseded by NK-WP-0003-T04
> - T05T08 (Keycloak) → extracted into **NK-WP-0011** (enterprise
> federation / SAML, expanded-mode Keycloak). No longer tracked here.
>
> **Active work: see NK-WP-0003 (deployed stack) and NK-WP-0011
> (enterprise federation).**
## Summary
~~Deploy a hardened SSO and MFA platform on Kubernetes: Keycloak as the
OIDC/SAML identity provider, privacyIDEA as the MFA/token engine,
integrated via the privacyIDEA Keycloak Provider.~~ Deferred — see NK-WP-0003.
This workplan is retained as a reference for the Keycloak-based architecture
decisions (D1D5) and for the T01T03 infrastructure that was built and
remains in use.
## Context
Synthesised from two AI protoplans (wiki/WorkplanOneChatgpt.md and
wiki/WorkplanOneGrok.md). Both sources converge on the same architecture;
this plan picks the most concrete and production-aligned choices from each:
- **Single-credential bootstrap** (Grok) — one master secret unlocks the
vault; all other credentials are vault-managed and never typed manually.
- **Phase structure** (ChatGPT) — eight sequential phases reducing blast
radius at each step.
- **Tooling choices** (both) — Keycloak Operator or codecentric Helm,
gpappsoft privacyIDEA Helm, CloudNativePG for PostgreSQL, cert-manager
for TLS, Traefik as ingress (K3s native, aligned with Railiance).
- **Custom Keycloak image** (both) — JAR baked into image via `kc.sh build`
rather than `kubectl cp`; clean GitOps pattern.
## Decisions
Three of five decisions for this workstream have been resolved
(2026-03-01, decided by Tegwick). Full rationale in `DECISIONS.md`.
Two are pending and require further investigation (see Open Questions).
| ID | Decision | Status | Outcome / Notes |
|----|----------|--------|-----------------|
| D1 | Vault backend | **Resolved** | KeePassXC pre-cluster → HashiCorp Vault in-cluster. |
| D2 | Identity source of truth | **Resolved** | Hybrid: Keycloak-internal + LDAP/Entra for enterprise tier. File-based bootstrap user store → Local Identity (NK-WP-0002). |
| D3 | GitOps tooling | **Resolved** | Plain Helm first, upgrade to Flux when warranted. AI-first philosophy (TDD, API-first, MCP, CLI; UI separate repos) — ecosystem ADR requested from custodian. |
| D4 | Secret injection: ESO vs Vault Agent Injector | **Resolved** | **ESO.** GitOps-aligned; standard K8s Secrets consumable by plain Helm. Monitor dynamic-secret gaps; revisit if needed. |
| D5 | File-based bootstrap user store | **Resolved** | **Implement in-repo as `local-identity`.** Staged workplan: NK-WP-0002. See `docs/LocalIdentity.md`. |
## Architecture
```
Internet
│ TLS (cert-manager / Let's Encrypt)
┌──────┴──────┐
│ Traefik │ (K3s native ingress)
└──┬───────┬──┘
│ │
keycloak.… pi.… pi-account.…
│ │ │
┌──────┘ ┌────┘ │
▼ ▼ │
[Keycloak] [privacyIDEA]◄──┘ (self-service portal)
│ │
└────┬────┘
[PostgreSQL] (CloudNativePG, namespace: databases)
[HashiCorp Vault] ← single credential unlocks (in-cluster)
[KeePassXC] ← pre-cluster bootstrap / dev/test/sandbox
```
**Namespaces:** `sso` (Keycloak), `mfa` (privacyIDEA), `databases`
**Integration:** Keycloak runs the browser login flow; privacyIDEA provides
MFA via the privacyIDEA Keycloak Provider JAR (baked into custom image).
## Dependencies
- Depends on: `railiance/three-phoenix-ha-cluster` — full production
deployment targets the ThreePhoenix K3s HA cluster. Development/staging
can proceed on a single-node k3s instance.
- Depends on: `railiance/phase-0-operational-baseline` — cert-manager, TLS,
backup strategy must be operational before going live.
## Tasks
### T01 — Phase 0: Vault & secret bootstrap (single-credential principle)
```task
id: NK-WP-0001-T01
state_hub_task_id: 7992528c-d533-44e5-bcce-f92aaa2b75b2
status: done
priority: critical
commit_0a: c576188
note: Phase 0a complete (gen-secrets.sh, pack-bundle.sh, README). Phase 0b (Vault in-cluster) follows T02 cluster deployment.
```
**Decision D1 applies:** Two-phase vault strategy.
**Phase 0a — Pre-cluster KeePassXC bootstrap (do this first, before K8s):**
Create a KeePassXC `.kdbx` database as the initial secret store. Keep the
KeePassXC master password in a personal password manager. Generate and store
all bootstrap secrets inside KeePassXC:
- privacyIDEA: `SECRET_KEY` (64+ chars), `PI_PEPPER` (32+ chars),
`PI_ENCFILE` content (`pi-manage create_enckey`).
- PostgreSQL: root + `keycloak` + `privacyidea` user passwords.
- Keycloak: admin bootstrap secret + DB password.
- TLS: ACME account key (if not delegated fully to cert-manager).
- Break-glass: admin credentials + offline recovery OTP seed.
Export an age-encrypted ops bundle (encrypted tar of all secret YAML
manifests). Store offsite.
**Phase 0b — HashiCorp Vault in-cluster (after T02, once K3s is running):**
Deploy HashiCorp Vault in the cluster (Helm chart). Migrate secrets from
KeePassXC into Vault. Enable K8s encryption-at-rest. Deploy External Secrets
Operator (ESO) — **decided D4**: ESO reconciles Vault secrets into standard
K8s Secrets, compatible with plain Helm charts without Vault-specific
annotations. KeePassXC remains the source of truth for dev/test/sandbox
systems that do not connect to the cluster Vault.
**Done when:** KeePassXC created and all secrets generated (0a). Vault
deployed in-cluster, secrets migrated, ESO operational and injecting secrets
into at least one test workload (0b). Encrypted ops bundle exported and
stored offsite.
---
### T02 — Phase 1: K8s foundations (namespaces, NetworkPolicies, cert-manager)
```task
id: NK-WP-0001-T02
state_hub_task_id: 721ca6b2-0cf4-4008-a966-87b1563550fa
status: done
priority: high
commit: ee794a6
note: Manifests committed. Apply with sso-mfa/k8s/README.md apply order; verify-t02.sh checks done-criteria.
```
**Prerequisite:** T01 Phase 0a (KeePassXC bootstrap) must be complete — all
secrets generated and encrypted ops bundle exported before cluster work begins.
Create namespaces: `sso`, `mfa`, `databases`. Verify cert-manager is
installed and functional on the K3s cluster (Traefik ingress). Define and
apply NetworkPolicies to prevent lateral movement:
- Only ingress controller reaches Keycloak/privacyIDEA service ports.
- Only Keycloak pods call the privacyIDEA API.
- Only app pods/ingress reach Keycloak.
- DB pods reachable only from `sso` and `mfa` namespaces.
Verify StorageClass for PVCs.
**Done when:** namespaces exist, NetworkPolicies applied and tested (verify
denied paths), cert-manager issues a test certificate.
---
### T03 — Phase 2: PostgreSQL deployment (Keycloak + privacyIDEA DBs)
```task
id: NK-WP-0001-T03
state_hub_task_id: 7fa60004-deb2-4db5-a470-f95dda07f6ab
status: done
priority: high
commit: TBD
note: Manifests committed. Restore drill required before marking fully done in production.
```
Deploy PostgreSQL via CloudNativePG operator (preferred: aligns with
ThreePhoenix HA posture) or Bitnami Helm chart as fallback. Create:
- Database `keycloak_db`, user `keycloak`
- Database `privacyidea_db`, user `privacyidea`
Store DB credentials as K8s Secrets injected from Vault (T01 Phase 0b must
be complete, or use placeholder K8s Secrets until Vault is live).
Configure automated DB backups to object storage (S3 or MinIO).
**Run a restore drill before proceeding** — a failed restore later is a
critical blocker.
**Done when:** both DBs live, credentials in K8s Secrets, backup running,
restore drill passed.
---
### T04 — Phase 3: Deploy privacyIDEA (MFA core)
```task
id: NK-WP-0001-T04
state_hub_task_id: 6ad1296a-a488-4031-b665-f77030e971ed
status: cancel
priority: high
note: Cancelled 2026-05-20. privacyIDEA deployment superseded by NK-WP-0003-T04 (privacyIDEA now runs in the live KeyCape stack on RAILIANCE01). This Keycloak-path variant is no longer pursued.
```
Deploy privacyIDEA via `gpappsoft/privacyidea` Helm chart (Artifact Hub) or
custom manifests (Deployment + Service + Ingress + PVC + Secrets). Key
Helm values:
```yaml
database:
password: <from-vault>
privacyidea:
config:
SECRET_KEY: <from-vault>
PI_PEPPER: <from-vault>
encfile:
enabled: true
existingSecret: privacyidea-secrets
key: PI_ENCFILE
ingress:
enabled: true
hostname: pink.coulomb.social
tls: true
```
Create K8s Secrets: `privacyidea-config`, `privacyidea-enckey`,
`privacyidea-auditkeys`. Configure Ingress + TLS. Add rate-limiting and
WAF rules at Traefik level.
**Bootstrap (single-credential moment):**
1. `kubectl exec` into pod, run `pi-manage admin add pi-admin` — password
comes from vault (only time a password is typed).
2. Immediately enroll MFA for `pi-admin` (TOTP or hardware token).
3. Create `trigger-admin` with `triggerchallenge` right only.
4. Apply policies: WebUI restricted to VPN/office IPs; MFA required for
all admin actions.
**Done when:** privacyIDEA reachable at pink.coulomb.social with valid TLS,
pi-admin enrolled with MFA, trigger-admin created, rate-limiting active.
---
### T05 — Phase 4: Deploy Keycloak (SSO core)
```task
id: NK-WP-0001-T05
state_hub_task_id: b9f73aa6-9035-4643-9905-64e73a29b298
status: cancel
priority: high
note: Migrated to NK-WP-0011 (enterprise federation / SAML). Refined there against the deployed KeyCape stack and the OpenBao/flex-auth architecture.
```
Build a **custom Keycloak image** that includes the privacyIDEA Provider JAR:
```dockerfile
FROM quay.io/keycloak/keycloak:<version>
COPY PrivacyIDEA-Provider.jar /opt/keycloak/providers/
RUN /opt/keycloak/bin/kc.sh build
```
Deploy via plain Helm chart (official Keycloak Operator CRD-based or
codecentric KeycloakX Helm chart; **decision D3: plain Helm first, Flux
later**). Configure:
- DB: `keycloak_db` (credentials from Vault / K8s Secret)
- Ingress + TLS: `keycloak.yourdomain.com` (Traefik + cert-manager)
- Hostname strictness + proxy mode (Traefik forward headers)
- Metrics/logging (Prometheus annotations)
- Admin bootstrap secret from vault
- Realm import strategy: GitOps-friendly (realm JSON in git or CR)
**Done when:** Keycloak reachable with valid TLS, admin console accessible,
custom image with privacyIDEA JAR deployed and verified.
---
### T06 — Phase 5: Realm config & MFA authentication flow
```task
id: NK-WP-0001-T06
state_hub_task_id: 3b6379a4-a27b-4d25-82be-bc600879f036
status: cancel
priority: medium
note: Migrated to NK-WP-0011 (enterprise federation / SAML).
```
In Keycloak:
1. Create/configure realm. **Decision D2 applies:** identity source of truth
is Keycloak-internal users. LDAP/AD and Entra federation is deferred to
the enterprise tier (not in scope for this workplan phase).
2. Create Authentication Flow "privacyIDEA Browser":
- Add privacyIDEA execution step (REQUIRED)
- Config: privacyIDEA URL = `https://pink.coulomb.social`, service account
= `trigger-admin` (secret from K8s Secret)
- Optional: bypass group (break-glass) with strict restrictions + alerts
3. Set this flow as the default browser flow.
4. Require MFA step-up for admin console and sensitive OIDC clients.
Test:
- Normal user: password → MFA OTP → session established
- Admin console: MFA required
- Failure modes: wrong OTP, token missing, privacyIDEA unreachable
- Break-glass: bypass works, alert fires
**Done when:** end-to-end auth works for normal and admin paths, all failure
modes handled gracefully.
---
### T07 — Phase 6: User management, policies & self-service portal
```task
id: NK-WP-0001-T07
state_hub_task_id: c7cf902a-b480-4545-a536-293070945206
status: cancel
priority: medium
note: Migrated to NK-WP-0011 (enterprise federation / SAML).
```
**Decision D2 applies:** identity source of truth is Keycloak-internal with
the privacyIDEA Keycloak resolver. Implement (not decide):
- Configure privacyIDEA 3.12+ Keycloak user resolver to align Keycloak
users with privacyIDEA token ownership.
- LDAP/Entra federation: out of scope for this phase. Registered as
extension point EP-NK-001 (State Hub) for future enterprise-tier work.
Define policies in privacyIDEA:
- Allowed token types: TOTP, hardware (YubiKey), passkey
- Enrollment rules (who can self-enroll, which token types)
- Admin rights separation: super-admin vs. helpdesk-admin
Enable self-service portal at `pink-account.coulomb.social` for user token
enrollment/replacement.
Configure auditing and log shipping: privacyIDEA audit logs + Keycloak
events → centralized logging (ELK/Loki or equivalent). Token lifecycle
policies: enrollment, revocation, re-enrollment on device loss.
**Bootstrap user management (D2 + D5 — Local Identity):**
The pre-Keycloak user store is implemented as the `local-identity` capability.
See [NK-WP-0002](NK-WP-0002-local-identity.md) and
[docs/LocalIdentity.md](../docs/LocalIdentity.md). NK-WP-0002 Stage 2
produces Keycloak-compatible user exports (`local-identity export --all`)
that feed the realm bulk-import during T06. Once T06 is operational,
Local Identity should be explicitly migrated away from for that instance.
**Done when:** policies documented and applied, self-service portal live,
audit logs flowing, Keycloak resolver configured.
---
### T08 — Phase 7: Backups, DR, break-glass & monitoring
```task
id: NK-WP-0001-T08
state_hub_task_id: 9cbd1d89-b5bf-491e-9d16-b1c7d57076fb
status: cancel
priority: medium
note: Migrated to NK-WP-0011 (enterprise federation / SAML).
```
**Backups:**
- DB backups: Keycloak + privacyIDEA (Velero or CloudNativePG scheduled
backup to S3/MinIO). Test restore.
- privacyIDEA encryption/audit key Secrets: encrypted export, versioned.
- Keycloak realm exports: stored as JSON in git (GitOps-friendly).
- Vault unseal keys and root token: offline copy in KeePassXC.
**Disaster recovery drill** (mandatory before production):
1. Restore DB + keys into a fresh namespace.
2. Verify token validation still works — this catches key/secret mistakes.
**Break-glass procedure:**
- Disabled-by-default Keycloak admin path or group exemption.
- Break-glass credentials stored offline + vault. Alert (PagerDuty/webhook)
on every use.
**Monitoring:**
- Prometheus scraping Keycloak + privacyIDEA metrics.
- Grafana dashboards: auth success/failure rates, MFA challenge latency,
token count by type.
- Alert: privacyIDEA unreachable (blocks all logins).
**Final validation:**
- All external traffic: Ingress + HSTS + strict TLS.
- NetworkPolicies verified (no unintended open paths).
- End-to-end: app → Keycloak → privacyIDEA OTP → SSO session established.
**Done when:** DR drill passed, monitoring live, break-glass procedure
documented and tested, HSTS and NetworkPolicies verified.
---
## Deliverables Checklist
- [ ] KeePassXC vault created; all secrets generated and encrypted ops bundle exported
- [ ] HashiCorp Vault deployed in-cluster; secrets migrated from KeePassXC
- [ ] Secret injection strategy chosen and operational (ESO + Vault or Vault Agent)
- [ ] `sso`, `mfa`, `databases` namespaces + NetworkPolicies deployed
- [ ] TLS everywhere via cert-manager (Traefik ingress)
- [ ] PostgreSQL live; both DBs created; backup + restore tested
- [ ] privacyIDEA running at `pink.coulomb.social`; pi-admin MFA enrolled;
trigger-admin created with least-privilege rights
- [ ] Keycloak running from custom image including privacyIDEA Provider JAR
- [ ] Keycloak "privacyIDEA Browser" flow enforced as default
- [ ] Realm exported to git; admin secret from vault
- [ ] Self-service portal live; token lifecycle policies defined
- [ ] DR drill passed; monitoring live; break-glass documented and tested
## Open Questions
See `DECISIONS.md` for the three resolved decisions (D1D3).
Two pending decisions have been raised; see State Hub for full detail.
All five decisions are now resolved. See `DECISIONS.md` for D1D3 rationale;
State Hub decisions `aca69951` (D4) and `d74e2b11` (D5) for the full records.
| Artefact | Item | Status |
|----------|------|--------|
| Task `007415ef` → [repo:custodian] | Create ecosystem ADR for AI-first principles (D3) | Open; custodian to action |
| EP-NK-001 (`513a7644`) | LDAP/AD/Entra federation | Open; enterprise tier |

View File

@@ -0,0 +1,240 @@
---
id: NK-WP-0002
type: workplan
title: "Local Identity — Bootstrap User Store & Minimal OIDC"
domain: infotech
status: finished
owner: worsch
topic_slug: netkingdom
state_hub_workstream_id: 7c9021b1-319c-4b4a-a8be-0642239a1893
created: "2026-03-01"
updated: "2026-03-05"
---
# Local Identity — Bootstrap User Store & Minimal OIDC
## Summary
Implement a zero-dependency, file-based user management capability for
net-kingdom environments that do not yet have (or do not need) a running
Keycloak instance. Local Identity derives the primary user from the Linux
identity, auto-generates test users, provides a sandbox→production mapping
mechanism, and (in Stage 3) a minimal native OIDC provider for dev/test use.
See [docs/LocalIdentity.md](../docs/LocalIdentity.md) for the full capability
description, design principles, user schema, and risk mitigations.
## Context
Resolved from Decision D5 (2026-03-01, Tegwick). The decision chose to
implement Local Identity in-repo (not as a separate repository) in staged
workplan form, with a clear scope boundary and explicit out-of-scope
limitations. The minimal OIDC provider is to be implemented natively to avoid
heavy dependencies, keeping the bootstrap footprint minimal.
## Relationship to NK-WP-0001
Local Identity is complementary to the SSO & MFA Platform (NK-WP-0001). It
is not a blocking dependency: the SSO platform core deployment (T01T08) does
not require Local Identity to be complete. However:
- NK-WP-0001 T07 (user management) references Local Identity for the
pre-Keycloak bootstrap use case.
- Stage 2 of this workplan produces Keycloak-compatible user exports, which
feed the NK-WP-0001 T06 realm configuration.
- Once NK-WP-0001 is fully operational, Local Identity is no longer needed
for new instances and should be explicitly migrated away from.
## Architecture
```
~/.local-identity/
├── config.yaml # operator email, optional overrides
└── users/
├── <user>.yaml # primary user (derived from Linux identity)
├── <user>1.yaml # test user 1 (generated)
└── <user>2.yaml # test user 2 (generated)
local-identity CLI
├── init # derive + generate users
├── list / show # read operations
├── export # Keycloak-compatible JSON
├── security-check # permissions validation
└── serve # Stage 3: minimal OIDC server (localhost only)
```
**Secret injection:** Local Identity does not use Vault or K8s Secrets —
it operates entirely at the filesystem level, pre-cluster. This is by design.
## Tasks
### T01 — Stage 1: Core file store
```task
id: NK-WP-0002-T01
state_hub_task_id: 656652dd-05af-4fa4-95b2-17ce029ac7bd
status: done
priority: high
commit: 4491bea
```
Define YAML user schema (`schema_version`, `username`, `fullname`, `email`,
`environment`, `generated`, `source_user`, `production_identity`).
Implement:
- `local-identity init` — read `$USER`, `/etc/passwd` GECOS, prompt for
email if not in config; write primary user file; auto-generate two test
users with `N` / `+testN` suffixes
- `local-identity list` — tabular output of all users in the store
- `local-identity show <user>` — pretty-print user YAML
File store:
- Create `~/.local-identity/` with mode `700`
- Create user files with mode `600`
- Refuse to overwrite existing store without `--force`
Unit tests:
- GECOS name parsing edge cases (missing fields, non-ASCII)
- Test user derivation: username suffix, email `+testN` insertion
- Idempotency: `init` twice with `--force` produces identical output
**Done when:** init/list/show work; files created with correct permissions;
unit tests passing.
---
### T02 — Stage 2: Bootstrap integration
```task
id: NK-WP-0002-T02
state_hub_task_id: 5ea6e68d-7ebe-4ea7-b92e-61aac17ff04c
status: done
priority: high
commit: dad8365
```
Extend user schema with optional `production_identity` block (`username`,
`realm`). Test users carry `environment: local` and `generated: true`.
Implement:
- `local-identity export <user>` — emit Keycloak-compatible user JSON
(Keycloak Admin REST API representation); apply `production_identity`
mapping if present
- Schema validation: run against Keycloak user JSON schema on export; fail
with a clear diff if schema has drifted
Bootstrap tooling integration:
- `local-identity export --all` produces a bulk import file compatible with
Keycloak's partial import endpoint
- Document the import procedure in `docs/LocalIdentity.md`
Isolation guarantee:
- Production connectors (Keycloak, future services) must reject users with
`environment: local` — document the configuration required on the
Keycloak side (e.g. custom attribute check in authentication flow)
**Done when:** export produces valid Keycloak JSON; schema validation
catches drift; bulk import procedure documented and tested against a local
Keycloak dev instance.
---
### T03 — Stage 3: Minimal native OIDC provider
```task
id: NK-WP-0002-T03
state_hub_task_id: eb09d287-8e08-4c88-8bd1-6f0501ef5fc8
status: done
priority: medium
commit: d35823d
```
Implement `local-identity serve` — a minimal OIDC Authorization Code flow
server, implemented natively (no heavy OIDC library dependencies). Target:
a single binary or script that can be invoked without installing an
application framework.
Endpoints required:
- `GET /.well-known/openid-configuration` — OIDC discovery document
- `GET /auth` — authorization endpoint (redirects with `code`)
- `POST /token` — token endpoint (exchanges `code` for JWT)
- `GET /userinfo` — userinfo endpoint
Token requirements:
- JWT signed with a local key (generated on first `serve` invocation;
stored in `~/.local-identity/keys/`)
- Claims: `sub`, `iss: local-identity`, `aud`, `exp`, `iat`, `email`,
`name`, `preferred_username`
- `iss: local-identity` is intentionally non-routable; configure production
Keycloak to reject tokens with this issuer
TLS:
- Auto-generate a self-signed certificate on first run; store in
`~/.local-identity/tls/`
- Bind to `127.0.0.1` only; document that external binding is explicitly
unsupported
Scope:
- Supports `openid`, `profile`, `email` scopes
- No refresh tokens (stateless; re-auth required after expiry)
- No client secret validation (dev-mode only; all registered clients are
trusted)
**Done when:** a standard OIDC client library can authenticate against
`local-identity serve`; discovery, auth, token, and userinfo endpoints
pass an OIDC conformance smoke test; server refuses to bind to 0.0.0.0.
---
### T04 — Stage 4: Security hardening
```task
id: NK-WP-0002-T04
state_hub_task_id: 936de7fa-dfb4-48a2-804f-6b9bd7271a05
status: done
priority: medium
commit: e7bafd6
```
Permission enforcement:
- On every startup, validate `~/.local-identity/` mode `700` and all user
files mode `600`; fail loudly (exit 1 + clear error) if violated
- `local-identity security-check` command: explicit security audit with
per-check output (pass / warn / fail)
Audit log:
- Append-only log at `~/.local-identity/audit.log`; mode `600`
- Log entries: timestamp, command, username, outcome
- For `serve`: log every authentication event (auth request, token issued,
userinfo call)
Token hardening (for Stage 3 OIDC server):
- Configurable token TTL (default: 1 hour)
- Token revocation list stored in `~/.local-identity/revoked.json`
- `local-identity revoke-token <jti>` command
Documentation:
- Optional SELinux/AppArmor label guidance added to `docs/LocalIdentity.md`
- Security model section: threat model, assumptions, explicit non-guarantees
**Done when:** security-check passes cleanly on a correct install; audit
log records all auth events; startup fails on incorrect permissions; token
expiry and revocation functional.
---
## Deliverables Checklist
- [x] `~/.local-identity/` store initialised from Linux identity; test users generated
- [x] `local-identity list / show / export` working; Keycloak export validated
- [x] Minimal OIDC server passes conformance smoke test; binds localhost only
- [x] Filesystem permissions enforced on startup; `security-check` passes
- [x] Audit log recording all auth events
- [x] `docs/LocalIdentity.md` complete with import procedure and security model
- [x] NK-WP-0001 T07 migration procedure documented (Local Identity → Keycloak)
## Open Questions
None at this stage. All decisions resolved. Stage 3 language selection
(implementation language for the OIDC server) is a task-level detail to be
determined in T03.

View File

@@ -0,0 +1,173 @@
---
id: NK-WP-0006
type: workplan
title: Recursive platform identity and security architecture
domain: infotech
repo: net-kingdom
status: finished
owner: Bernd Worsch
topic_slug: netkingdom
created: 2026-05-17
updated: 2026-05-18
depends_on:
- NK-WP-0001
- NK-WP-0004
- NK-WP-0005
state_hub_workstream_id: "2eb8a5e0-4e33-4ed3-8996-a2eec3aad862"
---
# NK-WP-0006 - Recursive Platform Identity and Security Architecture
## Goal
Make the platform identity and security architecture explicit enough that
Coulomb can be onboarded as the first internal/reference tenant without
accidentally becoming the platform root of trust.
The workplan turns the recursive insight into operational structure:
bootstrap plane, platform control plane, tenant plane, IAM Profile,
flex-auth authorization, Topaz runtime, privacyIDEA MFA/token handling,
OpenBao runtime secret authority, and safe orchestration boundaries.
## Context
The current platform work is both building the Coulomb infrastructure and
creating reusable infrastructure for later use cases. That means Coulomb
is tenant zero/reference tenant inside its own future platform. This is a
useful design pressure, but only if the tenant/control-plane separation
is made explicit.
NetKingdom owns the canonical identity and security architecture.
Railiance owns deployment layering. flex-auth provides the practical
reference implementation for CARING authorization semantics. key-cape and
Keycloak implement identity profiles in different operating modes.
## Scope
In scope:
- document the three-plane architecture
- define platform-root versus tenant authority
- define how NetKingdom, key-cape, Keycloak, privacyIDEA, flex-auth,
Topaz, OpenBao, and Railiance relate
- define bootstrap-to-runtime trust states
- update related workplans and ADRs when implementation details become
concrete
- identify whether a dedicated orchestration repo is justified
Out of scope:
- implementing flex-auth adapters
- deploying Keycloak, key-cape, privacyIDEA, Topaz, or Railiance services
- deploying OpenBao itself
- designing customer-specific tenant policy
- replacing existing Railiance layer ownership
## Tasks
```task
id: NK-WP-0006-T1
status: done
priority: high
state_hub_task_id: "3e1c432a-f1ef-4c96-bb7a-79d1b955cd82"
```
Document the recursive multi-tenant identity/security architecture in
`docs/platform-identity-security-architecture.md`.
```task
id: NK-WP-0006-T2
status: done
priority: high
state_hub_task_id: "194fe3d5-d47c-449e-a32d-50996fd39e66"
```
Record the architecture decision in an ADR so later repo work can point
to a stable decision.
```task
id: NK-WP-0006-T3
status: done
priority: high
state_hub_task_id: "842ba5a7-5199-490a-8af5-3150388e0d42"
```
Review flex-auth workplans and add tenant/control-plane implications:
CARING descriptors, policy packages, decision envelopes, Topaz adapter
scope, audit/explain records, and platform-root guardrails.
```task
id: NK-WP-0006-T4
status: done
priority: high
state_hub_task_id: "ce153339-f493-44ed-a2c5-befb578334fe"
```
Review NetKingdom credential/bootstrap workplans and add explicit trust
state transitions: bare host, cluster, secrets, bootstrap identity,
runtime identity, runtime authorization, tenant onboarding.
```task
id: NK-WP-0006-T5
status: done
priority: medium
state_hub_task_id: "6c9a3561-4e63-4acd-87a7-bf0f374fa6b2"
```
Map the first Coulomb tenant onboarding path: identity claims, tenant id,
resource registration, policy package import, Topaz initialization, and
audit readiness.
```task
id: NK-WP-0006-T6
status: done
priority: medium
state_hub_task_id: "27760e30-f773-4552-97f4-7fbe56507f9e"
```
Decide whether orchestration should stay as Railiance playbooks or become
a dedicated repo. Capture the decision as an ADR before implementation.
```task
id: NK-WP-0006-T7
status: done
priority: medium
state_hub_task_id: "f09519ac-cf97-4f8b-8a7b-6ff828bbd8d9"
```
Define production readiness checks for the security platform: MFA state,
secret rotation state, flex-auth policy state, Topaz health, audit sink,
and break-glass verification.
## Implementation Review - 2026-05-18
The recursive architecture remains the right framing. The refinement from
the current stack is that OpenBao is now part of the platform control
plane as the runtime secret authority. SOPS/age and emergency bundles
remain bootstrap and recovery mechanisms; they must not become the
long-lived runtime authority for every workload secret once OpenBao is
available.
Implemented refinements:
- `docs/platform-identity-security-architecture.md` now includes explicit
flex-auth/Topaz implications, Coulomb tenant onboarding, production
readiness checks, and OpenBao secret authority boundaries.
- `docs/adr/ADR-0007-security-orchestration-boundary.md` records that
orchestration stays in Railiance playbooks for now; a dedicated repo is
deferred until sequencing has a stable, cross-repo product surface.
- `workplans/NK-WP-0007-object-storage-sts-credential-vending.md` now
treats OpenBao as the runtime broker/audit option without letting it
replace flex-auth authorization or storage-native STS semantics.
- `workplans/NK-WP-0004-credential-management-foundation.md`,
`workplans/NK-WP-0005-agent-driven-credential-bootstrap.md`, and
`canon/standards/credential-management_v0.2.md` now distinguish
bootstrap credential handling from the OpenBao runtime-secret handoff.
State Hub task statuses should be synchronized to match this workplan.
## Acceptance Criteria
- Architecture docs distinguish bootstrap plane, platform control plane,
and tenant plane.
- Coulomb is represented as tenant zero/reference tenant, not platform
root.
- The role of NetKingdom, key-cape, Keycloak, privacyIDEA, flex-auth,
Topaz, OpenBao, and Railiance is clear.
- Follow-up workplans identify where flex-auth and bootstrap work need to
adapt.
- Any future orchestration repo is justified by an ADR before it is
created.

View File

@@ -0,0 +1,220 @@
---
id: NK-WP-0007
type: workplan
title: Object Storage STS Credential Vending
domain: infotech
repo: net-kingdom
status: finished
owner: codex
topic_slug: netkingdom
planning_priority: high
planning_order: 7
created: 2026-05-17
updated: 2026-05-18
depends_on:
- NK-WP-0004
- NK-WP-0005
- NK-WP-0006
state_hub_workstream_id: "3cbc81ec-7ad5-46cf-a4a0-fc5fe9873695"
---
# NK-WP-0007 - Object Storage STS Credential Vending
## Goal
Define and implement the canonical NetKingdom pattern for vending
short-lived object-storage credentials from verified identity and
policy decisions.
The intended runtime shape is:
1. key-cape or Keycloak issues and verifies NetKingdom IAM Profile
tokens.
2. flex-auth evaluates whether the subject may receive temporary S3
credentials for a specific bucket, prefix, action set, TTL, and
assurance level.
3. A small object-storage credential-vending service exchanges the
approved identity for storage-native temporary credentials.
4. Consumers such as artifact-store use temporary credentials without
owning the security policy.
## Context
Artifact-store needs to consume S3-compatible credentials, but the
credential-vending authority belongs to NetKingdom's identity and
security architecture. The surrounding ecosystem matters:
- key-cape is the lightweight NetKingdom IAM Profile implementation.
- Keycloak is the expanded-mode IAM implementation.
- Authelia, LLDAP, and privacyIDEA are backing components in the
lightweight stack, not object-storage policy owners.
- flex-auth owns policy-as-code decisions, resource/action vocabulary,
decision envelopes, delegated PDP adapters, and audit semantics.
- OpenBao is now part of the platform stack as the runtime secret
authority, dynamic credential broker where appropriate, and audit
source for secret access. It can broker or store credential material,
but it does not replace flex-auth authorization or provider-native STS
semantics.
- ops-warden and ops-bridge provide a useful precedent for short-lived
credentials and actor attribution, but they are SSH-specific and
should not be overloaded with object-storage credentials.
- Ceph RGW, MinIO/AIStor, AWS STS, and Cloudflare R2 are candidate
object-storage credential issuers.
## Scope
In scope:
- define the object-storage credential-vending trust model
- define resource/action vocabulary for flex-auth
- define claim, audience, assurance, actor, tenant, bucket, prefix,
action, TTL, revocation, and audit requirements
- define lightweight-mode behavior with key-cape plus Authelia, LLDAP,
and privacyIDEA
- define expanded-mode behavior with Keycloak
- compare native STS paths for Ceph RGW, MinIO/AIStor, AWS STS, and
Cloudflare R2
- decide whether the vendor is a standalone NetKingdom service, a small
controller, or a reusable library plus CLI
- create consumer guidance for artifact-store and other S3 clients
Out of scope:
- implementing artifact-store S3 adapter refresh behavior
- deploying the object-storage backend itself
- replacing flex-auth with provider-specific bucket policies
- putting object-storage policy inside key-cape, ops-warden, or
ops-bridge
- letting OpenBao root/admin authority become the object-storage policy
model
## Recursive Platform Implications
This workplan depends on NK-WP-0006, so object-storage credential vending
must honor the platform/tenant split:
- `tenant:platform` may administer the vending service, OpenBao mounts,
storage backends, policy import pipeline, and audit retention.
- `tenant:coulomb` and future tenants may request scoped credentials only
for registered tenant resources.
- flex-auth decision envelopes must include tenant id, protected-system
id, bucket or prefix, action set, TTL, assurance evidence, obligations,
deny reasons, and audit correlation ids.
- CARING descriptors must mark whether a request is platform-scoped or
tenant-scoped; platform-scoped descriptor use is rare, reviewed, and
auditable.
- Topaz is the first delegated PDP runtime behind flex-auth. Its data and
policy loading must not give a tenant administrator control over
platform policies.
- OpenBao may broker, lease, audit, or store temporary credential
material after flex-auth approval. OpenBao must not become the source of
object-storage authorization policy, and tenants must not receive
OpenBao root tokens, unseal/recovery material, platform mounts, or
global auth-method control.
## Tasks
```task
id: NK-WP-0007-T1
status: done
priority: high
state_hub_task_id: "3b50c48f-1ab2-4631-b176-d49d9d705f1e"
```
Document the target architecture in
`docs/object-storage-sts-credential-vending.md`, including actors,
trust boundaries, token flow, policy decision flow, credential lease
flow, and failure modes.
```task
id: NK-WP-0007-T2
status: done
priority: high
state_hub_task_id: "5b942d22-6f29-4975-88fb-e3e5bcaf4029"
```
Define the flex-auth resource/action model for object storage:
protected-system id, bucket resources, prefix resources, actions
(`s3:GetObject`, `s3:PutObject`, `s3:DeleteObject`, listing,
multipart operations), TTL limits, obligations, and deny reasons.
```task
id: NK-WP-0007-T3
status: done
priority: high
state_hub_task_id: "8d27e5b4-9bbb-4a53-a079-0df1047d755e"
```
Define the IAM Profile requirements for credential vending:
accepted issuers, audiences, service-account subjects, human/admin
subjects, MFA/assurance claims, emergency principals, and local-dev
issuer restrictions.
```task
id: NK-WP-0007-T4
status: done
priority: medium
state_hub_task_id: "c0c4f297-6cff-419b-9ce3-be5537c92e93"
```
Assess backend STS implementations and write a decision record covering
Ceph RGW STS, MinIO/AIStor STS, AWS STS, Cloudflare R2 temporary
credentials, and when OpenBao should broker, lease, audit, or store the
resulting credential material.
```task
id: NK-WP-0007-T5
status: done
priority: medium
state_hub_task_id: "ccb10b2d-6378-4824-90b1-c31bd882d93d"
```
Prototype the smallest credential-vending interface: CLI or HTTP
request shape, normalized response shape, lease metadata, audit event,
OpenBao lease/audit metadata where used, and a
`credential_process`-compatible option for SDK consumers.
```task
id: NK-WP-0007-T6
status: done
priority: medium
state_hub_task_id: "63c6859b-980e-44da-a5a6-b92a8a3225dd"
```
Create integration guidance for artifact-store and other consumers:
environment variables, `AWS_SESSION_TOKEN`, refresh behavior, sidecar or
controller refresh options, and prohibited patterns such as long-lived
root access keys.
## Implementation Review - 2026-05-18
Implemented as architecture and decision artifacts:
- `docs/object-storage-sts-credential-vending.md` defines the target
architecture, actors, trust boundaries, token flow, flex-auth
vocabulary, IAM Profile requirements, backend assessment, OpenBao
role, request/response prototype, audit event, failure modes, and
consumer guidance.
- `docs/adr/ADR-0008-object-storage-sts-credential-vending.md` records
the decision to use a provider-neutral NetKingdom vending boundary with
provider-native temporary credential mechanisms where possible.
The implementation deliberately stops before building a live vending
service. Service implementation belongs in a follow-up workplan once
artifact-store has session-token/refresh support and the Railiance
OpenBao bootstrap/unseal/break-glass work is ready.
## Acceptance Criteria
- NetKingdom has a canonical, provider-neutral pattern for object-storage
STS credential vending.
- flex-auth is the policy decision point for bucket/prefix/action/TTL
authorization.
- OpenBao is treated as runtime secret/lease infrastructure where useful,
not as the canonical authorization policy engine.
- key-cape and Keycloak are treated as IAM Profile implementations, not
object-storage policy engines.
- ops-warden and ops-bridge remain SSH/tunnel-specific but their
short-lived credential lessons are reused where appropriate.
- artifact-store has enough guidance to consume temporary credentials
without owning the vending authority.

View File

@@ -0,0 +1,285 @@
---
id: NK-WP-0008
type: workplan
title: IT Security Architecture Patterns Infospace
domain: infotech
repo: net-kingdom
status: done
owner: codex
topic_slug: netkingdom
planning_priority: high
planning_order: 8
created: 2026-05-17
updated: 2026-05-19
depends_on:
- NK-WP-0006
state_hub_workstream_id: "053c6d96-9396-40c9-a2e5-c36531e7810d"
execution_repo: infospace-bench
infospace_path: infospaces/patterns-of-it-securita-architecture---
# NK-WP-0008 - IT Security Architecture Patterns Infospace
## Goal
Create a curated infospace of reusable IT security architecture patterns
for NetKingdom-enabled infrastructures.
The infospace should be a reference library of patterns, tradeoffs,
threats, implementation variants, and canonical NetKingdom mappings. It
should help us recognize patterns such as STS credential vending,
workload identity, secret zero avoidance, break-glass access, delegated
authorization, short-lived certificates, and policy-as-code before they
become scattered repo-local folklore.
## Context
The platform now spans identity, MFA, policy, SSH certificates, reverse
tunnels, object storage, artifact storage, Kubernetes platform services,
and secrets management. Several patterns repeat across repos:
- key-cape and Keycloak implement OIDC identity contracts.
- flex-auth implements policy-as-code authorization decisions.
- ops-warden issues short-lived SSH certificates.
- ops-bridge consumes short-lived SSH credentials and records actor
attribution.
- artifact-store consumes object storage and needs temporary S3
credential support.
- Railiance platform services need a canonical secrets manager and
object-storage integration.
An infospace makes these repeatable architectural patterns explicit,
searchable, comparable, and teachable.
## Seeded Infospace
Bernd seeded the working corpus in `infospace-bench`:
```text
/home/worsch/infospace-bench/infospaces/patterns-of-it-securita-architecture/
```
The current seed is:
```text
genesis/InitialExploration.md
```
That file already sketches the two intended collections: a security
capability catalog and a security architecture pattern catalog, with
readiness levels and mappings to standards such as NIST CSF, CIS, OWASP,
SLSA, and OpenSSF.
NK-WP-0008 will therefore use `infospace-bench` as the canonical working
space instead of creating a separate `docs/security-patterns/` tree in
`net-kingdom`. `net-kingdom` remains the owner of the NetKingdom security
architecture mapping; `infospace-bench` owns the concrete infospace
artifact lifecycle, manifests, evaluation reports, and exports.
## Scope
In scope:
- promote the seeded directory into a valid `infospace-bench` infospace
with `infospace.yaml`, `artifacts/index.yaml`, and the standard layout
- import `genesis/InitialExploration.md` as the seed source artifact
- define capability and pattern document templates inside the infospace
- capture initial capability, pattern, readiness, and mapping artifacts
- record source references and current product/tool options
- connect patterns to implementation repos and workplans
- distinguish canonical patterns from experiments and anti-patterns
Out of scope:
- implementing every pattern
- building new lower-level `infospace-bench` engine features
- replacing ADRs
- duplicating vendor documentation
- using `net-kingdom/docs/security-patterns/` as the primary corpus
- writing full tutorials; tutorials are handled by NK-WP-0009
## Tasks
### T01 - Promote The Seed Into A Valid Infospace
```task
id: NK-WP-0008-T1
status: done
priority: high
state_hub_task_id: "d1b7213c-3315-49d2-90c9-efdf2bea3563"
```
Promote
`/home/worsch/infospace-bench/infospaces/patterns-of-it-securita-architecture`
from a genesis note into a valid `infospace-bench` project: create
`infospace.yaml`, `artifacts/index.yaml`, the required artifact/output
directories, and a manifest entry for `genesis/InitialExploration.md`.
Define the initial artifact taxonomy for:
- capabilities
- patterns
- readiness levels
- mappings
- source references
- generated reports
### T02 - Extract The Initial Capability And Pattern Catalogs
```task
id: NK-WP-0008-T2
status: done
priority: high
state_hub_task_id: "59966187-27f1-4b9c-9dfc-e59d11ff115c"
```
Extract the first structured artifacts from the seeded exploration:
- a security capability catalog
- a security architecture pattern catalog
- readiness levels RL0-RL4
- a production readiness baseline
Initial patterns must include STS credential vending, workload identity,
secret zero avoidance, dynamic secrets, short-lived SSH certificates,
delegated authorization, break-glass access, tenant isolation, central
audit ledger, policy-as-code admission, and supply-chain provenance.
Each pattern artifact should use a repeatable template: problem, context,
forces, solution, implementation sketch, failure modes, related
capabilities, maturity, verification, and references.
### T03 - Map Patterns To NetKingdom And Ecosystem Ownership
```task
id: NK-WP-0008-T3
status: done
priority: medium
state_hub_task_id: "927c08a5-1a7e-4634-a514-0f562e286708"
```
Map each capability and pattern to the owning repos, components, and
workplans:
- `net-kingdom`, NK-WP-0006, NK-WP-0007, NK-WP-0008, NK-WP-0009
- `key-cape`, Keycloak, Authelia, LLDAP, privacyIDEA
- `flex-auth`, Topaz, CARING descriptors, decision envelopes
- `railiance-platform`, OpenBao, Ceph RGW, MinIO-compatible stores
- `ops-warden`, `ops-bridge`, short-lived SSH and agent access
- `artifact-store`, object storage, STS consumers, artifact integrity
- relevant standards and references from the seed document
This mapping should distinguish platform ownership, product/application
ownership, tenant responsibility, and external provider responsibility.
### T04 - Build The Index, Maturity Matrix, And Report
```task
id: NK-WP-0008-T4
status: done
priority: medium
state_hub_task_id: "884626ea-243e-4806-9267-77ef643158b7"
```
Create the first infospace index/report with capability status, pattern
maturity, owning repo, implementation links, open decisions, and gaps.
The report should make it easy to answer:
- which patterns are canonical versus experimental
- which patterns already have NetKingdom/Railiance implementation anchors
- which patterns need ADRs, workplans, or tutorials
- which patterns feed NK-WP-0009 tutorials
### T05 - Define Admission And Review Criteria
```task
id: NK-WP-0008-T5
status: done
priority: medium
state_hub_task_id: "d3b29f3d-0da5-43b5-a93a-d95fb8a0ceef"
```
Add review criteria for admitting new patterns: vendor neutrality,
threat-model clarity, open-source/commercial implementation options,
operability, auditability, failure-mode behavior, readiness-level fit,
evidence quality, and ownership clarity.
Define when a pattern is allowed to graduate from:
```text
seed -> draft -> reviewed -> canonical -> deprecated
```
The criteria should be expressed as an infospace evaluation/checklist so
future pattern additions can be reviewed consistently.
## Implementation Review - 2026-05-19
NK-WP-0008 has been implemented in `infospace-bench` at:
```text
/home/worsch/infospace-bench/infospaces/patterns-of-it-securita-architecture/
```
Created artifacts:
- `infospace.yaml`
- `artifacts/index.yaml`
- `artifacts/entities/security-capability-catalog.md`
- `artifacts/entities/security-architecture-pattern-catalog.md`
- `artifacts/entities/security-readiness-levels.md`
- `artifacts/relations/netkingdom-ownership-map.md`
- `artifacts/generated/security-pattern-index.md`
- `artifacts/generated/pattern-admission-review.md`
- `reports/initial-security-pattern-report.md`
Population pass:
- copied the NetKingdom object-storage STS credential-vending document,
platform identity/security architecture document, ADR-0008, and
Railiance OpenBao platform secrets service note into
`artifacts/sources/`
- added `artifacts/entities/capability-object-storage-access.md`
- added `artifacts/entities/pattern-sts-credential-vending.md`
- added `artifacts/relations/sts-credential-vending-relationship-map.md`
- added `artifacts/generated/sts-credential-vending-extraction.md`
- registered the new STS/OpenBao evidence, capability, pattern, relation
map, extraction, index, and report edges in `artifacts/index.yaml`
- normalized relationship direction so the infospace graph remains
connected and acyclic
Catalogue population pass:
- added first-class pattern artifacts for the initial NetKingdom pattern
set beyond STS credential vending: workload identity, secret zero
avoidance, dynamic secrets, short-lived SSH certificates, delegated
authorization, break-glass access, tenant isolation, central audit
ledger, policy-as-code admission, supply-chain provenance, network
default deny, object-level authorization check, human/agent identity
split, and tenant context propagation
- added `artifacts/generated/research-pattern-normalization.md` to map
the broader `genesis/InitialExploration.md` research tables into the
first-class pattern set and future promotion candidates
- registered the pattern artifacts in `artifacts/index.yaml` with source
seed, catalog inclusion, ownership map, admission review, readiness,
and index summary relationships
Verification:
- `.venv/bin/python -m infospace_bench inspect infospaces/patterns-of-it-securita-architecture`
- `.venv/bin/python -m infospace_bench validate infospaces/patterns-of-it-securita-architecture`
- `.venv/bin/python -m infospace_bench metrics infospaces/patterns-of-it-securita-architecture` passed viability in snapshot `502d0933` with 16 artifacts, 100% coverage, one connected component, and zero consistency cycles
- `.venv/bin/python -m infospace_bench graph infospaces/patterns-of-it-securita-architecture --format mermaid`
- `.venv/bin/python -m pytest` passed with 179 passed, 2 skipped
## Acceptance Criteria
- `infospace-bench/infospaces/patterns-of-it-securita-architecture/`
is a valid infospace-bench project with a manifest and standard layout.
- Initial high-value security patterns are documented in a consistent
shape.
- Each pattern names the canonical NetKingdom mapping and the repos that
own implementation.
- The infospace distinguishes patterns, tutorials, ADRs, and vendor docs.
- State Hub task titles and descriptions reflect the concrete
infospace-bench workflow instead of generic placeholder task names.

View File

@@ -0,0 +1,352 @@
---
id: NK-WP-0010
type: workplan
title: Genesis Security Pattern Completion
domain: infotech
repo: net-kingdom
status: finished
owner: codex
topic_slug: netkingdom
planning_priority: medium
planning_order: 10
created: 2026-05-19
updated: 2026-05-19
depends_on:
- NK-WP-0008
unblocks:
- NK-WP-0009
execution_repo: infospace-bench
infospace_path: infospaces/patterns-of-it-securita-architecture
state_hub_workstream_id: "f4faf8b4-ae57-40cf-a881-6fe66ca6ad74"
---
# NK-WP-0010 - Genesis Security Pattern Completion
## Goal
Promote every security architecture and solution pattern explicitly
named in
`/home/worsch/infospace-bench/infospaces/patterns-of-it-securita-architecture/genesis/InitialExploration.md`
into a first-class infospace artifact.
NK-WP-0008 created the infospace and populated the first NetKingdom
pattern set. NK-WP-0010 closes the remaining catalogue gap: no pattern
mentioned in the genesis research should remain only as prose inside the
source note or as a candidate row in the normalization artifact.
## Context
The genesis file names a broad security pattern catalogue across seven
families:
- identity and access
- tenant isolation
- Kubernetes and platform
- secrets and cryptography
- application/API security
- supply chain
- detection and response
NK-WP-0008 already created first-class artifacts for the NetKingdom
initial pattern set, including STS credential vending, workload
identity, secret zero avoidance, dynamic secrets, short-lived SSH
certificates, delegated authorization, break-glass access, tenant
isolation, central audit ledger, policy-as-code admission, supply-chain
provenance, network default deny, object-level authorization,
human/agent identity split, and tenant context propagation.
This workplan should complete the literal genesis coverage while keeping
the distinction between:
- an exact pattern named by the research seed
- a NetKingdom canonical pattern
- an umbrella pattern that groups several exact seed patterns
- a future tutorial candidate for NK-WP-0009
## Scope
In scope:
- create or reconcile one first-class artifact for each exact pattern
name in the genesis security architecture pattern catalogue
- keep existing NK-WP-0008 pattern artifacts, adding aliases or related
links instead of duplicating them where an exact seed pattern is
already represented
- update `artifacts/index.yaml` with source, catalogue, ownership,
admission, readiness, index, and report relationships
- update `artifacts/generated/research-pattern-normalization.md` so it
becomes a completion map rather than a candidate-only map
- update the generated index, report, and ownership map
- preserve an acyclic, connected infospace graph
Out of scope:
- writing tutorials; that remains NK-WP-0009
- implementing platform services
- resolving every open architecture decision in the pattern artifacts
- replacing ADRs or vendor docs
## Genesis Pattern Inventory
This workplan targets the exact pattern names in the genesis file:
| Family | Patterns |
| --- | --- |
| Identity and access | Central Identity Provider; Identity Broker; Tenant Membership Boundary; Role Composition; Policy Decision Point / Policy Enforcement Point; Time-boxed Privilege Elevation; Break-glass Access; Human/Agent Identity Split |
| Tenant isolation | Namespace-per-Tenant; Cluster-per-Tenant; Cell-based Architecture; Shared Control Plane, Isolated Data Plane; Tenant Context Propagation; Tenant Data Partitioning |
| Kubernetes and platform | Secure Cluster Baseline; Policy-as-Code Admission Control; Pod Security Baseline/Restricted; Network Default Deny; Signed Image Admission; GitOps with Guardrails; Runtime Threat Detection |
| Secrets and cryptography | External Secrets Operator; Sealed Secret / Encrypted Git Secret; Short-lived Credentials; Key-per-Tenant; Certificate Automation |
| Application/API security | API Gateway as Security Boundary; Backend-for-Frontend; Object-Level Authorization Check; Schema-First API Security; Idempotent Command API; Secure File Upload Pipeline |
| Supply chain | Protected Main Branch; Dependency Update Bot; SBOM-per-Release; SLSA Build Provenance; Signed Container Images; Quarantined Build Runner |
| Detection and response | Security Event Taxonomy; Central Audit Ledger; Tenant Audit Log View; Incident Runbook Library; Kill Switch / Tenant Freeze; Token Revocation Sweep |
## Tasks
### T01 - Reconcile The Genesis Inventory
```task
id: NK-WP-0010-T1
status: done
priority: high
state_hub_task_id: "61160df5-7305-4a0f-a34d-2a763c29eab4"
```
Create a completion matrix from `genesis/InitialExploration.md` that
lists every exact seed pattern, current artifact coverage, aliases,
canonical NetKingdom mapping, owner, status, and whether a new artifact
is needed.
Update `artifacts/generated/research-pattern-normalization.md` so it
becomes the authoritative inventory for this workplan.
### T02 - Complete Identity And Access Patterns
```task
id: NK-WP-0010-T2
status: done
priority: high
state_hub_task_id: "dad43681-9404-47b8-b58c-39b7218c2542"
```
Create or reconcile first-class artifacts for:
- Central Identity Provider
- Identity Broker
- Tenant Membership Boundary
- Role Composition
- Policy Decision Point / Policy Enforcement Point
- Time-boxed Privilege Elevation
- Break-glass Access
- Human/Agent Identity Split
Existing break-glass and human/agent identity artifacts should be
retained and enriched. The PDP/PEP artifact may reference the existing
delegated authorization artifact, but the exact seed pattern must be
discoverable as a first-class artifact or explicit alias.
### T03 - Complete Tenant Isolation Patterns
```task
id: NK-WP-0010-T3
status: done
priority: high
state_hub_task_id: "dee39f82-aa3a-4824-ba61-7fbdbd5c3d21"
```
Create or reconcile first-class artifacts for:
- Namespace-per-Tenant
- Cluster-per-Tenant
- Cell-based Architecture
- Shared Control Plane, Isolated Data Plane
- Tenant Context Propagation
- Tenant Data Partitioning
Ensure these link to the existing tenant isolation and tenant context
propagation artifacts without flattening their different isolation
strengths and failure modes.
### T04 - Complete Kubernetes And Platform Patterns
```task
id: NK-WP-0010-T4
status: done
priority: high
state_hub_task_id: "19def7b4-4f1a-45ad-b15b-6a56e675be41"
```
Create or reconcile first-class artifacts for:
- Secure Cluster Baseline
- Policy-as-Code Admission Control
- Pod Security Baseline/Restricted
- Network Default Deny
- Signed Image Admission
- GitOps with Guardrails
- Runtime Threat Detection
Preserve the relationship to Railiance platform responsibilities,
admission policy, pod security, image provenance, network segmentation,
and detection coverage.
### T05 - Complete Secrets And Cryptography Patterns
```task
id: NK-WP-0010-T5
status: done
priority: high
state_hub_task_id: "622c3bbe-77a7-4049-b6f4-0cd1f54f3783"
```
Create or reconcile first-class artifacts for:
- External Secrets Operator
- Sealed Secret / Encrypted Git Secret
- Short-lived Credentials
- Key-per-Tenant
- Certificate Automation
Link these to OpenBao, secret-zero avoidance, dynamic secrets, STS
credential vending, credential bootstrap, tenant isolation, and
certificate lifecycle ownership.
### T06 - Complete Application And API Security Patterns
```task
id: NK-WP-0010-T6
status: done
priority: medium
state_hub_task_id: "e792f598-4dfc-4598-ba86-facd13cd8a12"
```
Create or reconcile first-class artifacts for:
- API Gateway as Security Boundary
- Backend-for-Frontend
- Object-Level Authorization Check
- Schema-First API Security
- Idempotent Command API
- Secure File Upload Pipeline
Ensure each artifact names where platform responsibility ends and
product/application responsibility begins.
### T07 - Complete Supply-Chain Patterns
```task
id: NK-WP-0010-T7
status: done
priority: medium
state_hub_task_id: "a43b189a-d1b4-4692-94d7-9c7e140808ca"
```
Create or reconcile first-class artifacts for:
- Protected Main Branch
- Dependency Update Bot
- SBOM-per-Release
- SLSA Build Provenance
- Signed Container Images
- Quarantined Build Runner
Relate these to artifact-store, signed image admission, policy-as-code
admission, build provenance, SBOM storage, and release evidence.
### T08 - Complete Detection And Response Patterns
```task
id: NK-WP-0010-T8
status: done
priority: medium
state_hub_task_id: "78a2d242-5a56-40a7-8499-ba7c72150700"
```
Create or reconcile first-class artifacts for:
- Security Event Taxonomy
- Central Audit Ledger
- Tenant Audit Log View
- Incident Runbook Library
- Kill Switch / Tenant Freeze
- Token Revocation Sweep
Retain the existing central audit ledger artifact and add explicit
patterns for event classification, tenant-visible projections,
response playbooks, containment, and credential revocation.
### T09 - Refresh Relationships, Indexes, And Reports
```task
id: NK-WP-0010-T9
status: done
priority: high
state_hub_task_id: "8ec9bc00-1f7b-4f34-b02e-33fdacda9da5"
```
Update the infospace manifest and narrative artifacts:
- `artifacts/index.yaml`
- `artifacts/entities/security-architecture-pattern-catalog.md`
- `artifacts/relations/netkingdom-ownership-map.md`
- `artifacts/generated/security-pattern-index.md`
- `artifacts/generated/pattern-admission-review.md`
- `artifacts/generated/research-pattern-normalization.md`
- `reports/initial-security-pattern-report.md`
The final graph must remain connected and acyclic.
### T10 - Verify Completion And Feed NK-WP-0009
```task
id: NK-WP-0010-T10
status: done
priority: medium
state_hub_task_id: "a5449bc6-8529-4350-822b-7c758bf790cb"
```
Run the infospace verification suite:
- `.venv/bin/python -m infospace_bench validate infospaces/patterns-of-it-securita-architecture`
- `.venv/bin/python -m infospace_bench metrics infospaces/patterns-of-it-securita-architecture`
- `.venv/bin/python -m infospace_bench graph infospaces/patterns-of-it-securita-architecture --format mermaid`
- `.venv/bin/python -m pytest`
Update State Hub progress, mark completed tasks, and add a handoff note
for NK-WP-0009 identifying which completed patterns should become
tutorials first.
## Implementation Evidence
Completed on 2026-05-19 in
`/home/worsch/infospace-bench/infospaces/patterns-of-it-securita-architecture`.
- Promoted all 44 exact genesis pattern names into first-class pattern
artifacts or retained exact existing artifacts.
- Preserved the nine NetKingdom umbrella/canonical pattern artifacts
created by NK-WP-0008 and linked them to the exact seed patterns.
- Refreshed `artifacts/index.yaml`, the pattern catalog, ownership map,
security pattern index, admission review, normalization matrix, and
initial report.
- Verification passed:
- `.venv/bin/python -m infospace_bench validate infospaces/patterns-of-it-securita-architecture`
- `.venv/bin/python -m infospace_bench metrics infospaces/patterns-of-it-securita-architecture`
with snapshot `7bf35f3b`, 69 artifacts, one connected component,
zero cycles, coverage `1.0`, and viability passed.
- `.venv/bin/python -m infospace_bench graph infospaces/patterns-of-it-securita-architecture --format mermaid`
- `.venv/bin/python -m pytest` with 181 passed and 2 skipped.
## Acceptance Criteria
- Every exact pattern name from the genesis pattern catalogue is
discoverable as a first-class artifact or explicit alias in the
infospace.
- `research-pattern-normalization.md` shows no unaccounted seed
patterns.
- The manifest registers all pattern artifacts and relationships.
- The generated index and report identify canonical, draft, seed, and
promotion-candidate patterns.
- `infospace_bench validate` passes.
- `infospace_bench metrics` passes viability with one connected
component and zero consistency cycles.
- NK-WP-0009 has a clear tutorial-priority handoff from the completed
pattern library.

View File

@@ -0,0 +1,222 @@
---
id: NK-WP-0012
type: workplan
title: "NetKingdom IAM Profile Specification"
domain: infotech
repo: net-kingdom
status: finished
owner: worsch
topic_slug: netkingdom
planning_priority: high
planning_order: 12
created: "2026-05-21"
updated: "2026-05-22"
depends_on:
- NK-WP-0006
state_hub_workstream_id: 9b8e4afc-eb71-47d9-8750-799a082b320a
enables:
- NK-WP-0011---
# NK-WP-0012 — NetKingdom IAM Profile Specification
> The IAM Profile is referenced everywhere as "the contract all applications
> target," but it does not exist as a net-kingdom artifact. A draft **v0.1
> exists in the-custodian canon** (`canon/standards/iam-profile_v0.1.md`),
> scoped "all-hubs" and Custodian-flavored. SCOPE.md says net-kingdom owns
> the IAM Profile. This workplan resolves that: net-kingdom becomes the
> canonical owner, and the profile is made provider-neutral, tenant- and
> agent-aware, and conformance-testable.
## Goal
Produce the **canonical, versioned NetKingdom IAM Profile** in net-kingdom
canon — the OIDC/PKCE contract every implementation issues and every
application and the authorization layer consume — together with an
**executable conformance check**.
The profile is the contract that makes the rest of the architecture
coherent:
- it is what `key-cape` (lightweight) and Keycloak (expanded) each
implement, interchangeably (capability ladder C1/C5);
- it is the identity input `flex-auth` consumes for authorization
decisions (responsibility map: the identity layer owns the claim
contract — that contract is this profile);
- it is the thing **NK-WP-0011-T6** runs conformance checks against, so
this workplan **enables** NK-WP-0011.
## Why now / what exists
The v0.1 draft is a strong base — discovery contract, Authorization Code +
PKCE human flow, service-account flow, required claims, token lifecycle,
emergency/break-glass, and a local-development profile. But it has gaps for
the current architecture:
| Gap in v0.1 | Needed because |
|---|---|
| Lives in the-custodian, scoped "all-hubs" | net-kingdom owns the profile (SCOPE.md, responsibility map) |
| Keycloak named as *the* reference provider | provider-neutral now: key-cape lightweight / Keycloak expanded are interchangeable implementations |
| Scope/role vocabulary is hub-specific (`hub:*`, `ops:*`, `fin:*`) | the core profile must be platform-neutral; hub/app scopes are downstream extensions |
| No tenant claim | recursive `tenant:platform` vs tenant model (NK-WP-0006) needs tenant in the token |
| Only human/service identities | architecture distinguishes human / service / **agent** principals |
| Assurance is implicit | flex-auth decision envelopes require explicit assurance evidence |
| No executable conformance check | NK-WP-0011-T6 and every implementation need a runnable contract test |
## Scope
In scope:
- ownership and reconciliation decision (ADR) with the-custodian v0.1
- a provider-neutral, platform-neutral **v0.2** profile in net-kingdom canon
- tenant- and agent-aware claims, and explicit assurance evidence
- the identity→authorization claim contract consumed by flex-auth
- an executable conformance check
- versioning and breaking-change governance for the profile
- migration of downstream references to the canonical net-kingdom spec
Out of scope:
- implementing the profile in key-cape or Keycloak (their repos own that)
- defining tenant- or application-specific scope vocabularies
- deploying any identity provider
## Tasks
```task
id: NK-WP-0012-T1
state_hub_task_id: 284dda38-b778-445a-a7dc-9b5a12fa380f
status: done
priority: high
```
**Ownership & reconciliation decision (ADR-0011).** Record that net-kingdom
is the canonical owner of the IAM Profile. Decide how the-custodian's
all-hubs v0.1 reconciles: net-kingdom owns the **core/platform profile**;
hub- and app-specific scope vocabularies (`hub:*`, `ops:*`, `fin:*`) become
**downstream extensions** that map back to the core, not part of it. Define
the profile's **versioning and breaking-change governance** (what a
breaking change is, how downstream is notified, how versions coexist).
```task
id: NK-WP-0012-T2
state_hub_task_id: 0070398d-b0a4-4c11-a6fa-000166e1108f
status: done
priority: high
```
**Author IAM Profile v0.2 (provider-neutral core).** Create
`canon/standards/iam-profile_v0.2.md` in net-kingdom. Carry forward the
solid v0.1 material — discovery contract, Authorization Code + PKCE human
flow, service-account flow, required/recommended claims, token lifecycle,
emergency/break-glass, local-development profile — and make it
**provider-neutral**: key-cape (lightweight) and Keycloak (expanded) are
named as interchangeable implementations, neither as "the" reference.
Remove hub-specific vocabulary from the core.
```task
id: NK-WP-0012-T3
state_hub_task_id: 6fc2a5e1-1480-42f1-86a2-3e714359e1ba
status: done
priority: high
```
**Extend for the recursive and agent model.** Add a **tenant** claim
(`tenant:platform` vs tenant id), formalize the **human / service / agent**
principal types and how each is represented, and define an explicit
**assurance evidence** claim (how authentication strength / MFA is conveyed
in the token). Align with NK-WP-0006 and the responsibility map.
```task
id: NK-WP-0012-T4
state_hub_task_id: 0e52ed45-afa7-4832-9d6a-1ebbbab43872
status: done
priority: high
```
**Define the identity→authorization claim contract.** Specify exactly which
claims the profile guarantees as inputs to flex-auth decision envelopes —
subject, issuer, audience, tenant, groups, roles, scopes, assurance — so
flex-auth treats the profile as normative input and never re-derives
identity. This is the contract named in the responsibility map.
```task
id: NK-WP-0012-T5
state_hub_task_id: f0a62e77-b781-4625-b8bd-d191b48af58e
status: done
priority: high
```
**Executable conformance check.** Build a runnable suite that validates an
issuer/implementation against the profile: discovery document completeness,
PKCE enforcement, claim shape, JWKS and key-rotation tolerance, token
validation (issuer/audience/expiry/signature), and rejection of
local-development issuers in production. This is the artifact NK-WP-0011-T6
consumes; it must run against both a key-cape and a Keycloak issuer.
```task
id: NK-WP-0012-T6
state_hub_task_id: a1fd53a9-526f-4d87-89db-6073710c885d
status: done
priority: medium
```
**Migration & cross-references.** Supersede or relink the-custodian v0.1
(deprecation note pointing at the net-kingdom canonical spec), and update
downstream references — `key-cape` and `flex-auth` interface docs,
NK-WP-0011, and any architecture docs — to cite the canonical net-kingdom
profile. Per ADR-0010, downstream **intents** are not touched; only
interface/reference docs.
## Acceptance Criteria
- The canonical IAM Profile lives in net-kingdom canon, versioned, and an
ADR records ownership and the reconciliation with the-custodian v0.1.
- The core profile is provider-neutral and platform-neutral (no
hub-specific scopes in the core; no single "reference provider").
- The profile carries tenant, principal-type (human/service/agent), and
assurance claims, aligned with the recursive model.
- The claims flex-auth consumes are specified as a normative contract.
- An executable conformance check exists and passes against both a
key-cape and a Keycloak issuer.
- Versioning and breaking-change governance is documented.
- Downstream reference docs point at the canonical spec; the custodian v0.1
carries a deprecation/relocation note.
## Completion Notes
- ADR: `docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md`
- Canonical profile: `canon/standards/iam-profile_v0.2.md`
- Executable conformance suite:
`tools/iam-profile-conformance/iam_profile_conformance.py`
- Fixture tests cover key-cape-like and Keycloak-like issuers, local-dev
rejection in production mode, tenant claim enforcement, provider-native
role normalization warnings, and delegated-agent claim shape.
- Cross-repo reference docs updated without touching downstream
`INTENT.md`: key-cape README/spec references now point at v0.2, and
flex-auth consumption docs plus claim fixtures now include v0.2 tenant,
principal, and assurance inputs.
## Dependencies & Sequencing
- **Depends on NK-WP-0006** for the recursive tenant model the claims encode.
- **Enables NK-WP-0011** — T6 (IAM Profile conformance) cannot pass without
the spec and the conformance check from this workplan. NK-WP-0012 should
land before NK-WP-0011-T6.
- Coordinates with **flex-auth** (the consumed claim contract, T4) and with
**key-cape**/**Keycloak** as the implementations the conformance check
runs against — those repos implement, this workplan specifies and tests.
## Resolved Questions
- Canonical role claim: `roles` is canonical. `realm_access.roles` is a
transitional/provider-native source that must be mapped before
production consumption.
- Audience granularity: the core profile requires the receiving service
in `aud`; endpoint/resource granularity belongs to flex-auth
resource/action policy.
- Agent principals differ from service accounts through
`principal_type: agent`, an `agent` object, and delegated actor context
(`actor_sub` or `act.sub`) when applicable.
- The conformance check is a standalone tool in net-kingdom for v0.2.
Other repos consume it as an executable contract rather than importing
a shared library for now.

View File

@@ -0,0 +1,214 @@
---
id: NK-WP-0013
type: workplan
title: "Playbook Capability Contract"
domain: infotech
repo: net-kingdom
status: finished
owner: worsch
topic_slug: netkingdom
planning_priority: high
planning_order: 13
created: "2026-05-21"
updated: "2026-05-22"
depends_on:
- NK-WP-0006
state_hub_workstream_id: 32a54d8e-8633-42a6-8ec1-104842c581c1
---
# NK-WP-0013 — Playbook Capability Contract
> The **orchestration-layer analog of the IAM Profile**. ADR-0007's
> meta-orchestration refinement named this as a prerequisite: for NetKingdom
> to select and parametrize playbooks reliably, each Railiance playbook must
> publish a **declared interface** — the capability it provisions, its
> parameters (with defaults and constraints), and the responsibility it
> claims. Without it, meta-orchestration composes against implicit behavior
> and breaks silently when a playbook changes. This workplan defines that
> contract.
## Goal
Define the **Playbook Capability Contract** — the schema and vocabulary by
which a playbook declares:
1. **what capability it provisions** (controlled vocabulary, aligned to the
capability ladder and the responsibility-map resource kinds),
2. **its parameters** — name, type, default, constraints, required/optional,
and which are security-sensitive, and
3. **the responsibility it claims** — which element owns which resources, and
which trust state(s) / readiness checks it satisfies or requires.
…plus the **catalog/consumption model** NetKingdom meta-orchestration uses
to select, parametrize, and build a responsibility map for a scenario, and a
**conformance validator** for declarations.
## Ownership (the boundary this realizes)
By symmetry with the IAM Profile, the **consumer that needs a stable
interface defines the contract; the provider conforms**:
| | Contract owner | Publishes conformant declarations | Consumer |
|---|---|---|---|
| Identity | NetKingdom (IAM Profile) | key-cape / Keycloak | apps, flex-auth |
| Orchestration | **NetKingdom (this contract)** | Railiance playbooks | NetKingdom meta-orchestration |
NetKingdom owns the contract schema; Railiance owns the playbooks and
publishes one declaration per playbook; **execution stays in Railiance**
(ADR-0007 unchanged). The contract makes a playbook change a versioned event
rather than a silent break.
## Scope
In scope:
- ownership & boundary decision (ADR) and contract versioning governance
- the capability vocabulary a declaration draws from
- the parameter declaration format (defaults, constraints, sensitivity)
- the responsibility-claim and trust-state/readiness format
- the catalog and the meta-orchestration consumption model
- a conformance validator for declarations
- coordinated adoption proof with one reference Railiance playbook
Out of scope:
- authoring the playbooks themselves (Railiance owns execution)
- writing declarations for every existing playbook (Railiance work; this
workplan proves the contract with one reference declaration)
- a dedicated execution-orchestration repo (deferred per ADR-0007)
## Tasks
```task
id: NK-WP-0013-T1
state_hub_task_id: d40f8b29-e983-4d52-bc1f-5f1c51709e7d
status: done
priority: high
```
**Ownership & boundary decision (ADR-0012).** Record that NetKingdom owns
the Playbook Capability Contract schema (consumer-defines-contract, IAM
Profile precedent), Railiance authors playbooks and publishes conformant
declarations, and execution stays in Railiance (ADR-0007). Decide whether
the contract is NetKingdom-owned outright or NetKingdom-owned with Railiance
co-design. Define contract **versioning and breaking-change governance**.
```task
id: NK-WP-0013-T2
state_hub_task_id: ece4b5b1-e1c2-449d-b0f4-83b7010bc838
status: done
priority: high
```
**Capability vocabulary.** Define the controlled vocabulary of capabilities
a playbook can declare it provisions, aligned to the **capability ladder
(C0C6)** and the **responsibility-map resource kinds** (identities,
roles/scopes/policies, secrets/credentials, infrastructure resources). This
is what "capability" means in a declaration, so two playbooks providing the
same capability are comparable.
```task
id: NK-WP-0013-T3
state_hub_task_id: c956f4a8-b9fa-44ab-8174-31999b98e3b1
status: done
priority: high
```
**Parameter declaration format.** Define how a playbook declares its
parameters: name, type, **default**, **constraints** (allowed values /
ranges), required vs optional, and a **security-sensitivity** marker so
NetKingdom knows which parameters it may tune versus which are
security-critical and constrained. This is what makes "parametrize where
adequate" safe rather than guesswork.
```task
id: NK-WP-0013-T4
state_hub_task_id: e7de05a6-528a-4213-b6db-2c2e90353996
status: done
priority: high
```
**Responsibility-claim & trust-state format.** Define how a declaration
states which element **owns which resources** (feeding the responsibility
map) and which **trust state(s) / readiness checks** (ADR-0007 model) it
satisfies or requires. This lets NetKingdom assemble a coherent
responsibility map and sequence for a scenario from the declarations.
```task
id: NK-WP-0013-T5
state_hub_task_id: 05a2ff7d-86c4-4de9-9ea8-39a9ad5352a8
status: done
priority: high
```
**Catalog, consumption model, and conformance validator.** Define how
declarations are published and discovered (the catalog), how
meta-orchestration consumes them to **select**, **parametrize**, and build a
**responsibility map** for a scenario, and a **conformance validator** that
checks a declaration against the contract (the orchestration-layer analog of
the IAM Profile conformance check, NK-WP-0012-T5).
```task
id: NK-WP-0013-T6
state_hub_task_id: 769ed490-c091-41c1-b2e2-e8e378470b6b
status: done
priority: medium
```
**Reference adoption with Railiance.** Coordinate with Railiance to have
**one reference playbook publish a conformant declaration end-to-end**, and
demonstrate NetKingdom selecting + parametrizing it from the declaration
alone. Proves the contract is sufficient and is the template for adopting
the rest. Cross-repo coordination item for the Railiance domain.
## Acceptance Criteria
- An ADR records contract ownership, the Railiance-publishes/NetKingdom-
consumes split, and ADR-0007 is confirmed unchanged.
- The contract specifies capability vocabulary, parameter format (defaults,
constraints, sensitivity), and responsibility/trust-state claims.
- A catalog/consumption model and a declaration conformance validator exist.
- At least one Railiance playbook publishes a conformant declaration, and
NetKingdom composes and parametrizes it from that declaration alone.
- Contract versioning and breaking-change governance is documented.
## Completion Notes
- ADR: `docs/adr/ADR-0012-playbook-capability-contract-ownership.md`
- Canonical contract:
`canon/standards/playbook-capability-contract_v0.1.md`
- Machine-readable schema:
`canon/schemas/playbook-capability-declaration_v0.1.schema.json`
- Validator and composition demo:
`tools/playbook-capability-contract/playbook_contract_validator.py`
- Reference Railiance declaration:
`../railiance-infra/capabilities/playbooks/railiance-infra.bootstrap-host.yaml`
- Sample scenario:
`examples/playbook-capability-contract/scenario-s1-host-bootstrap.yaml`
- Fixture tests cover valid declarations, controlled vocabulary failures,
forbidden tenant overrides, missing required parameters, and successful
selection/parameter composition.
## Dependencies & Sequencing
- **Realizes** the playbook-contract dependency from ADR-0007's
meta-orchestration refinement; does not change ADR-0007.
- **Depends on NK-WP-0006** for the trust-state model and the
responsibility-map resource kinds the declarations reference.
- **Coordinates with the Railiance domain** — NetKingdom defines the
contract; Railiance publishes declarations (T6) and continues to own
execution.
- Parallels NK-WP-0012: same consumer-defines-contract pattern, same
conformance-check shape, applied to orchestration instead of identity.
## Resolved Questions
- Contract format and home: NetKingdom canon standard plus a
machine-readable JSON schema and standalone validator.
- Catalog mechanism: v0.1 uses file convention
`capabilities/playbooks/*.yaml`; a registry can be layered on later.
- Parameter sensitivity: tenant scenarios cannot override
`platform_only`, `forbidden`, `playbook_default`,
`security_sensitive`, or `secret_reference` parameters.
- Validator form: standalone NetKingdom tool for v0.1, mirroring
NK-WP-0012's executable-contract pattern.

View File

@@ -0,0 +1,181 @@
---
id: NK-WP-0014
type: workplan
title: "User Engine Preparation And Boundary Contracts"
domain: infotech
repo: net-kingdom
status: finished
owner: codex
topic_slug: netkingdom
planning_priority: high
planning_order: 14
created: "2026-05-22"
updated: "2026-05-22"
depends_on:
- NK-WP-0012
- NK-WP-0013
state_hub_workstream_id: "b9bf56bc-7ef6-43eb-badc-fa0f4896c63c"
---
# NK-WP-0014 - User Engine Preparation And Boundary Contracts
## Goal
Prepare implementation of `/home/worsch/user-engine` by turning the current
architecture review into concrete contracts. This workplan must be completed
before production code is started, so the MVP does not duplicate IAM,
authorization, application registration, membership, audit, or deployment
responsibilities already owned by NetKingdom-aligned components.
## Context
The user-engine PRD and architecture blueprint define a headless user-domain
service for users, accounts, profiles, preferences, memberships, application
catalogs, projections, audit, and events.
The architecture review in
`docs/reviews/2026-05-22T19-19-59+0200-user-engine-architecture-review.md`
identified the main risk: duplicate truth across IAM providers, user-engine,
flex-auth, application registrations, OIDC clients, protected systems, and
profile projections.
NetKingdom keeps this workplan because it owns cross-repo boundary and
orchestration guidance. Implementation work now lives in the `user-engine`
repository as `USER-WP-0001` through `USER-WP-0006`.
## Scope
In scope:
- source-of-truth matrix;
- membership synchronization contract;
- application onboarding contract;
- projection boundary split;
- authorization performance model;
- audit correlation contract;
- user-engine repo preparation artifacts.
- NetKingdom/user-engine interface guidance.
Out of scope:
- implementing user-engine production code, which belongs in the user-engine
repository workplans;
- implementing UI repos;
- implementing SCIM or enterprise federation adapters;
- changing the NetKingdom IAM Profile.
## Tasks
```task
id: NK-WP-0014-T1
status: done
priority: high
state_hub_task_id: "4e941174-ac55-4f6e-8568-40f45b1ed821"
```
**Source-of-truth matrix.** Define which system owns each resource kind:
identity claims, human subjects, local user records, account lifecycle,
groups, roles, memberships, tenants, applications, OIDC clients,
flex-auth protected systems, catalog namespaces, profile values,
effective-profile projections, audit records, and events.
Initial guidance lives in `docs/user-engine-interface-guidance.md` and should
be hardened into versioned contracts as implementation feedback arrives.
```task
id: NK-WP-0014-T2
status: done
priority: high
state_hub_task_id: "5ddc46bb-6238-4944-a023-d8b46b410c76"
```
**Membership synchronization contract.** Specify which memberships are mastered
in user-engine, which are imported from IAM or provisioning systems, which are
exported to flex-auth, and how freshness, conflict handling, deletes, and
tenant boundaries are represented.
```task
id: NK-WP-0014-T3
status: done
priority: high
state_hub_task_id: "696bc65b-0f8d-47b5-bccc-65ed285b42e6"
```
**Application onboarding contract.** Define the binding between a user-engine
application, IAM OIDC client, flex-auth protected system, catalog namespace,
event/audit identity, and Railiance deployment metadata. Include a checklist
for adding one new application safely.
```task
id: NK-WP-0014-T4
status: done
priority: high
state_hub_task_id: "99ab4535-cbbf-4e13-a2c5-adfc814d5aeb"
```
**Projection and claims-enrichment boundaries.** Split projection types into
runtime, self-service UI, admin UI, audit, agent context, and optional claims
enrichment. Explicitly state that user-engine does not issue tokens and that
claims enrichment is adapter-owned and cache/freshness governed.
```task
id: NK-WP-0014-T5
status: done
priority: medium
state_hub_task_id: "d35a1356-a9fe-4cf3-8fb0-6f45cfbbccee"
```
**Authorization and audit contracts.** Define the user-engine resource/action
vocabulary for flex-auth, when checks are synchronous, when they may be
batched or cached, and how user-engine audit records correlate with flex-auth
decision IDs and platform audit sinks.
```task
id: NK-WP-0014-T6
status: done
priority: medium
state_hub_task_id: "04fd2f92-3aa4-468d-9e9e-9b092890507e"
```
**Prepare the user-engine repo.** Add or update user-engine `SCOPE.md`,
architecture notes, repo layout decision, local development contract, and
initial implementation readiness checklist. Do not add NetKingdom
orchestration relationships to user-engine `INTENT.md`; those belong in
NetKingdom documents per ADR-0010.
## Acceptance Criteria
- Boundary contracts exist and are reviewed against the PRD and architecture
review.
- user-engine responsibilities are distinct from key-cape, Keycloak,
flex-auth, OpenBao, Railiance, user-account, and user-manager.
- The first implementation slice can start without unresolved ownership of
memberships, applications, projections, authorization checks, or audit
correlation.
- user-engine repo-local workplans carry implementation tasks, while
NetKingdom retains only boundary, orchestration, and responsibility-map work.
- NetKingdom responsibility-map updates are either applied or explicitly
deferred until user-engine becomes a shared platform service.
## Completion Notes
Completed on 2026-05-22:
- Added the canonical versioned contract at
`canon/standards/user-engine-boundary-contract_v0.1.md`.
- Promoted `docs/user-engine-interface-guidance.md` to an implementation guide
that points at the canonical contract.
- Confirmed `docs/responsibility-map.md` already includes `user-engine` as an
orchestrated repository and names NetKingdom's boundary responsibilities.
- Confirmed `/home/worsch/user-engine` already carries the required repo-local
preparation artifacts: `SCOPE.md`, `wiki/ArchitectureBlueprint.md`,
`docs/development.md`, `docs/configuration.md`,
`docs/interfaces/netkingdom-integration.md`, and `USER-WP-0001` through
`USER-WP-0006`.
## Dependencies And Sequencing
- Depends on NK-WP-0012 for IAM Profile consumption rules.
- Depends on NK-WP-0013 for NetKingdom meta-orchestration conventions.
- Gates implementation work in `/home/worsch/user-engine`, now tracked as
`USER-WP-0001` through `USER-WP-0006`.