diff --git a/README.md b/README.md index 9a4d462..9f4b5ec 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,11 @@ Those concerns stay with `railiance-infra`, `railiance-cluster`, This repo now owns the wave-1 grouped home-reef boundary for Railiance. +The rail and rApp binding projections were reconciled against their owning +family declarations on 2026-08-21. Live evidence still shows one Ready member +carrying the Kubernetes control-plane and etcd roles, so the Qonto binding +remains verified and private rather than production-approved. + The retained S1 compatibility path while reef localization is still in flight is documented in `docs/retained-s1-handoff.md`. diff --git a/SCOPE.md b/SCOPE.md index 296a029..d19fdb6 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -62,10 +62,11 @@ or one-host naming into the reef model. ## Current State - Status: bootstrapped first-wave grouped reef home -- Implementation: declaration, grouped substrate files, and retained-S1 - compatibility handoff are present +- Implementation: declaration, grouped substrate files, retained-S1 + compatibility handoff, and checked rail/rApp binding projections are present - Stability: evolving, with the migration-window split now explicit -- Usage: wave-1 home reef for the Railiance server group +- Usage: wave-1 home reef for the Railiance server group; Qonto production + admission remains blocked on an independent failure domain --- diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 8dcd28f..6793b31 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -12,6 +12,7 @@ | workplan | REEF-RAILIANCE-WP-0002 | finished | — | workplans/REEF-RAILIANCE-WP-0002-knative-and-qonto-production-admission.md | | workplan | REEF-RAILIANCE-WP-0003 | blocked | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | | workplan | REEF-RAILIANCE-WP-0004 | finished | — | workplans/REEF-RAILIANCE-WP-0004-exposure-grants.md | +| workplan | REEF-RAILIANCE-WP-0005 | finished | — | workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.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 | @@ -28,3 +29,6 @@ | task | REEF-RAILIANCE-WP-0003-T04 | wait | — | workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md | | task | REEF-RAILIANCE-WP-0004-T01 | done | — | workplans/REEF-RAILIANCE-WP-0004-exposure-grants.md | | task | REEF-RAILIANCE-WP-0004-T02 | done | — | workplans/REEF-RAILIANCE-WP-0004-exposure-grants.md | +| task | REEF-RAILIANCE-WP-0005-T01 | done | — | workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.md | +| task | REEF-RAILIANCE-WP-0005-T02 | done | — | workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.md | +| task | REEF-RAILIANCE-WP-0005-T03 | done | — | workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.md | diff --git a/bindings/rails.yaml b/bindings/rails.yaml index f158337..1e06bc4 100644 --- a/bindings/rails.yaml +++ b/bindings/rails.yaml @@ -2,16 +2,18 @@ reef_id: reef-railiance hosted_rails: - rail_id: rail-kubernetes role: primary - readiness_state: declared + readiness_state: verified contract_version: 1.0.0 evidence: - evidence/admission/rail-kubernetes-baseline.json - notes: First-wave default execution rail for the grouped Railiance home reef. + - evidence/verification/rail-runtime-2026-08-21.json + notes: First-wave default execution rail; live verification still records one Ready control-plane and etcd node. - rail_id: rail-knative role: derived - readiness_state: declared + readiness_state: verified contract_version: 1.0.0 base_rail: rail-kubernetes evidence: - evidence/admission/rail-knative-baseline.json - notes: Declared second-wave rail; not installed or production-approved. + - evidence/verification/rail-runtime-2026-08-21.json + notes: Installed and verified for private operation; production approval remains blocked by the single-node failure domain. diff --git a/bindings/rapps.yaml b/bindings/rapps.yaml index 3fc107a..bbc8877 100644 --- a/bindings/rapps.yaml +++ b/bindings/rapps.yaml @@ -1,13 +1,30 @@ reef_id: reef-railiance bound_rapps: + - rapp_id: rapp-issue-core + rail_id: rail-kubernetes + package_readiness_state: verified + readiness_state: verified + evidence: + - ../rapp-issue-core/declarations/rapp.yaml + - ../rapp-issue-core/evidence/live/2026-08-19-railiance01.json + - rapp_id: rapp-openbao + rail_id: rail-kubernetes + package_readiness_state: verified + readiness_state: verified + evidence: + - ../rapp-openbao/declarations/rapp.yaml + - ../railiance-platform/docs/rapp-openbao-boundary.md + - ../railiance-platform/docs/openbao.md - rapp_id: rapp-qonto rail_id: rail-knative + package_readiness_state: verified readiness_state: verified evidence: - ../rapp-qonto/docs/security-and-reliability-gates.md - ../rapp-qonto/evidence/live/2026-07-29-railiance01.json - rapp_id: rapp-policy-nexus rail_id: rail-kubernetes + package_readiness_state: verified readiness_state: production-approved evidence: - ../rapp-policy-nexus/declarations/rapp.yaml @@ -15,7 +32,24 @@ bound_rapps: - ../rapp-policy-nexus/bindings/reef-railiance.yaml - ../rapp-policy-nexus/evidence/live/2026-08-18-railiance01.json - ../rapp-policy-nexus/evidence/live/2026-08-18-railiance01-release2-rollback.json + - rapp_id: rapp-postgres + rail_id: rail-kubernetes + package_readiness_state: verified + readiness_state: verified + evidence: + - ../rapp-postgres/declarations/rapp.yaml + - ../rapp-postgres/docs/evidence/node-reboot-2026-08-16.md + - ../rapp-postgres/docs/evidence/backup-restore-2026-08-13.md + - rapp_id: rapp-user-engine + rail_id: rail-kubernetes + package_readiness_state: verified + readiness_state: declared + evidence: + - ../rapp-user-engine/declarations/rapp.yaml + - ../rapp-user-engine/bindings/reef-railiance.yaml notes: + - Membership is the derived projection of rApp declarations whose bound_reefs includes reef-railiance; package_readiness_state is not reef binding admission. - The Qonto binding is verified for non-production operation; production approval remains separate. - The policy-nexus release-2 binding is deployed and verified; rollback to release 1 and forward restoration to release 2 were exercised successfully on 2026-08-18. + - User Engine remains declared at the reef binding even though its package readiness is verified. - Add or promote bindings only when the substrate decision is explicit and source-backed. diff --git a/evidence/admission/rail-knative-baseline.json b/evidence/admission/rail-knative-baseline.json index 2c657a9..719acc6 100644 --- a/evidence/admission/rail-knative-baseline.json +++ b/evidence/admission/rail-knative-baseline.json @@ -3,29 +3,60 @@ "reef_id": "reef-railiance", "subject": "rail-knative", "readiness_state": "verified", - "checked_at": "2026-07-26T18:00:00Z", + "checked_at": "2026-08-20T23:55:06Z", "checks": { "compatibility": { "status": "pass", "evidence": [ "../rail-knative/declarations/rail.yaml", - "../rail-kubernetes/declarations/rail.yaml" + "../rail-kubernetes/declarations/rail.yaml", + "../verification/rail-runtime-2026-08-21.json" ], "notes": "Knative 1.22 minimum Kubernetes 1.34; observed Kubernetes 1.35.1." }, "capacity": { "status": "pass", - "evidence": ["../preflight/knative-2026-07-26-success.json"], - "notes": "Installation verification passed; 4 CPU remains below the generic 6 CPU recommendation." + "evidence": ["../verification/rail-runtime-2026-08-21.json"], + "notes": "All Knative control-plane deployments are available; 4 CPU remains below the generic 6 CPU recommendation." + }, + "ingress": { + "status": "pass", + "evidence": [ + "../verification/rail-knative-v1.22.0-2026-07-26.json", + "../verification/rail-runtime-2026-08-21.json" + ], + "notes": "Kourier remains ClusterIP-only; public exposure is disabled." + }, + "network": { + "status": "pass", + "evidence": [ + "../verification/rail-knative-v1.22.0-2026-07-26.json", + "../verification/rail-runtime-2026-08-21.json", + "../../../rapp-qonto/evidence/live/2026-07-29-railiance01.json" + ] + }, + "identity_and_secrets": { + "status": "pass", + "evidence": ["../../../rapp-qonto/evidence/live/2026-07-29-railiance01.json"] + }, + "observability": { + "status": "pass", + "evidence": [ + "../verification/rail-knative-v1.22.0-2026-07-26.json", + "../verification/rail-runtime-2026-08-21.json" + ], + "notes": "Control-plane availability and lifecycle observations are recorded." + }, + "recovery": { + "status": "pass", + "evidence": [ + "../verification/rail-knative-v1.22.0-2026-07-26.json", + "../../../rapp-qonto/evidence/live/2026-07-29-railiance01.json" + ] }, - "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": "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": "fail", - "evidence": ["../preflight/knative-2026-07-26-success.json"], + "evidence": ["../verification/rail-runtime-2026-08-21.json"], "notes": "Production approval is rejected while Knative shares the single-member control plane." } }, @@ -33,8 +64,8 @@ { "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." + "owner": "railiance-infra", + "decision": "Not accepted for production; verified non-production rail operation may continue." } ] } diff --git a/evidence/admission/rail-kubernetes-baseline.json b/evidence/admission/rail-kubernetes-baseline.json index d5c3bad..2fc47a4 100644 --- a/evidence/admission/rail-kubernetes-baseline.json +++ b/evidence/admission/rail-kubernetes-baseline.json @@ -2,31 +2,43 @@ "contract_version": "1.0.0", "reef_id": "reef-railiance", "subject": "rail-kubernetes", - "readiness_state": "declared", - "checked_at": "2026-07-26T00:00:00Z", + "readiness_state": "verified", + "checked_at": "2026-08-20T23:55:06Z", "checks": { "compatibility": { "status": "pass", "evidence": [ "declarations/reef.yaml", "bindings/rails.yaml", - "../rail-kubernetes/declarations/rail.yaml" + "../rail-kubernetes/declarations/rail.yaml", + "../verification/rail-runtime-2026-08-21.json" ] }, "capacity": { - "status": "unknown", - "evidence": [], - "notes": "Automated capacity and headroom probe not yet recorded." + "status": "pass", + "evidence": ["../verification/rail-runtime-2026-08-21.json"], + "notes": "The only node is Ready with 4 CPU and 16377028Ki allocatable memory; production failure-domain risk remains open." + }, + "ingress": { + "status": "pass", + "evidence": ["../verification/rail-runtime-2026-08-21.json"], + "notes": "Traefik is the observed ingress class." + }, + "network": { + "status": "pass", + "evidence": [ + "../verification/rail-runtime-2026-08-21.json", + "../../../rapp-qonto/evidence/live/2026-07-29-railiance01.json" + ], + "notes": "NetworkPolicy objects are present and the Qonto binding has workload-level restricted-egress evidence." }, - "ingress": {"status": "unknown", "evidence": []}, - "network": {"status": "unknown", "evidence": []}, "identity_and_secrets": {"status": "unknown", "evidence": []}, "observability": {"status": "unknown", "evidence": []}, "recovery": {"status": "unknown", "evidence": []}, "failure_domain": { - "status": "unknown", - "evidence": [], - "notes": "Current grouped reef has one declared member." + "status": "fail", + "evidence": ["../verification/rail-runtime-2026-08-21.json"], + "notes": "Current grouped reef has one Ready member carrying control-plane and etcd roles." } }, "residual_risks": [ diff --git a/evidence/verification/rail-runtime-2026-08-21.json b/evidence/verification/rail-runtime-2026-08-21.json new file mode 100644 index 0000000..502821e --- /dev/null +++ b/evidence/verification/rail-runtime-2026-08-21.json @@ -0,0 +1,76 @@ +{ + "schema_version": "reef-railiance.rail-runtime-evidence/v1", + "collected_at": "2026-08-20T23:55:06Z", + "collector": "reef-railiance/tools/collect_rail_runtime_evidence.sh", + "executor": "operator-ssh", + "context": "default", + "kubernetes": { + "server_version": "v1.35.1+k3s1", + "nodes": { + "total": 1, + "ready": 1, + "members": [ + { + "name": "239.62.205.92.host.secureserver.net", + "roles": ["control-plane", "etcd"], + "kubelet_version": "v1.35.1+k3s1", + "allocatable": {"cpu": "4", "memory": "16377028Ki", "pods": "110"} + } + ] + }, + "ingress_classes": ["traefik"], + "storage_classes": ["local-path"], + "network_policy_count": 79 + }, + "knative": { + "deployments": [ + { + "name": "activator", + "desired": 1, + "available": 1, + "images": ["gcr.io/knative-releases/knative.dev/serving/cmd/activator@sha256:8f7e9df2642a8ba715ebc55b62abee17b0984b6b6af0c6ec00dabaadf5f8cccb"] + }, + { + "name": "autoscaler", + "desired": 1, + "available": 1, + "images": ["gcr.io/knative-releases/knative.dev/serving/cmd/autoscaler@sha256:ec66d97244395b57a67923d4a8c5a95f0264805f1fdb2ee0cdb49ec0f3bd7855"] + }, + { + "name": "controller", + "desired": 1, + "available": 1, + "images": ["gcr.io/knative-releases/knative.dev/serving/cmd/controller@sha256:6833f2c83e9f356c274ddb2de40e5471ad2b1c08882c9bd11f5afa240e86d574"] + }, + { + "name": "net-kourier-controller", + "desired": 1, + "available": 1, + "images": ["gcr.io/knative-releases/knative.dev/net-kourier/cmd/kourier@sha256:a2e8f568a4bf68ef6391bc3afea956d11a8698f6a22c4be50844b1da4f8bcc74"] + }, + { + "name": "webhook", + "desired": 1, + "available": 1, + "images": ["gcr.io/knative-releases/knative.dev/serving/cmd/webhook@sha256:c505888f7ee34ccadc1b9a6877d6d49691f633ea28cf8cbe03fcfa6d3afcd584"] + } + ], + "all_deployments_available": true, + "ingress": { + "implementation": "net-kourier", + "service_type": "ClusterIP", + "cluster_ip": "10.43.29.12" + }, + "services": [ + { + "namespace": "rapp-qonto", + "name": "rapp-qonto", + "latest_created_revision": "rapp-qonto-00008", + "latest_ready_revision": "rapp-qonto-00008", + "ready": true + } + ] + }, + "failure_domain": {"independent_members_observed": 1, "result": "fail-single-node"}, + "secret_values_collected": false +} diff --git a/tests/test_binding_projection.py b/tests/test_binding_projection.py new file mode 100644 index 0000000..998ca50 --- /dev/null +++ b/tests/test_binding_projection.py @@ -0,0 +1,65 @@ +import importlib.util +from pathlib import Path + +import yaml + + +MODULE = Path(__file__).parents[1] / "tools/check_binding_projection.py" +SPEC = importlib.util.spec_from_file_location("binding_projection", MODULE) +binding_projection = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(binding_projection) + + +def write_yaml(path: Path, value: dict) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(yaml.safe_dump(value, sort_keys=False), encoding="utf-8") + + +def test_matching_projection_passes(tmp_path): + repo = tmp_path / "reef-example" + write_yaml( + repo / "declarations/reef.yaml", + {"reef_id": "reef-example", "hosted_rails": ["rail-kubernetes"]}, + ) + write_yaml( + repo / "bindings/rails.yaml", + {"hosted_rails": [{"rail_id": "rail-kubernetes"}]}, + ) + write_yaml( + repo / "bindings/rapps.yaml", + {"bound_rapps": [{"rapp_id": "rapp-example"}]}, + ) + write_yaml( + tmp_path / "rail-kubernetes/declarations/rail.yaml", + {"rail_id": "rail-kubernetes"}, + ) + write_yaml( + tmp_path / "rapp-example/declarations/rapp.yaml", + {"rapp_id": "rapp-example", "bound_reefs": ["reef-example"]}, + ) + + assert binding_projection.assess(repo, tmp_path) == [] + + +def test_stale_rapp_projection_fails(tmp_path): + repo = tmp_path / "reef-example" + write_yaml( + repo / "declarations/reef.yaml", + {"reef_id": "reef-example", "hosted_rails": ["rail-kubernetes"]}, + ) + write_yaml( + repo / "bindings/rails.yaml", + {"hosted_rails": [{"rail_id": "rail-kubernetes"}]}, + ) + write_yaml(repo / "bindings/rapps.yaml", {"bound_rapps": []}) + write_yaml( + tmp_path / "rail-kubernetes/declarations/rail.yaml", + {"rail_id": "rail-kubernetes"}, + ) + write_yaml( + tmp_path / "rapp-example/declarations/rapp.yaml", + {"rapp_id": "rapp-example", "bound_reefs": ["reef-example"]}, + ) + + failures = binding_projection.assess(repo, tmp_path) + assert failures and "rapp projection differs" in failures[0] diff --git a/tools/check_binding_projection.py b/tools/check_binding_projection.py new file mode 100755 index 0000000..6ba8c60 --- /dev/null +++ b/tools/check_binding_projection.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Check reef binding files against authoritative sibling declarations.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + +import yaml + + +def load_yaml(path: Path) -> dict: + value = yaml.safe_load(path.read_text(encoding="utf-8")) + if not isinstance(value, dict): + raise ValueError(f"{path}: expected a YAML mapping") + return value + + +def ids(items: object, key: str) -> set[str]: + if not isinstance(items, list): + return set() + return { + item[key] + for item in items + if isinstance(item, dict) and isinstance(item.get(key), str) + } + + +def expected_rapps(parent: Path, reef_id: str) -> set[str]: + result: set[str] = set() + for declaration_path in sorted(parent.glob("rapp-*/declarations/rapp.yaml")): + declaration = load_yaml(declaration_path) + if reef_id in declaration.get("bound_reefs", []): + result.add(str(declaration["rapp_id"])) + return result + + +def expected_rails(parent: Path, declared: list[str]) -> set[str]: + result: set[str] = set() + for rail_id in declared: + declaration_path = parent / rail_id / "declarations" / "rail.yaml" + declaration = load_yaml(declaration_path) + result.add(str(declaration["rail_id"])) + return result + + +def assess(repo: Path, parent: Path) -> list[str]: + reef = load_yaml(repo / "declarations" / "reef.yaml") + reef_id = str(reef["reef_id"]) + rapp_bindings = load_yaml(repo / "bindings" / "rapps.yaml") + rail_bindings = load_yaml(repo / "bindings" / "rails.yaml") + + actual_rapps = ids(rapp_bindings.get("bound_rapps"), "rapp_id") + derived_rapps = expected_rapps(parent, reef_id) + actual_rails = ids(rail_bindings.get("hosted_rails"), "rail_id") + derived_rails = expected_rails(parent, list(reef.get("hosted_rails", []))) + + failures: list[str] = [] + if actual_rapps != derived_rapps: + failures.append( + f"rapp projection differs: binding={sorted(actual_rapps)}, " + f"derived={sorted(derived_rapps)}" + ) + if actual_rails != derived_rails: + failures.append( + f"rail projection differs: binding={sorted(actual_rails)}, " + f"declared={sorted(derived_rails)}" + ) + return failures + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--repo", type=Path, default=Path(__file__).parents[1]) + parser.add_argument("--parent", type=Path) + args = parser.parse_args() + repo = args.repo.resolve() + parent = (args.parent or repo.parent).resolve() + failures = assess(repo, parent) + print(json.dumps({"pass": not failures, "failures": failures})) + return bool(failures) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/collect_rail_runtime_evidence.sh b/tools/collect_rail_runtime_evidence.sh new file mode 100755 index 0000000..1f3be11 --- /dev/null +++ b/tools/collect_rail_runtime_evidence.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Read-only, secret-free evidence collector for the rails hosted by this reef. +# The cluster API is intentionally reached through the operator SSH path; 6443 +# remains non-public. Override only when the approved executor name changes. +remote_host="${RAIL_RUNTIME_HOST:-railiance01}" + +ssh -o BatchMode=yes "$remote_host" 'bash -s' <<'REMOTE' +set -euo pipefail + +context="$(kubectl config current-context)" +server_version="$(kubectl version -o json | jq -r '.serverVersion.gitVersion')" +nodes="$(kubectl get nodes -o json)" +knative_deployments="$(kubectl -n knative-serving get deployments -o json)" +kourier_service="$(kubectl -n kourier-system get service kourier -o json)" +knative_services="$(kubectl get ksvc -A -o json)" +ingress_classes="$(kubectl get ingressclass -o json)" +storage_classes="$(kubectl get storageclass -o json)" +network_policy_count="$(kubectl get networkpolicy -A -o json | jq '.items | length')" + +jq -n \ + --arg context "$context" \ + --arg server_version "$server_version" \ + --argjson nodes "$nodes" \ + --argjson deployments "$knative_deployments" \ + --argjson kourier "$kourier_service" \ + --argjson services "$knative_services" \ + --argjson ingress_classes "$ingress_classes" \ + --argjson storage_classes "$storage_classes" \ + --argjson network_policy_count "$network_policy_count" \ + '{ + schema_version: "reef-railiance.rail-runtime-evidence/v1", + collected_at: (now | todateiso8601), + collector: "reef-railiance/tools/collect_rail_runtime_evidence.sh", + executor: "operator-ssh", + context: $context, + kubernetes: { + server_version: $server_version, + nodes: { + total: ($nodes.items | length), + ready: ([$nodes.items[] | select(any(.status.conditions[]; .type == "Ready" and .status == "True"))] | length), + members: [$nodes.items[] | { + name: .metadata.name, + roles: ([.metadata.labels | keys[] | select(startswith("node-role.kubernetes.io/")) | split("/")[1]] | sort), + kubelet_version: .status.nodeInfo.kubeletVersion, + allocatable: { + cpu: .status.allocatable.cpu, + memory: .status.allocatable.memory, + pods: .status.allocatable.pods + } + }] + }, + ingress_classes: [$ingress_classes.items[].metadata.name] | sort, + storage_classes: [$storage_classes.items[].metadata.name] | sort, + network_policy_count: $network_policy_count + }, + knative: { + deployments: [$deployments.items[] | { + name: .metadata.name, + desired: (.spec.replicas // 0), + available: (.status.availableReplicas // 0), + images: [.spec.template.spec.containers[].image] + }] | sort_by(.name), + all_deployments_available: (all($deployments.items[]; (.status.availableReplicas // 0) >= (.spec.replicas // 0))), + ingress: { + implementation: "net-kourier", + service_type: $kourier.spec.type, + cluster_ip: $kourier.spec.clusterIP + }, + services: [$services.items[] | { + namespace: .metadata.namespace, + name: .metadata.name, + latest_created_revision: .status.latestCreatedRevisionName, + latest_ready_revision: .status.latestReadyRevisionName, + ready: (any(.status.conditions[]?; .type == "Ready" and .status == "True")) + }] | sort_by(.namespace, .name) + }, + failure_domain: { + independent_members_observed: ($nodes.items | length), + result: (if ($nodes.items | length) > 1 then "requires-source-backed-review" else "fail-single-node" end) + }, + secret_values_collected: false + }' +REMOTE diff --git a/workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md b/workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md index eb0146a..723e565 100644 --- a/workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md +++ b/workplans/REEF-RAILIANCE-WP-0001-bootstrap-and-wave1-import.md @@ -8,7 +8,11 @@ status: finished owner: codex topic_slug: railiance created: "2026-07-26" -updated: "2026-07-26" +updated: "2026-08-21" +quality_dod: DoD-Ok +quality_dod_at: "2026-08-21" +quality_dod_by: codex +quality_dod_note: "Retrospective assessment: all four tasks are done, the grouped boundary and handoff remain current, and repository checks pass." state_hub_workstream_id: "da64c718-68bf-4719-aa42-fcf26687ab23" --- 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 e8c253d..d6aa0b5 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 @@ -8,7 +8,11 @@ status: finished owner: codex topic_slug: railiance created: "2026-07-26" -updated: "2026-07-26" +updated: "2026-08-21" +quality_dod: DoD-Ok +quality_dod_at: "2026-08-21" +quality_dod_by: codex +quality_dod_note: "Retrospective assessment: completed and cancelled work is explicit, Qonto residual work transferred to WP-0003, and rail evidence checks pass." state_hub_workstream_id: "5b31c13e-ddc9-495f-8325-88fa770982c5" --- diff --git a/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md b/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md index 5535665..6978fdc 100644 --- a/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md +++ b/workplans/REEF-RAILIANCE-WP-0003-rapp-qonto-production-gates.md @@ -8,9 +8,9 @@ status: blocked owner: codex topic_slug: railiance created: "2026-07-26" -updated: "2026-08-15" +updated: "2026-08-21" related: - - RAIL-BS-WP-0007 + - RCLUSTER-WP-0007 - RMASTER-WP-0023 - ADR-0006 - ADR-0008 @@ -21,7 +21,7 @@ state_hub_workstream_id: "c3f9fbfd-3db1-4387-8b65-7d53ba57138d" This reef records the `rapp-qonto` binding and refuses `production-approved` without ADR-0006 evidence. It does not implement -HA (`RAIL-BS-WP-0007`), Knative packaging (`rapp-qonto`), or public +HA (`RCLUSTER-WP-0007`), Knative packaging (`rapp-qonto`), or public listeners. Production approval does not make Qonto public (ADR-0008). New binds stay `private`. Exposure grants for already-public surfaces are `REEF-RAILIANCE-WP-0004`, not this file. @@ -133,7 +133,7 @@ single-node production availability risk for Qonto. The current binding remains accurately `verified`, not `production-approved`. 2026-08-08 alignment: live inspection still reports one Ready node, which also -owns the control-plane and etcd roles. `railiance-cluster/RAIL-BS-WP-0007` now +owns the control-plane and etcd roles. `railiance-cluster/RCLUSTER-WP-0007` now owns the required three-server embedded-etcd topology, source-backed node-to-reef failure-domain map, and machine-readable one-server-loss S2 drill. `state-hub/CUST-WP-0038` is a downstream stateful consumer and does not @@ -144,6 +144,12 @@ dependency behavior, and restoration on the surviving cluster. The alternate closure remains explicit founder acceptance of the single-node production availability risk. +2026-08-21 evidence refresh: the read-only reef collector still observes one +Ready Kubernetes node carrying both control-plane and etcd roles. All five +Knative control-plane deployments and `rapp-qonto-00008` are Ready, and Kourier +remains ClusterIP-only. `RCLUSTER-WP-0007` is still backlog, so this is fresh +evidence for retaining the block, not grounds for production promotion. + This repo only updates `bindings/rapps.yaml` when those conditions hold. Do not implement the three-node topology here. Do not add an exposure grant for Qonto as a side effect of `production-approved`. diff --git a/workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.md b/workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.md new file mode 100644 index 0000000..c3bc77d --- /dev/null +++ b/workplans/REEF-RAILIANCE-WP-0005-binding-and-evidence-reconciliation.md @@ -0,0 +1,90 @@ +--- +id: REEF-RAILIANCE-WP-0005 +type: workplan +title: "Reconcile reef bindings and refresh rail evidence" +domain: financials +repo: reef-railiance +status: finished +owner: codex +topic_slug: railiance +created: "2026-08-21" +updated: "2026-08-21" +quality_dod: DoD-Ok +quality_dod_at: "2026-08-21" +quality_dod_by: codex +quality_dod_note: "Binding projections match family declarations, live rail evidence is fresh, tests pass, and the Qonto production block remains explicit." +related: + - REEF-RAILIANCE-WP-0002 + - REEF-RAILIANCE-WP-0003 + - ADR-0006 + - ADR-0007 +state_hub_workstream_id: "99e8e93b-99a0-4ef6-91d7-e4f155fa7ee9" +--- + +# REEF-RAILIANCE-WP-0005 — binding and evidence reconciliation + +## Goal + +Remove drift between the reef-local binding surfaces, family declarations, +and current secret-free runtime evidence without promoting any workload beyond +its proven reef admission state. + +## T01 — Refresh hosted-rail evidence + +```task +id: REEF-RAILIANCE-WP-0005-T01 +status: done +priority: high +state_hub_task_id: "bebf85e7-db0a-41f1-9ad3-a7e184a6249c" +``` + +Add a repeatable operator-SSH collector, capture fresh Kubernetes and Knative +runtime evidence, and reconcile both hosted rails to `verified`. + +Completed 2026-08-21. The collector observed Kubernetes v1.35.1+k3s1, one of +one nodes Ready, all five Knative control-plane deployments available, Kourier +as ClusterIP, and the Qonto Knative Service Ready. No Secret resources or +values were read. The one-node control-plane/etcd failure-domain check remains +failed, so neither the rail nor Qonto gained production approval. + +## T02 — Reconcile the rApp binding projection + +```task +id: REEF-RAILIANCE-WP-0005-T02 +status: done +priority: high +state_hub_task_id: "88fb7abe-6b85-4cae-bd0b-d6d7c4a5deaa" +``` + +Project every family rApp whose declaration names `reef-railiance`, while +keeping package readiness distinct from reef binding admission. Add a check +that fails when the local relation files diverge from sibling declarations. + +Completed 2026-08-21. `bindings/rapps.yaml` now covers `rapp-issue-core`, +`rapp-openbao`, `rapp-policy-nexus`, `rapp-postgres`, `rapp-qonto`, and +`rapp-user-engine`. Only Policy Nexus is `production-approved`; Qonto remains +`verified`, and User Engine remains `declared` at the reef binding. + +## T03 — Close documentation and quality drift + +```task +id: REEF-RAILIANCE-WP-0005-T03 +status: done +priority: medium +state_hub_task_id: "923647a0-1010-4023-8f2f-9e69c9f0b8e1" +``` + +Correct the renamed ThreePhoenix dependency, state the current blocker in the +orientation docs, and retrospectively assess the completed WP-0001 and WP-0002 +records against the current workplan Definition of Done. + +Completed 2026-08-21. References now use `RCLUSTER-WP-0007`; the README and +scope state the fresh single-node result; WP-0001 and WP-0002 are DoD-Ok. + +## Outcome + +The reef-local relationship files are current and mechanically checked. Rail +evidence is fresh and secret-free. `REEF-RAILIANCE-WP-0003` remains correctly +blocked until ThreePhoenix produces independent-failure-domain evidence and +Qonto is reverified during loss of Railiance01, or the founder explicitly +accepts the single-node availability risk.