diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 51c444a..33214ce 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -51,7 +51,7 @@ | task | AUDIT-WP-0008-T02 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T03 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T04 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | -| task | AUDIT-WP-0008-T05 | progress | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | +| task | AUDIT-WP-0008-T05 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T06 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T07 | progress | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T08 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | diff --git a/docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-final-report.json b/docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-final-report.json new file mode 100644 index 0000000..8cea28b --- /dev/null +++ b/docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-final-report.json @@ -0,0 +1,182 @@ +{ + "assurance_statement": "Pass means only that the attacks attempted in this run did not work; it is not proof that the tenant boundary always holds.", + "attacker_model": "E2-authenticated-tenant-a", + "attempted_operations": 10, + "authorization_id": "operator-session-2026-08-22-e2-03-approval", + "cleanup": "WP-0025 receipt-bound cleanup completed at 2026-08-22T22:13:48Z for projection sha256:c22ef5651efde1416f33936e193a3438c09a1284925b36f51fa6328519c7d02e", + "credential_revocation": "revoked by railiance-platform custody cleanup for lease custody:32c03d05b32fa6850d65eeba7bd7e2a0", + "ended_at": "2026-08-22T22:10:25.073895Z", + "engagement_id": "WH-ENG-20260822-AUDIT-E2-03", + "evidence_class": "target", + "limitations": [], + "outcome": "pass", + "posture_claim": "implemented E2; currently evidenced E1", + "probes": [ + { + "observations": { + "absent": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 0, + "run_digest": "6f1b8575bc0a114ac8eee4ce04e67bf2c0a727ddd706069453bc69e208960041", + "schema": [ + "$", + "$.error:str" + ], + "status": 404 + }, + "attacker": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 0, + "run_digest": "6f1b8575bc0a114ac8eee4ce04e67bf2c0a727ddd706069453bc69e208960041", + "schema": [ + "$", + "$.error:str" + ], + "status": 404 + }, + "owner": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 2, + "run_digest": "bbed8ca6ed1e1343885ddc0945869af4f430127da9d3523f6b26ed1688f493e6", + "schema": [ + "$", + "$.accepted_at:str", + "$.action:str", + "$.actor:NoneType", + "$.details", + "$.details.correlation_id:str", + "$.details.data", + "$.details.data.fixture_id:str", + "$.event_id:str", + "$.observed_at:str", + "$.outcome:str", + "$.reason:NoneType", + "$.resource:str", + "$.schema_version:str", + "$.scope:str", + "$.source:str", + "$.tenant:str" + ], + "status": 200 + } + }, + "operation": "read", + "outcome": "pass", + "probe_id": "audit-event-by-id", + "reasons": [] + }, + { + "observations": { + "attacker": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 0, + "run_digest": "f023e92394bf5d3a1d8127f78eaa038afcf409159ad82637af0aeaa3bde6c276", + "schema": [ + "$", + "$.events[]", + "$.events[]", + "$.events[].accepted_at:str", + "$.events[].action:str", + "$.events[].actor:NoneType", + "$.events[].details", + "$.events[].details.correlation_id:str", + "$.events[].details.data", + "$.events[].details.data.fixture_id:str", + "$.events[].event_id:str", + "$.events[].observed_at:str", + "$.events[].outcome:str", + "$.events[].reason:NoneType", + "$.events[].resource:str", + "$.events[].schema_version:str", + "$.events[].scope:str", + "$.events[].source:str", + "$.events[].tenant:str" + ], + "status": 200 + }, + "owner": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 2, + "run_digest": "3411e7a6de77dc184926bf94ca492f7fccc3c3dfa3d1041763c35bbaa666e7eb", + "schema": [ + "$", + "$.events[]", + "$.events[]", + "$.events[].accepted_at:str", + "$.events[].action:str", + "$.events[].actor:NoneType", + "$.events[].details", + "$.events[].details.correlation_id:str", + "$.events[].details.data", + "$.events[].details.data.fixture_id:str", + "$.events[].event_id:str", + "$.events[].observed_at:str", + "$.events[].outcome:str", + "$.events[].reason:NoneType", + "$.events[].resource:str", + "$.events[].schema_version:str", + "$.events[].scope:str", + "$.events[].source:str", + "$.events[].tenant:str" + ], + "status": 200 + } + }, + "operation": "read", + "outcome": "pass", + "probe_id": "audit-correlation-slice", + "reasons": [] + }, + { + "observations": { + "absent": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 0, + "run_digest": "6f1b8575bc0a114ac8eee4ce04e67bf2c0a727ddd706069453bc69e208960041", + "schema": [ + "$", + "$.error:str" + ], + "status": 404 + }, + "attacker": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 0, + "run_digest": "01f07af3e3c784c765f1190d0d6607e15cfb972ff2562a3a7566237b3ef1f88e", + "schema": [ + "$", + "$.error:str" + ], + "status": 400 + }, + "state_after": { + "content_type": "application/json", + "count": 1, + "fixture_match_count": 0, + "run_digest": "6f1b8575bc0a114ac8eee4ce04e67bf2c0a727ddd706069453bc69e208960041", + "schema": [ + "$", + "$.error:str" + ], + "status": 404 + } + }, + "operation": "create", + "outcome": "pass", + "probe_id": "audit-append-as-b", + "reasons": [] + } + ], + "run_id": "WH-ENG-20260822-AUDIT-E2-03-2026-08-22T22:09:30.705690Z", + "schema_version": "whitehat-run/v1", + "started_at": "2026-08-22T22:09:30.705690Z", + "target": "audit-core", + "target_revision": "sha256:c2fe39a0185b99be3fc0cb14d2de69772b8e66e20490097c9d11d90cc39719a6" +} diff --git a/docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md b/docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md new file mode 100644 index 0000000..e226223 --- /dev/null +++ b/docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md @@ -0,0 +1,69 @@ +# WH-ENG-20260822-AUDIT-E2-03 target pass + +Date: 2026-08-22 +Workplan task: `AUDIT-WP-0008-T05` +Evidence class: adversarial target run +Outcome: pass, with no reported limitations + +## Claim and limit + +An ordinary identity bound to fixture tenant A attempted to read and create +fixture data belonging to tenant B through audit-core's public application +routes. All three calibrated probes passed. This is evidence that the attacks +attempted in this bounded run did not work; it is not proof that audit-core's +tenant boundary always holds. + +The target revision was +`sha256:c2fe39a0185b99be3fc0cb14d2de69772b8e66e20490097c9d11d90cc39719a6`. +The run started at `2026-08-22T22:09:30.705690Z`, ended at +`2026-08-22T22:10:25.073895Z`, and attempted ten operations with concurrency +one. No non-fixture data was collected. + +## Probe observations + +- `audit-event-by-id`: the tenant-B owner received the declared fixture with + status 200. The tenant-A attacker received the same status, schema and digest + as the deliberately absent-object control: 404, with no fixture match. +- `audit-correlation-slice`: the owner result contained both tenant-B fixture + markers. The attacker result contained zero tenant-B fixture markers. +- `audit-append-as-b`: the tenant-A attempt to append as tenant B was refused + with status 400. A subsequent owner read returned the same 404 digest and + schema as the absent-object control, demonstrating no created fixture. + +The complete sanitized observations are in +`AUDIT-WP-0008-T05-whitehat-e2-03-final-report.json`, SHA-256 +`2d5a21141b78024a5334881e2b7fd62a69c46931057f77515a6c6f18ec497593`. + +## Custody and cleanup + +Projection receipt +`sha256:c22ef5651efde1416f33936e193a3438c09a1284925b36f51fa6328519c7d02e` +bound the two projected handles to lease +`custody:32c03d05b32fa6850d65eeba7bd7e2a0`, expiring at 22:15Z. The runner was +deleted after the probe. Receipt-bound cleanup completed at 22:13:48Z, before +expiry, and removed both temporary identities, both exact KV paths, the +projection resources and mounted Secret. Independent post-cleanup status found +all exact lists empty, the runner absent, and audit-core `1/1` Ready. No secret +value was observed or retained. + +Artifact hashes: + +- projection receipt: + `eeb8abd84abf5451915f7ab2c45c722fa58b279a4ec8e62187d20d5af135cde4` +- cleanup receipt: + `74d53852f8a0eaead73d468e9e0e12d617807fa3f00028a7473bc3b765738889` +- broker receipt: + `85cf0e507d3b84188c1ea39fd9e6f948c2983a08a5aa94b578e952ac832d0433` + +The sanitized final report reached `risk-nexus` as State Hub message +`40e3f825-fc70-4091-96d2-9ab01d42184a` with subject +`WHITEHAT TARGET PASS: WH-ENG-20260822-AUDIT-E2-03`. + +## Freshness + +The facility baseline is a 24-hour cadence plus run and reporting latency, with +event-triggered pre-promotion runs after relevant boundary changes. This +artifact is therefore due for review or replacement at +`2026-08-23T22:10:25Z`. Repeating that cadence reliably requires an automated +multi-driver orchestrator; the attended run proves the sequence but is not a +sustainable scheduler. diff --git a/tenancy.yaml b/tenancy.yaml index cac65ee..76670a1 100644 --- a/tenancy.yaml +++ b/tenancy.yaml @@ -6,8 +6,8 @@ # provider block per Decision 5.5. # # Conformance is accuracy, not altitude (§6). Nothing here is claimed above -# what this repo can evidence today. E is deliberately declared lower than the -# mechanism in place because the adversarial artifact is still absent. +# what this repo can evidence today. E2 is backed by a bounded adversarial +# target run; its scope and freshness limit are recorded below. schema_version: "0.1" framework: netkingdom-tenancy-posture @@ -15,20 +15,19 @@ service: audit-core role: tenant-audit-service tenancy: - reviewed: "2026-08-17" - review_due: "2027-02-17" + reviewed: "2026-08-22" + review_due: "2026-08-23" service_class: batch # §8.3.2. Co-resident with latency-critical # tenant-engine on platform-pg; the mixture is # reported by the platform, not hidden. - current: { I: 1, A: 2, E: 1, P: 1, R: 2, V: 0 } - implemented: { E: 2 } + current: { I: 1, A: 2, E: 2, P: 1, R: 2, V: 0 } target: { I: 1, A: 2, E: 3, P: 1, R: 2, V: 1 } # §5.2 — declare per path, quote the minimum. The quoted E above is the # minimum across paths. As of AUDIT-WP-0008-T04 both paths carry the same - # mechanism; the quoted level stays at 1 for the evidence reason in gap.E, - # not because a path is weaker. + # mechanism. The quoted level is now 2 because the adversarial target artifact + # required by §13.2 exists for this revision. paths: E: write: 2 # Sender credential bound to the sources and tenants it may @@ -60,16 +59,17 @@ tenancy: delegating to it today would lower this service's assurance, not raise it. E: >- - The E2 mechanism is in place on both paths as of AUDIT-WP-0008-T04, and - the quoted level is still 1. This is deliberate. §13.2 states that a - passing CI run is not E2 evidence: the E2 artifact is adversarial, needs - separate tenant contexts compared against each other, and carries a review - date rather than a green build. The repo's cross-tenant tests are - mechanical. Under §13.1 the level is not claimable until that artifact - exists, so E stays at 1 until AUDIT-WP-0008-T05 produces it with - whitehat-security. Declaring E2 on the strength of unit tests would be the - overclaim §6 prohibits, and the read-path defect this repo just fixed was - found precisely by refusing that kind of reasoning. + E2 is implemented on both paths by AUDIT-WP-0008-T04 and evidenced by the + bounded whitehat-security target run WH-ENG-20260822-AUDIT-E2-03. An + ordinary tenant-A identity could not fetch tenant B's event by id, observe + tenant B's correlation fixture, or append as tenant B across ten attempted + operations. The run ended 2026-08-22T22:10:25Z with no limitations; + receipt-bound cleanup removed both temporary identities, both exact KV + paths, all projection resources and the runner. This says only that the + attempted attacks did not work, not that the boundary always holds. The + 24-hour facility baseline makes review or replacement due at + 2026-08-23T22:10:25Z, and relevant boundary changes require a + pre-promotion run. E_target: >- E3 (row-level security per rapp-postgres ADR-0003) targeted 2027-03-31. Blocked behind the E2 artifact — §4.3 requires E2 evidence alongside any @@ -125,6 +125,7 @@ provider: evidence: - "audit_core/ingestion.py" - "tests/test_ingestion.py" + - "docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md" R: available: 2 maximum: 2 @@ -158,9 +159,9 @@ evidence: A2: - "audit_core/ingestion.py" - "tests/test_ingestion.py" - E1: - - "audit_core/postgres_backend.py" - - "tests/test_backend_conformance.py" + E2: + - "docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md" + - "docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-final-report.json" P1: "rapp-postgres/docs/evidence/isolation-2026-08-10.md" R2: - "rapp-postgres/consumers/audit-core.yaml" diff --git a/workplans/AUDIT-WP-0008-tenancy-posture-alignment.md b/workplans/AUDIT-WP-0008-tenancy-posture-alignment.md index e1ec78c..3693076 100644 --- a/workplans/AUDIT-WP-0008-tenancy-posture-alignment.md +++ b/workplans/AUDIT-WP-0008-tenancy-posture-alignment.md @@ -374,7 +374,7 @@ and the operator runbook. Raises E to 2 on both paths; update T01's declaration. ```task id: AUDIT-WP-0008-T05 -status: progress +status: done priority: medium state_hub_task_id: "30b56b30-e7eb-4873-aa7c-f4a3bf2fcb24" ``` @@ -505,6 +505,28 @@ identity, exact KV path, projection resource, runner, or secret value. The engagement is approved but projection remains fail-closed before 22:00Z and after 22:03Z. +The `-03` engagement completed successfully. Receipt-bound projection opened at +22:01:35Z; Whitehat admitted the exact plane lease; and the bounded runner sent +ten operations from 22:09:30Z through 22:10:25Z. All three calibrated probes +passed: a tenant-A identity could not fetch tenant B's event by id, could not +observe tenant B's correlation slice, and could not append an event attributed +to tenant B. The report carries no limitations and explicitly limits the claim +to the attacks attempted in this run. + +The runner was deleted and custody cleanup completed at 22:13:48Z, before the +22:15Z expiry. Independent status found both exact KV paths, both temporary +identities, all projection resources and the runner absent, with audit-core +still `1/1` Ready; no secret value was observed or retained. The finalized +sanitized report reached `risk-nexus` as message +`40e3f825-fc70-4091-96d2-9ab01d42184a`. Durable target evidence is recorded in +`docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md` and its +companion JSON report. Audit-core notified `net-kingdom` in +`b8a7ce2a-cf8e-44ef-ab25-37b0f93337db` that the canonical worked example can +advance from E1 to E2. The facility's 24-hour baseline makes the next review or +replacement due at 2026-08-23T22:10:25Z; sustaining it without minute-precise +operator attendance now belongs in a multi-driver integration/e2e harness, not +in another manual T05 sequence. + ```task id: AUDIT-WP-0008-T06 status: done