diff --git a/Makefile b/Makefile index 94e4bc3..37f3c1c 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ BOOTSTRAP_CLEANUP_EVIDENCE ?= /tmp/netkingdom-bootstrap-cleanup/evidence.json LIFECYCLE_FLOW_EVIDENCE ?= /tmp/netkingdom-lifecycle-flow/evidence.json ONBOARDING_DRY_RUN_EVIDENCE ?= /tmp/netkingdom-onboarding-dry-run/evidence.json RAILIANCE_PLATFORM_PATH ?= ../railiance-platform +KEY_CAPE_PATH ?= ../key-cape CUSTODY_ROSTER ?= .local/custody-roster.json CUSTODY_ROSTER_SIGNATURE ?= .local/custody-roster.json.sig CUSTODY_ROSTER_ALLOWED_SIGNERS ?= .local/custody-roster.allowed_signers @@ -199,6 +200,12 @@ security-scenario-compose-c0: ## Compose the plan-only C0 local-identity referen --scenario examples/security-scenarios/c0-local-identity.yaml \ capabilities/playbooks/net-kingdom.local-identity.yaml +security-scenario-compose-lightweight: ## Compose plan-only KeyCape C1+C2b from owner declarations + python3 tools/security-scenario-composer/security_scenario_composer.py \ + --scenario examples/security-scenarios/c1-c2b-key-cape.yaml \ + $(KEY_CAPE_PATH)/capabilities/playbooks/key-cape.lightweight-sso.yaml \ + $(KEY_CAPE_PATH)/capabilities/playbooks/key-cape.privacyidea-token-authority.yaml + posture-feedback-test: ## Run deterministic posture-feedback tests python3 -m pytest tools/posture-feedback/tests tools/tenancy-posture/test_validate.py @@ -369,7 +376,7 @@ security-bootstrap-ui: security-bootstrap-metadata-init ## Serve local custody a creds-agent-init creds-agent-status creds-emergency-reprint \ openbao-init-unseal openbao-init-unseal-dry-run \ iam-profile-conformance-test playbook-contract-test posture-feedback-test \ - posture-feedback-reference \ + posture-feedback-reference security-scenario-compose-lightweight \ security-bootstrap-console-test security-bootstrap-scripts-syntax \ security-bootstrap-console security-bootstrap-king-kit \ security-bootstrap-validate-kit security-bootstrap-validate-t02 \ diff --git a/SCOPE.md b/SCOPE.md index c0099d6..bf80971 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -120,10 +120,9 @@ Current open work as of 2026-08-23 is either externally blocked, date-gated, or explicit backlog: reef carrier/public-classification decisions in NK-WP-0027, the NK-WP-0022 retirement gate, security tutorials in NK-WP-0009, and enterprise federation in NK-WP-0011. NK-WP-0030 has delivered the local C0 -scenario-composition slice and waits for externally owned C1/C2 provider -declarations before the lightweight SSO scenario can compose. NK-WP-0031 has -delivered the local proposal-only feedback evaluator and waits for authoritative -freshness adoption by `audit-core`. +and externally declared KeyCape C1+C2b plan-only composition slices. NK-WP-0031 +has delivered the local proposal-only feedback evaluator and waits for +authoritative freshness adoption by `audit-core`. --- diff --git a/examples/security-scenarios/c1-c2b-key-cape.yaml b/examples/security-scenarios/c1-c2b-key-cape.yaml new file mode 100644 index 0000000..cd3a96b --- /dev/null +++ b/examples/security-scenarios/c1-c2b-key-cape.yaml @@ -0,0 +1,12 @@ +id: scenario:c1-c2b-key-cape-reference +authority: platform +initial_trust: + - cluster_trust + - runtime_secret_trust +requires: + capabilities: + - c1.lightweight-sso + - c2b.token-authority +providers: + c1.lightweight-sso: key-cape.lightweight-sso + c2b.token-authority: key-cape.privacyidea-token-authority diff --git a/history/2026-08-23-key-cape-c1-c2b-composition.md b/history/2026-08-23-key-cape-c1-c2b-composition.md new file mode 100644 index 0000000..70329bd --- /dev/null +++ b/history/2026-08-23-key-cape-c1-c2b-composition.md @@ -0,0 +1,33 @@ +# KeyCape C1 and C2b composition evidence + +Date: 2026-08-23 +Workplan: NK-WP-0030 +Mode: plan-only + +KeyCape published provider-owned Playbook Capability Contract v0.1 +declarations for `key-cape.lightweight-sso` and +`key-cape.privacyidea-token-authority`. The implementation content originates +at KeyCape revision `efce3e9`; its file-first workplan and State Hub identifiers +were reconciled by revision `34fadae`. NetKingdom received the handoff in State +Hub message `1d5f5f15-d137-4c11-8386-c8cc58c17bb8`. + +Both owner declarations passed NetKingdom's canonical playbook capability +validator. The reference request in +`examples/security-scenarios/c1-c2b-key-cape.yaml` then composed successfully +with: + +- initial trust: `cluster_trust`, `runtime_secret_trust`; +- step 1: `key-cape.lightweight-sso` provides C1 and establishes + `runtime_identity_trust`; +- step 2: `key-cape.privacyidea-token-authority` provides C2b after consuming + that identity trust; +- final trust: `cluster_trust`, `runtime_secret_trust`, and + `runtime_identity_trust`; and +- composition digest: + `sha256:cd7aeba3c83c83e2de7bc9a64d2dd9922f4f39a4de81c41760f9f9a431a820a6`. + +The plan retains KeyCape, railiance-platform, and privacyIDEA ownership exactly +as declared. It sets `execution.mode: plan-only` and +`execution.permitted: false`; no provider entry point was invoked. C2a built-in +factors are not part of the scenario, and neither NetKingdom nor KeyCape claims +them through this composition. diff --git a/history/2026-08-23-scope-intent-gap-assessment.md b/history/2026-08-23-scope-intent-gap-assessment.md index b6c46c1..ff9b448 100644 --- a/history/2026-08-23-scope-intent-gap-assessment.md +++ b/history/2026-08-23-scope-intent-gap-assessment.md @@ -142,9 +142,12 @@ NK-WP-0030 subsequently implemented the first bounded G1 increment: proposed Security Scenario Composition v0.1 canon, a fail-closed plan-only composer, and a real C0 local-identity declaration and reference scenario. This establishes deterministic provider pins, trust ordering, responsibility mapping, and -readiness handoff without executing provider actions. G1 remains open for the -lightweight SSO path until the KeyCape/Railiance owners publish conformant C1 -and C2 declarations. +readiness handoff without executing provider actions. KeyCape subsequently +published conformant owner declarations for C1 and C2b. NetKingdom's checked-in +reference now composes them in trust order and preserves their responsibility +map without claiming C2a. G1 remains open beyond this bounded increment because +the composer neither executes the provider entry points nor closes their +readiness obligations into verified turn-key state. NK-WP-0031 subsequently implemented the first bounded G2 increment: proposed Posture Feedback v0.1 canon and a deterministic evaluator that turns explicit diff --git a/tools/security-scenario-composer/README.md b/tools/security-scenario-composer/README.md index e352556..faf9590 100644 --- a/tools/security-scenario-composer/README.md +++ b/tools/security-scenario-composer/README.md @@ -17,6 +17,20 @@ python3 tools/security-scenario-composer/security_scenario_composer.py \ capabilities/playbooks/net-kingdom.local-identity.yaml ``` +Compose the KeyCape C1 plus C2b reference from its authoritative sibling +declarations: + +```bash +python3 tools/security-scenario-composer/security_scenario_composer.py \ + --scenario examples/security-scenarios/c1-c2b-key-cape.yaml \ + ../key-cape/capabilities/playbooks/key-cape.lightweight-sso.yaml \ + ../key-cape/capabilities/playbooks/key-cape.privacyidea-token-authority.yaml +``` + +The scenario pins both provider ids. NetKingdom does not copy or reinterpret +their execution authority; the emitted plan retains `execution.permitted: +false` and routes readiness to the declaration owners. + Run tests: ```bash diff --git a/tools/security-scenario-composer/tests/test_security_scenario_composer.py b/tools/security-scenario-composer/tests/test_security_scenario_composer.py index 9712731..d99fc5a 100644 --- a/tools/security-scenario-composer/tests/test_security_scenario_composer.py +++ b/tools/security-scenario-composer/tests/test_security_scenario_composer.py @@ -264,3 +264,44 @@ def test_checked_in_c0_scenario_composes(): "c0.bootstrap-identity": "net-kingdom.local-identity" } assert plan["execution_steps"][0]["repo"] == "net-kingdom" + + +def test_checked_in_key_cape_scenario_sequences_c1_before_c2b(tmp_path): + repo_root = Path(__file__).resolve().parents[3] + scenario_path = repo_root / "examples/security-scenarios/c1-c2b-key-cape.yaml" + c1_data = declaration_data( + "key-cape.lightweight-sso", + "c1.lightweight-sso", + "C1", + requires=["cluster_trust", "runtime_secret_trust"], + satisfies=["runtime_identity_trust"], + ) + c1_data["metadata"]["owner"] = "key-cape" + c1_data["metadata"]["repo"] = "key-cape" + c2b_data = declaration_data( + "key-cape.privacyidea-token-authority", + "c2b.token-authority", + "C2b", + requires=["runtime_identity_trust", "runtime_secret_trust"], + satisfies=["runtime_identity_trust"], + ) + c2b_data["metadata"]["owner"] = "key-cape" + c2b_data["metadata"]["repo"] = "key-cape" + declarations = [ + declaration(tmp_path, c2b_data, "c2b.yaml"), + declaration(tmp_path, c1_data, "c1.yaml"), + ] + + request = composer.contract.load_yaml(scenario_path) + issues, plan = composer.compose_scenario(declarations, request) + + assert messages(issues) == [] + assert plan["capability_providers"] == { + "c1.lightweight-sso": "key-cape.lightweight-sso", + "c2b.token-authority": "key-cape.privacyidea-token-authority", + } + assert [step["declaration_id"] for step in plan["execution_steps"]] == [ + "key-cape.lightweight-sso", + "key-cape.privacyidea-token-authority", + ] + assert plan["execution"]["permitted"] is False diff --git a/workplans/NK-WP-0030-deterministic-security-scenario-composition.md b/workplans/NK-WP-0030-deterministic-security-scenario-composition.md index 25449e3..f60bdbb 100644 --- a/workplans/NK-WP-0030-deterministic-security-scenario-composition.md +++ b/workplans/NK-WP-0030-deterministic-security-scenario-composition.md @@ -4,7 +4,7 @@ type: workplan title: "Implement deterministic security scenario composition" domain: infotech repo: net-kingdom -status: blocked +status: finished owner: codex topic_slug: netkingdom planning_priority: P1 @@ -69,7 +69,7 @@ executing the CLI entry point. ```task id: NK-WP-0030-T04 -status: wait +status: done priority: high state_hub_task_id: "41fd145d-7a37-5c65-ae72-142ac6d49144" ``` @@ -80,6 +80,15 @@ authority in NetKingdom. The complete lightweight SSO scenario remains blocked until those declarations exist and pass the canonical composer. Routed to `key-cape` in State Hub message `64d247e4-9170-4d18-b7ed-d8b071282104`. +KeyCape published the authoritative C1 and C2b declarations at revision +`34fadae` and notified NetKingdom in State Hub message +`1d5f5f15-d137-4c11-8386-c8cc58c17bb8`. Both pass the canonical declaration +validator. `examples/security-scenarios/c1-c2b-key-cape.yaml` pins the exact +providers, sequences C1 before C2b through `runtime_identity_trust`, and emits +plan digest +`sha256:cd7aeba3c83c83e2de7bc9a64d2dd9922f4f39a4de81c41760f9f9a431a820a6` +with execution forbidden. C2a remains outside the scenario and is not implied. + ## Verify the fail-closed and reference paths ```task @@ -89,11 +98,11 @@ priority: medium state_hub_task_id: "7db26092-35c4-52c6-9a3e-3f24bc3e26c7" ``` -Added ten composer tests and five regression tests for the legacy declaration +Added eleven composer tests and five regression tests for the legacy declaration validator/demo selector, including secret-reference syntax enforcement. Exact selection, ambiguity refusal, bad pins, override boundaries, duplicate ids, dependency ordering, unresolved trust, responsibility/readiness mapping, -and the checked-in C0 composition pass. The complete relevant repository suite -passes 70 tests; the isolated local-identity suite passes 142 tests. JSON/YAML -parsing, Python compilation, the reference CLI, and `git diff --check` also -pass. +and the checked-in C0 and KeyCape C1+C2b compositions pass. The current root +repository suite passes 88 tests; the isolated local-identity suite passes 142 +tests. JSON/YAML parsing, Python compilation, both reference CLI paths, and +`git diff --check` also pass.