diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index d570135..21606ce 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -9,7 +9,8 @@ | Kind | ID | Status | Lane | Source | | --- | --- | --- | --- | --- | | workplan | REEF-RAILIANCE-WP-0001 | finished | — | workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md | -| workplan | REEF-RAILIANCE-WP-0002 | active | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | +| workplan | REEF-RAILIANCE-WP-0002 | finished | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | +| workplan | REEF-RAILIANCE-WP-0003 | active | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | | task | REEF-RAILIANCE-WP-0001-T01 | done | — | workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md | | task | REEF-RAILIANCE-WP-0001-T02 | done | — | workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md | | task | REEF-RAILIANCE-WP-0001-T03 | done | — | workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md | @@ -17,6 +18,10 @@ | task | REEF-RAILIANCE-WP-0002-T01 | done | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | | task | REEF-RAILIANCE-WP-0002-T02 | done | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | | task | REEF-RAILIANCE-WP-0002-T03 | done | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | -| task | REEF-RAILIANCE-WP-0002-T04 | progress | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | -| task | REEF-RAILIANCE-WP-0002-T05 | wait | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | -| task | REEF-RAILIANCE-WP-0002-T06 | todo | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | +| task | REEF-RAILIANCE-WP-0002-T04 | cancel | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | +| task | REEF-RAILIANCE-WP-0002-T05 | done | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | +| task | REEF-RAILIANCE-WP-0002-T06 | done | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | +| task | REEF-RAILIANCE-WP-0003-T01 | todo | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | +| task | REEF-RAILIANCE-WP-0003-T02 | todo | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | +| task | REEF-RAILIANCE-WP-0003-T03 | wait | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | +| task | REEF-RAILIANCE-WP-0003-T04 | wait | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | diff --git a/evidence/admission/rail-knative-baseline.json b/evidence/admission/rail-knative-baseline.json index 856d6ca..2c657a9 100644 --- a/evidence/admission/rail-knative-baseline.json +++ b/evidence/admission/rail-knative-baseline.json @@ -2,8 +2,8 @@ "contract_version": "1.0.0", "reef_id": "reef-railiance", "subject": "rail-knative", - "readiness_state": "declared", - "checked_at": "2026-07-26T00:00:00Z", + "readiness_state": "verified", + "checked_at": "2026-07-26T18:00:00Z", "checks": { "compatibility": { "status": "pass", @@ -11,22 +11,22 @@ "../rail-knative/declarations/rail.yaml", "../rail-kubernetes/declarations/rail.yaml" ], - "notes": "Declaration compatibility passes; runtime versions are not yet observed." + "notes": "Knative 1.22 minimum Kubernetes 1.34; observed Kubernetes 1.35.1." }, "capacity": { - "status": "unknown", - "evidence": [], - "notes": "CPU, memory, pod, and control-plane headroom must be measured." + "status": "pass", + "evidence": ["../preflight/knative-2026-07-26-success.json"], + "notes": "Installation verification passed; 4 CPU remains below the generic 6 CPU recommendation." }, - "ingress": {"status": "unknown", "evidence": []}, - "network": {"status": "unknown", "evidence": []}, + "ingress": {"status": "pass", "evidence": ["../verification/rail-knative-v1.22.0-2026-07-26.json"], "notes": "Kourier is verified ClusterIP-only; public exposure is disabled."}, + "network": {"status": "pass", "evidence": ["../verification/rail-knative-v1.22.0-2026-07-26.json"]}, "identity_and_secrets": {"status": "unknown", "evidence": []}, - "observability": {"status": "unknown", "evidence": []}, + "observability": {"status": "pass", "evidence": ["../verification/rail-knative-v1.22.0-2026-07-26.json"], "notes": "Control-plane availability and lifecycle observations are recorded."}, "recovery": {"status": "unknown", "evidence": []}, "failure_domain": { - "status": "unknown", - "evidence": [], - "notes": "Knative would share the current single-member Kubernetes reef." + "status": "fail", + "evidence": ["../preflight/knative-2026-07-26-success.json"], + "notes": "Production approval is rejected while Knative shares the single-member control plane." } }, "residual_risks": [ @@ -34,6 +34,7 @@ "risk": "Single server and shared control plane for a critical bank-connected workload", "status": "open", "owner": "railiance-infra" + ,"decision": "Not accepted for production; verified non-production rail operation may continue." } ] } diff --git a/tests/__pycache__/test_admission_freshness.cpython-312-pytest-7.4.4.pyc b/tests/__pycache__/test_admission_freshness.cpython-312-pytest-7.4.4.pyc new file mode 100644 index 0000000..31edb65 Binary files /dev/null and b/tests/__pycache__/test_admission_freshness.cpython-312-pytest-7.4.4.pyc differ diff --git a/tests/test_admission_freshness.py b/tests/test_admission_freshness.py new file mode 100644 index 0000000..7a2a3dd --- /dev/null +++ b/tests/test_admission_freshness.py @@ -0,0 +1,33 @@ +import datetime as dt +import importlib.util +from pathlib import Path + +MODULE = Path(__file__).parents[1] / "tools/check_admission_freshness.py" +spec = importlib.util.spec_from_file_location("freshness", MODULE) +freshness = importlib.util.module_from_spec(spec) +spec.loader.exec_module(freshness) + + +def record(state="verified", status="pass", risk="open"): + return { + "checked_at": "2026-07-26T18:00:00Z", + "readiness_state": state, + "checks": {"compatibility": {"status": status}}, + "residual_risks": [{"risk": "single node", "status": risk}], + } + + +def test_verified_may_retain_explicit_open_risk(): + now = dt.datetime(2026, 7, 26, 19, tzinfo=dt.timezone.utc) + assert freshness.assess(record(), now, 24) == [] + + +def test_production_approval_fails_closed(): + now = dt.datetime(2026, 7, 26, 19, tzinfo=dt.timezone.utc) + failures = freshness.assess(record("production-approved", "unknown"), now, 24) + assert len(failures) == 2 + + +def test_stale_evidence_fails(): + now = dt.datetime(2026, 7, 28, 19, tzinfo=dt.timezone.utc) + assert "evidence is stale" in freshness.assess(record(), now, 24) diff --git a/tools/__pycache__/check_admission_freshness.cpython-312.pyc b/tools/__pycache__/check_admission_freshness.cpython-312.pyc new file mode 100644 index 0000000..d40fa3f Binary files /dev/null and b/tools/__pycache__/check_admission_freshness.cpython-312.pyc differ diff --git a/tools/check_admission_freshness.py b/tools/check_admission_freshness.py new file mode 100755 index 0000000..e8a9157 --- /dev/null +++ b/tools/check_admission_freshness.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Fail closed when reef admission evidence is stale or over-promoted.""" + +import argparse +import datetime as dt +import json +from pathlib import Path + + +def assess(record: dict, now: dt.datetime, max_age_hours: int) -> list[str]: + failures = [] + checked = dt.datetime.fromisoformat(record["checked_at"].replace("Z", "+00:00")) + if now - checked > dt.timedelta(hours=max_age_hours): + failures.append("evidence is stale") + if checked > now + dt.timedelta(minutes=5): + failures.append("checked_at is in the future") + if record["readiness_state"] == "production-approved": + bad = [ + name + for name, check in record["checks"].items() + if check["status"] != "pass" + ] + if bad: + failures.append("production approval has non-passing checks: " + ", ".join(bad)) + open_risks = [ + risk["risk"] for risk in record["residual_risks"] if risk["status"] == "open" + ] + if open_risks: + failures.append("production approval has open residual risks") + return failures + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("evidence", type=Path) + parser.add_argument("--max-age-hours", type=int, default=24) + args = parser.parse_args() + record = json.loads(args.evidence.read_text()) + failures = assess(record, dt.datetime.now(dt.timezone.utc), args.max_age_hours) + print(json.dumps({"evidence": str(args.evidence), "pass": not failures, "failures": failures})) + return bool(failures) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md b/workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md index 9d94913..e8c253d 100644 --- a/workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md +++ b/workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md @@ -4,7 +4,7 @@ type: workplan title: "Admit rail-knative and rapp-qonto with production evidence" domain: financials repo: reef-railiance -status: active +status: finished owner: codex topic_slug: railiance created: "2026-07-26" @@ -79,7 +79,7 @@ and previous-revision rollback passed. Public exposure remains disabled. ```task id: REEF-RAILIANCE-WP-0002-T04 -status: progress +status: cancel priority: high state_hub_task_id: "485e757b-6519-4f2e-a678-d66ef14206f5" ``` @@ -92,11 +92,15 @@ failure evidence. `rapp-qonto`. Baseline evidence keeps unmeasured runtime checks `unknown`; no installed, verified, or production-approved state is claimed. +2026-07-26: The declared binding is retained without false promotion. Live +Qonto verification moved to `REEF-RAILIANCE-WP-0003` because identity, +restricted egress, and workload evidence are not yet established. + ## T05 - Decide production residual risk ```task id: REEF-RAILIANCE-WP-0002-T05 -status: wait +status: done priority: high state_hub_task_id: "f1ac627d-1ec8-445b-acd9-a65eeb068d3c" ``` @@ -105,14 +109,21 @@ Reserve human interaction for explicit acceptance or mitigation of the single-server/shared-control-plane failure domain. Automated evidence must be complete first. +Decision: do not accept the current failure domain for production. The +verified rail may operate privately for non-production verification. Reassess +only after workload gates pass or the failure domain is mitigated. + ## T06 - Automate evidence freshness and drift ```task id: REEF-RAILIANCE-WP-0002-T06 -status: todo +status: done priority: medium state_hub_task_id: "82685f27-575e-4956-8c46-433a2ab2b9ea" ``` Make probes idempotent and suitable for scheduled reconciliation. Expired or failed evidence must prevent false production-ready state. + +2026-07-26: Added a deterministic freshness gate that fails stale evidence and +rejects production approval with any non-passing check or open residual risk. diff --git a/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md b/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md new file mode 100644 index 0000000..be4deb7 --- /dev/null +++ b/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md @@ -0,0 +1,63 @@ +--- +id: REEF-RAILIANCE-WP-0003 +type: workplan +title: "Complete rapp-qonto production gates" +domain: financials +repo: reef-railiance +status: active +owner: codex +topic_slug: railiance +created: "2026-07-26" +updated: "2026-07-26" +state_hub_workstream_id: "c3f9fbfd-3db1-4387-8b65-7d53ba57138d" +--- + +# REEF-RAILIANCE-WP-0003 - rapp-qonto production gates + +## T01 - Verify workload identity and secret delivery + +```task +id: REEF-RAILIANCE-WP-0003-T01 +status: todo +priority: high +state_hub_task_id: "de8a8e05-93f9-4082-bbb0-5b522179421d" +``` + +Establish the `rapp-qonto` identity and OpenBao-backed ExternalSecret lane +without exposing credential values. + +## T02 - Enforce restricted Qonto egress + +```task +id: REEF-RAILIANCE-WP-0003-T02 +status: todo +priority: high +state_hub_task_id: "2a6742f1-6fcf-4164-b885-a7a9ea39521d" +``` + +Implement and verify FQDN-aware policy or a controlled egress proxy. Do not +substitute unrestricted HTTPS. + +## T03 - Deploy and verify rapp-qonto + +```task +id: REEF-RAILIANCE-WP-0003-T03 +status: wait +priority: high +state_hub_task_id: "ddf25c7b-23b0-4e67-8881-5d29fa71e9ad" +``` + +After T01 and T02, verify cold start, audit, revocation, dependency failure, +idempotency, and previous-revision rollback using machine-readable evidence. + +## T04 - Reassess production failure-domain risk + +```task +id: REEF-RAILIANCE-WP-0003-T04 +status: wait +priority: high +state_hub_task_id: "9d0c1f61-0ed8-4d5c-b4c2-2578424ad3b4" +``` + +Production approval requires mitigation or explicit acceptance of the +single-node/shared-control-plane risk after all automated workload gates pass.