diff --git a/.github/workflows/build-clp-001-s-postgres.yml b/.github/workflows/build-clp-001-s-postgres.yml new file mode 100644 index 0000000..56199f7 --- /dev/null +++ b/.github/workflows/build-clp-001-s-postgres.yml @@ -0,0 +1,126 @@ +name: BUILD-CLP-001-S Governance Health Gate +on: + pull_request: + paths: + - 'governance/clp-001/builds/BUILD-CLP-001-S/**' + - '.github/workflows/build-clp-001-s-postgres.yml' +jobs: + postgres-s-health: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:16 + env: + POSTGRES_PASSWORD: postgres + ports: ['5432:5432'] + options: >- + --health-cmd "pg_isready -U postgres" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + PGHOST: 127.0.0.1 + PGPORT: 5432 + PGUSER: postgres + PGPASSWORD: postgres + PGDATABASE: postgres + FROZEN_S_MANIFEST_SHA256: aba8841c7e0c175c308e7e6410367874a9e41ec562de53bfd38e5820a728ea25 + steps: + - uses: actions/checkout@v4 + - name: Report exact S source hashes + run: | + root=governance/clp-001/builds/BUILD-CLP-001-S + for f in \ + migrations/003_clp001_s_governance_health.sql \ + migrations/004_clp001_s_review_hardening.sql \ + migrations/005_clp001_s_canonical_binding.sql \ + migrations/006_clp001_s_exact_evidence_binding.sql \ + tests/s-health.sql \ + tests/s-health-v102.sql \ + fixtures/repository-observations.sql \ + fixtures/G0-STATUS-SUPERSESSION.json \ + fixtures/R-INDEPENDENT-REVIEW-RECEIPT.json \ + README-S.md \ + docs/BUILD-CLP-001-S-SPEC.md \ + docs/2026-10-04-build-clp-001-s-plan.md; do + bytes=$(wc -c < "$root/$f" | tr -d ' ') + hash=$(sha256sum "$root/$f" | awk '{print $1}') + echo "S_SOURCE $f $bytes $hash" + done + - name: Verify frozen S source manifest + run: | + python3 - <<'PY' + import hashlib, json, os, pathlib, sys + root = pathlib.Path('governance/clp-001/builds/BUILD-CLP-001-S') + manifest_path = root / 'receipts/S-source-manifest.json' + receipt_path = root / 'receipts/BUILD-CLP-001-S-verification.json' + manifest_bytes = manifest_path.read_bytes() + manifest_sha = hashlib.sha256(manifest_bytes).hexdigest() + manifest = json.loads(manifest_bytes) + receipt = json.loads(receipt_path.read_text()) + frozen_sha = os.environ['FROZEN_S_MANIFEST_SHA256'] + failures = [] + if manifest_sha != frozen_sha: + failures.append(f'MANIFEST_DIGEST expected={frozen_sha} observed={manifest_sha}') + if receipt.get('source_manifest_sha256') != manifest_sha: + failures.append(f"RECEIPT_MANIFEST_DIGEST expected={receipt.get('source_manifest_sha256')} observed={manifest_sha}") + required = { + 'migrations/003_clp001_s_governance_health.sql', + 'migrations/004_clp001_s_review_hardening.sql', + 'migrations/005_clp001_s_canonical_binding.sql', + 'migrations/006_clp001_s_exact_evidence_binding.sql', + 'tests/s-health.sql', + 'tests/s-health-v102.sql', + 'fixtures/repository-observations.sql', + 'fixtures/G0-STATUS-SUPERSESSION.json', + 'fixtures/R-INDEPENDENT-REVIEW-RECEIPT.json', + 'README-S.md', + 'docs/BUILD-CLP-001-S-SPEC.md', + 'docs/2026-10-04-build-clp-001-s-plan.md', + } + listed = [item['path'] for item in manifest['files']] + if set(listed) != required or len(listed) != len(required): + failures.append(f'INVENTORY expected={sorted(required)} observed={sorted(listed)}') + for item in manifest['files']: + path = root / item['path'] + if not path.is_file(): + failures.append(f"MISSING {item['path']}") + continue + data = path.read_bytes() + observed_hash = hashlib.sha256(data).hexdigest() + observed_bytes = len(data) + print(f"S_MANIFEST {item['path']} {observed_bytes} {observed_hash}") + if observed_bytes != item['bytes']: + failures.append(f"SIZE {item['path']} expected={item['bytes']} observed={observed_bytes}") + if observed_hash != item['sha256']: + failures.append(f"HASH {item['path']} expected={item['sha256']} observed={observed_hash}") + if failures: + print('\n'.join(failures), file=sys.stderr) + raise SystemExit(1) + print(f'S_SOURCE_MANIFEST_PASS {manifest_sha}') + PY + - name: Report workflow hash + run: sha256sum .github/workflows/build-clp-001-s-postgres.yml + - name: Install PostgreSQL client + run: sudo apt-get update && sudo apt-get install -y postgresql-client + - name: Apply Q, R, S migrations + run: | + psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-Q/migrations/001_clp001_q.sql + psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-R/migrations/002_clp001_r.sql + psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/migrations/003_clp001_s_governance_health.sql + psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/migrations/004_clp001_s_review_hardening.sql + psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/migrations/005_clp001_s_canonical_binding.sql + psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/migrations/006_clp001_s_exact_evidence_binding.sql + - name: Load repository governance observations + run: psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/fixtures/repository-observations.sql + - name: Run deterministic S health rules T1-T14 + run: psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health.sql + - name: Run deterministic S v1.0.2 rules T15-T16 + run: psql -v ON_ERROR_STOP=1 -f governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health-v102.sql + - name: Verify live EdOpSys projection + run: | + row=$(psql -At -F '|' -c "SELECT overall_health,blocking_reason_count,governance_status,build_status,ci_status,integrity_status,review_status,authority_status,drift_status FROM edopsys_observability.v_repository_health WHERE repository='JaeTierce31/EdOpSys'") + test "$row" = "DEGRADED|0|CURRENT|HEALTHY|PASS|HEALTHY|HEALTHY|DEGRADED|HEALTHY" + json=$(psql -Atc "SELECT dashboard::text FROM edopsys_observability.v_dashboard_summary_json WHERE repository='JaeTierce31/EdOpSys'") + test -n "$json" + echo "$json" diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/README-S.md b/governance/clp-001/builds/BUILD-CLP-001-S/README-S.md new file mode 100644 index 0000000..c8cc571 --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/README-S.md @@ -0,0 +1,37 @@ +# BUILD-CLP-001-S — Repository Governance Observability + Health Projection + +Parent baseline: `b0f19f2d0ce8a086604ed1f08d1202cd5650dae8` (merged BUILD-CLP-001-R). + +S adds an append-only PostgreSQL observability schema and deterministic views for repository/build/authority/integrity/CI/review/drift health. It does not alter CLP domain semantics and does not authorize domain actions. + +## Canonical boundary + +> Observability projections are descriptive and MUST NOT authorize CLP state transitions, worker eligibility, verification, payout, or policy execution. + +## Health model + +- `BLOCKED`: unresolved P0/P1, required artifact failure, canonical CI failure, blocking authority conflict, or blocked canonical build. +- `UNKNOWN`: required observations are absent or verification is incomplete. +- `DEGRADED`: stale-head CI, authority freshness debt, unresolved P2, or non-blocking open drift. +- `HEALTHY`: all required gates present and passing. + +## Dashboard views + +- `v_build_health` +- `v_authority_health` +- `v_integrity_health` +- `v_ci_health` +- `v_review_health` +- `v_governance_assertion_current` +- `v_governance_drift` +- `v_governance_timeline` +- `v_repository_health` +- `v_dashboard_summary_json` + +## Stale G0 supersession + +`governance/clp-001/g0/G0-STATUS.json` is preserved as historical evidence. `fixtures/G0-STATUS-SUPERSESSION.json` records why its earlier blocked operational status is superseded by the later G0 designation without rewriting history. + +## Verification + +`tests/s-health.sql` contains deterministic T1–T10 tests. The GitHub Actions PostgreSQL 16 gate applies Q→R→S migrations, loads repository observations, runs T1–T10, and checks the live EdOpSys projection. diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/docs/2026-10-04-build-clp-001-s-plan.md b/governance/clp-001/builds/BUILD-CLP-001-S/docs/2026-10-04-build-clp-001-s-plan.md new file mode 100644 index 0000000..23f6adf --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/docs/2026-10-04-build-clp-001-s-plan.md @@ -0,0 +1,51 @@ +# BUILD-CLP-001-S Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Build an append-only PostgreSQL governance observability projection and deterministic repository-health views without granting execution authority. + +**Architecture:** Source evidence is ingested as append-only observations/snapshots in `edopsys_observability`; deterministic SQL views compute domain health. A dedicated assertion/supersession model preserves stale historical facts while resolving current truth through higher-authority later evidence. + +**Tech Stack:** PostgreSQL 16, SQL/PLpgSQL, GitHub Actions. + +**Spec:** `docs/BUILD-CLP-001-S-SPEC.md` + +## Global Constraints +- Parent baseline MUST be merged R `b0f19f2d0ce8a086604ed1f08d1202cd5650dae8`. +- Observability MUST NOT mutate CLP domain history or authorize domain actions. +- Existing Q/R constraints and triggers MUST remain unchanged. +- UNKNOWN MUST NOT collapse into HEALTHY. +- Historical stale G0 evidence MUST be superseded, never rewritten/deleted. + +## Review Focus +- Missing observation sets return UNKNOWN rather than optimistic health. +- CI success on a stale head returns STALE_HEAD/DEGRADED. +- Resolved/superseded P1 findings no longer block. +- Historical G0 blockage remains queryable while current G0 status resolves designated. +- Append-only protections reject mutation in both CLP and observability tables. + +--- + +### Task 1: Schema + append-only observation model +**Files:** migration and SQL tests. +- [ ] Write failing schema contract tests. +- [ ] Implement schema/tables/comments/triggers. +- [ ] Verify schema contract passes. + +### Task 2: Deterministic health views +**Files:** migration and health-rule tests. +- [ ] Write T1-T9 failing health tests. +- [ ] Implement build/integrity/CI/review/authority/drift/repository/timeline/JSON views. +- [ ] Verify all health tests pass. + +### Task 3: Stale-G0 supersession fixture +**Files:** `fixtures/repository-observations.sql`. +- [ ] Write fixture assertions for historical blockage + current designation + resolved drift. +- [ ] Insert machine-readable assertions, supersession receipt and resolved drift record. +- [ ] Verify current G0 projection is not BLOCKED by the historical assertion. + +### Task 4: PostgreSQL 16 gate + immutable-domain test +**Files:** workflow and `tests/s-health.sql`. +- [ ] Add T10 mutation rejection test for CLP and observability. +- [ ] Run migration + fixture + tests against PostgreSQL 16 in CI. +- [ ] Record exact-head run before review. diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/docs/BUILD-CLP-001-S-SPEC.md b/governance/clp-001/builds/BUILD-CLP-001-S/docs/BUILD-CLP-001-S-SPEC.md new file mode 100644 index 0000000..88aec5b --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/docs/BUILD-CLP-001-S-SPEC.md @@ -0,0 +1,29 @@ +# BUILD-CLP-001-S — Repository Governance Observability + Health Projection + +Baseline: `b0f19f2d0ce8a086604ed1f08d1202cd5650dae8` (merged BUILD-CLP-001-R). + +## Purpose +Create a PostgreSQL-backed, append-only observability projection for repository governance health. The projection ingests evidence-derived observations and exposes deterministic views suitable for a future dashboard. + +## Authority boundary +Observability projections are descriptive and MUST NOT authorize CLP state transitions, worker eligibility, verification, payout, or policy execution. + +GitHub governance artifacts, signed/hashed receipts, authority records, CI evidence, and independent reviews remain source evidence. SQL views are derived projections only. + +## Required health states +`HEALTHY`, `DEGRADED`, `BLOCKED`, `UNKNOWN`. + +## Required rules +- Unresolved P0/P1 -> BLOCKED. +- Missing required artifact or hash/size mismatch -> BLOCKED. +- Failed canonical CI -> BLOCKED. +- Authority conflict that blocks execution -> BLOCKED. +- Missing required observation -> UNKNOWN (never HEALTHY). +- Non-blocking governance drift -> DEGRADED. +- Authority freshness review due -> DEGRADED unless an explicit fail-closed policy marks it blocking. +- Unresolved P2 -> DEGRADED. +- Stale-head CI -> DEGRADED. +- HEALTHY only when every required gate is present and passing. + +## Stale G0 rule +`governance/clp-001/g0/G0-STATUS.json` is retained as historically valid evidence of an earlier blocked state. It is superseded, not deleted or rewritten, by the later G0 designation chain. The supersession relationship must be machine-readable. diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/G0-STATUS-SUPERSESSION.json b/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/G0-STATUS-SUPERSESSION.json new file mode 100644 index 0000000..f1dcffa --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/G0-STATUS-SUPERSESSION.json @@ -0,0 +1,22 @@ +{ + "receipt_id": "CLP001-G0-STATUS-SUPERSESSION-001", + "repository": "JaeTierce31/EdOpSys", + "historical_assertion": { + "source_path": "governance/clp-001/g0/G0-STATUS.json", + "git_blob_sha1": "1a12cc327460748fdb24b306cac6dced83d05a71", + "status": "BLOCKED_PENDING_SOURCE_BUNDLE_UPLOAD", + "g0_designated": false, + "interpretation": "Historically valid fail-closed status before byte-exact source-bundle materialization completed." + }, + "superseding_assertion": { + "source_path": "governance/clp-001/g1/G0-designation.json", + "git_blob_sha1": "1217f749311ee24c2b31a6d702e75e9d2eb9863f", + "g0_commit_sha": "adab09caa0093c9490a8f1ab215a719bf0fa9aa4", + "designated_at": "2026-10-04T09:03:06.661926Z", + "designation": "G0", + "source_bundle_integrity": "PASS" + }, + "resolution": "SUPERSEDED", + "rule": "Retain the historical status artifact unchanged. Current G0 status resolves from the later higher-authority designation chain; historical replay retains both artifacts.", + "current_baseline_at_receipt_creation": "b0f19f2d0ce8a086604ed1f08d1202cd5650dae8" +} diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/R-INDEPENDENT-REVIEW-RECEIPT.json b/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/R-INDEPENDENT-REVIEW-RECEIPT.json new file mode 100644 index 0000000..139f896 --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/R-INDEPENDENT-REVIEW-RECEIPT.json @@ -0,0 +1,16 @@ +{ + "receipt_id": "BUILD-CLP-001-R-INDEPENDENT-REVIEW-001", + "repository": "JaeTierce31/EdOpSys", + "reviewer": "Mistral Vibe", + "reviewed_sha": "32a2064cf0aa179e2b0f2c8f40e56e705cf37fec", + "base_sha": "5427aff8c10370085546cf98ae83dacd5939bb0a", + "artifact_integrity": "PASS_16_OF_16", + "ci_run_id": 37206695993, + "ci_result": "SUCCESS", + "p0": 0, + "p1": 0, + "p2": 0, + "p3": 3, + "decision": "MERGE_APPROVED", + "source_note": "Structured from the user-supplied Mistral Vibe exact-head independent review transcript; this file is an observability receipt, not a cryptographic reviewer signature." +} diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/repository-observations.sql b/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/repository-observations.sql new file mode 100644 index 0000000..108485b --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/fixtures/repository-observations.sql @@ -0,0 +1,29 @@ +BEGIN; +SET search_path=edopsys_observability,public; + +INSERT INTO obs_observations VALUES +('obs-base-r','JaeTierce31/EdOpSys','REPOSITORY_HEAD','refs/heads/main','b0f19f2d0ce8a086604ed1f08d1202cd5650dae8','2026-10-04T15:19:10Z','sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','{}'), +('obs-build-r','JaeTierce31/EdOpSys','BUILD_RECEIPT','PR#3','32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','2026-10-04T15:19:10Z','sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb','{}'), +('obs-ci-r','JaeTierce31/EdOpSys','CI_RUN','actions/37206695993','32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','2026-10-04T13:45:19Z','sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc','{}'), +('obs-review-r','JaeTierce31/EdOpSys','PR_REVIEW','Mistral-Vibe-review','32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','2026-10-04T14:47:00Z','sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd','{}'), +('obs-int-r','JaeTierce31/EdOpSys','ARTIFACT_INTEGRITY','R-source-manifest','0609035dc2373e8b2224e739761df88b5f2c7030b25b8db7434b5bf8638e680a','2026-10-04T14:47:00Z','sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee','{}'), +('obs-auth-av','JaeTierce31/EdOpSys','AUTHORITY_RECORD','authority-registry-v2','17145394aa274dfca76003ac6e8be07082a997c1','2026-10-04T15:19:10Z','sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff','{}'), +('obs-auth-mn','JaeTierce31/EdOpSys','AUTHORITY_RECORD','authority-registry-v2','17145394aa274dfca76003ac6e8be07082a997c1','2026-10-04T15:19:10Z','sha256:abababababababababababababababababababababababababababababababab','{}'); + +INSERT INTO repository_baseline VALUES('obs-base-r','JaeTierce31/EdOpSys','b0f19f2d0ce8a086604ed1f08d1202cd5650dae8','BUILD-CLP-001-R','adab09caa0093c9490a8f1ab215a719bf0fa9aa4','dddd7d91494a5c3916146387828efd643b957fa2','95a1da390d81d3fefe611c74405505aa28fa686d','5427aff8c10370085546cf98ae83dacd5939bb0a','b0f19f2d0ce8a086604ed1f08d1202cd5650dae8','2026-10-04T15:19:10Z'); +INSERT INTO build_status VALUES('obs-build-r','JaeTierce31/EdOpSys','BUILD-CLP-001-R',true,'32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','b0f19f2d0ce8a086604ed1f08d1202cd5650dae8','5427aff8c10370085546cf98ae83dacd5939bb0a',61,61,'success','APPROVED_EXTERNAL',0,true,'2026-10-04T15:19:10Z'); +INSERT INTO ci_runs VALUES('obs-ci-r','JaeTierce31/EdOpSys','BUILD-CLP-001-R',37206695993,'32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','completed','success','success','2026-10-04T13:45:19Z'); +INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) +VALUES('obs-review-r','JaeTierce31/EdOpSys',3,'32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','32a2064cf0aa179e2b0f2c8f40e56e705cf37fec','Mistral Vibe',NULL,'APPROVED',true,false,false,'2026-10-04T14:47:00Z','__summary__'); +INSERT INTO artifact_integrity VALUES('obs-int-r','JaeTierce31/EdOpSys','governance/clp-001/builds/BUILD-CLP-001-R/receipts/R-source-manifest.json',true,'PASS','0609035dc2373e8b2224e739761df88b5f2c7030b25b8db7434b5bf8638e680a','0609035dc2373e8b2224e739761df88b5f2c7030b25b8db7434b5bf8638e680a',2413,2413,'2026-10-04T14:47:00Z'); +INSERT INTO artifact_integrity_scope VALUES('obs-int-r','JaeTierce31/EdOpSys','BUILD-CLP-001-R','2026-10-04T14:47:00Z'); +INSERT INTO authority_records VALUES +('obs-auth-av','JaeTierce31/EdOpSys','AUTH-APPLEVALLEY-155360','2025-S21','SC-0','US-MN-DAKOTA-APPLE-VALLEY','sha256:00b53bf9346e8e89debff50503783b2bcbe311715c6cb1a560c3076a2b971004','FRESHNESS_REVIEW_DUE',false,'2026-10-04T15:19:10Z'), +('obs-auth-mn','JaeTierce31/EdOpSys','AUTH-MN-PLUMBING-4714','2020-MN-PLUMBING-CODE','SC-0','US-MN','sha256:1a49eaa526cffbc39613fc0b64fd70daeb8e41a025baed00f708fc5b013b0bc2','CURRENT',false,'2026-10-04T15:19:10Z'); + +INSERT INTO governance_status_assertions VALUES +('G0-BLOCKED-HIST','JaeTierce31/EdOpSys','G0','designation_status','"BLOCKED_PENDING_SOURCE_BUNDLE_UPLOAD"','governance/clp-001/g0/G0-STATUS.json',NULL,'2026-10-04T08:50:00Z','2026-10-04T09:03:06Z','G0-DESIGNATED-CURRENT',1,'SUPERSEDED'), +('G0-DESIGNATED-CURRENT','JaeTierce31/EdOpSys','G0','designation_status','"DESIGNATED"','governance/clp-001/g1/G0-designation.json','adab09caa0093c9490a8f1ab215a719bf0fa9aa4','2026-10-04T09:03:06Z',NULL,NULL,2,'CURRENT'); +INSERT INTO governance_supersession_receipts VALUES('G0-SUPERSESSION-001','JaeTierce31/EdOpSys','G0-BLOCKED-HIST','G0-DESIGNATED-CURRENT','Earlier fail-closed G0 status was historically valid; later byte-exact G0 designation supersedes its current operational interpretation.','sha256:1111111111111111111111111111111111111111111111111111111111111111','2026-10-04T09:03:06Z'); +INSERT INTO governance_drift_findings VALUES('DRIFT-G0-001','JaeTierce31/EdOpSys','STALE_STATUS_ASSERTION','G0','P2','SUPERSEDED','G0-SUPERSESSION-001','2026-10-04T15:19:10Z'); +COMMIT; diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/migrations/003_clp001_s_governance_health.sql b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/003_clp001_s_governance_health.sql new file mode 100644 index 0000000..3212d3a --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/003_clp001_s_governance_health.sql @@ -0,0 +1,86 @@ +BEGIN; +CREATE SCHEMA IF NOT EXISTS edopsys_observability; +COMMENT ON SCHEMA edopsys_observability IS 'Observability projections are descriptive and MUST NOT authorize CLP state transitions, worker eligibility, verification, payout, or policy execution.'; + +CREATE TABLE edopsys_observability.obs_observations( + observation_id text PRIMARY KEY, repository text NOT NULL, observation_type text NOT NULL, + source_ref text NOT NULL, source_sha text, observed_at timestamptz NOT NULL, + payload_hash text NOT NULL, payload jsonb NOT NULL); +CREATE TABLE edopsys_observability.repository_baseline( + id text PRIMARY KEY REFERENCES edopsys_observability.obs_observations(observation_id), repository text NOT NULL, + canonical_head text NOT NULL, latest_merged_build text NOT NULL, g0_sha text, g1_sha text, + p_merge_sha text,q_merge_sha text,r_merge_sha text,observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.build_status( + id text PRIMARY KEY REFERENCES edopsys_observability.obs_observations(observation_id),repository text NOT NULL, + build_id text NOT NULL,authorized boolean NOT NULL,implementation_sha text,merge_sha text,parent_sha text, + tests_passed int,tests_total int,ci_conclusion text,review_state text,blocking_findings int NOT NULL DEFAULT 0, + canonical boolean NOT NULL DEFAULT false,observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.authority_records( + id text PRIMARY KEY REFERENCES edopsys_observability.obs_observations(observation_id),repository text NOT NULL, + authority_id text NOT NULL,version text NOT NULL,source_class text,jurisdiction text,content_hash text, + freshness_status text NOT NULL CHECK(freshness_status IN('CURRENT','FRESHNESS_REVIEW_DUE','SUPERSEDED','HISTORICAL_ONLY','CONFLICT','UNKNOWN')), + execution_blocking boolean NOT NULL DEFAULT false,observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.artifact_integrity( + id text PRIMARY KEY REFERENCES edopsys_observability.obs_observations(observation_id),repository text NOT NULL, + artifact_path text NOT NULL,required boolean NOT NULL DEFAULT true,status text NOT NULL CHECK(status IN('PASS','MISSING','HASH_MISMATCH','SIZE_MISMATCH','UNVERIFIED')), + expected_sha256 text,observed_sha256 text,expected_bytes bigint,observed_bytes bigint,observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.ci_runs( + id text PRIMARY KEY REFERENCES edopsys_observability.obs_observations(observation_id),repository text NOT NULL, + build_id text NOT NULL,run_id bigint NOT NULL,head_sha text NOT NULL,expected_head_sha text NOT NULL, + status text NOT NULL,conclusion text,substantive_result text,observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.pr_reviews( + id text PRIMARY KEY REFERENCES edopsys_observability.obs_observations(observation_id),repository text NOT NULL, + pr_number int NOT NULL,reviewed_sha text NOT NULL,expected_head_sha text NOT NULL,reviewer text NOT NULL, + severity text CHECK(severity IS NULL OR severity IN('P0','P1','P2','P3')),finding_status text NOT NULL, + resolved boolean NOT NULL DEFAULT false,superseded boolean NOT NULL DEFAULT false,merge_blocking boolean NOT NULL DEFAULT false, + observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.governance_status_assertions( + assertion_id text PRIMARY KEY,repository text NOT NULL,subject text NOT NULL,predicate text NOT NULL,value jsonb NOT NULL, + source_path text NOT NULL,source_commit text,observed_at timestamptz NOT NULL,valid_to timestamptz, + superseded_by text REFERENCES edopsys_observability.governance_status_assertions(assertion_id),authority_rank int NOT NULL, + status text NOT NULL CHECK(status IN('CURRENT','HISTORICAL','SUPERSEDED','CONFLICT','UNKNOWN'))); +CREATE TABLE edopsys_observability.governance_supersession_receipts( + receipt_id text PRIMARY KEY,repository text NOT NULL,superseded_assertion_id text NOT NULL REFERENCES edopsys_observability.governance_status_assertions(assertion_id), + superseding_assertion_id text NOT NULL REFERENCES edopsys_observability.governance_status_assertions(assertion_id),rationale text NOT NULL,receipt_hash text NOT NULL,observed_at timestamptz NOT NULL); +CREATE TABLE edopsys_observability.governance_drift_findings( + finding_id text PRIMARY KEY,repository text NOT NULL,finding_type text NOT NULL,subject text NOT NULL,severity text NOT NULL CHECK(severity IN('P0','P1','P2','P3')), + resolution_status text NOT NULL CHECK(resolution_status IN('OPEN','RESOLVED','SUPERSEDED','ACCEPTED_RISK')),resolution_receipt text REFERENCES edopsys_observability.governance_supersession_receipts(receipt_id),detected_at timestamptz NOT NULL); + +DO $$DECLARE t text;BEGIN FOREACH t IN ARRAY ARRAY['obs_observations','repository_baseline','build_status','authority_records','artifact_integrity','ci_runs','pr_reviews','governance_status_assertions','governance_supersession_receipts','governance_drift_findings'] LOOP EXECUTE format('CREATE TRIGGER %I_append_only BEFORE UPDATE OR DELETE ON edopsys_observability.%I FOR EACH ROW EXECUTE FUNCTION public.clp_reject_mutation()',t,t); END LOOP;END$$; + +CREATE VIEW edopsys_observability.v_build_health AS +SELECT DISTINCT ON(repository,build_id) *,CASE WHEN blocking_findings>0 OR NOT authorized OR ci_conclusion NOT IN('success') THEN 'BLOCKED' WHEN ci_conclusion IS NULL OR review_state IS NULL THEN 'UNKNOWN' WHEN review_state NOT IN('APPROVED','APPROVED_EXTERNAL','CLEAN') THEN 'DEGRADED' ELSE 'HEALTHY' END health +FROM edopsys_observability.build_status ORDER BY repository,build_id,observed_at DESC,id DESC; +CREATE VIEW edopsys_observability.v_integrity_health AS +SELECT r.repository,CASE WHEN count(a.*) FILTER(WHERE a.required AND a.status IN('MISSING','HASH_MISMATCH','SIZE_MISMATCH'))>0 THEN 'BLOCKED' WHEN count(a.*) FILTER(WHERE a.required)=0 OR count(a.*) FILTER(WHERE a.required AND a.status='UNVERIFIED')>0 THEN 'UNKNOWN' ELSE 'HEALTHY' END health +FROM (SELECT DISTINCT repository FROM edopsys_observability.repository_baseline) r LEFT JOIN edopsys_observability.artifact_integrity a USING(repository) GROUP BY r.repository; +CREATE VIEW edopsys_observability.v_ci_health AS +SELECT DISTINCT ON(repository,build_id) *,CASE WHEN status<>'completed' THEN 'IN_PROGRESS' WHEN head_sha<>expected_head_sha THEN 'STALE_HEAD' WHEN conclusion='success' AND substantive_result='success' THEN 'PASS' ELSE 'FAIL' END ci_health +FROM edopsys_observability.ci_runs ORDER BY repository,build_id,observed_at DESC,id DESC; +CREATE VIEW edopsys_observability.v_review_health AS +SELECT r.repository,count(p.*) FILTER(WHERE severity='P0' AND NOT resolved AND NOT superseded) p0,count(p.*) FILTER(WHERE severity='P1' AND NOT resolved AND NOT superseded) p1,count(p.*) FILTER(WHERE severity='P2' AND NOT resolved AND NOT superseded) p2, +CASE WHEN count(p.*)=0 THEN 'UNKNOWN' WHEN count(p.*) FILTER(WHERE severity IN('P0','P1') AND NOT resolved AND NOT superseded)>0 THEN 'BLOCKED' WHEN count(p.*) FILTER(WHERE severity='P2' AND NOT resolved AND NOT superseded)>0 THEN 'DEGRADED' WHEN count(p.*) FILTER(WHERE reviewed_sha=expected_head_sha AND finding_status IN('APPROVED','CLEAN'))>0 THEN 'HEALTHY' ELSE 'UNKNOWN' END health +FROM (SELECT DISTINCT repository FROM edopsys_observability.repository_baseline) r LEFT JOIN edopsys_observability.pr_reviews p USING(repository) GROUP BY r.repository; +CREATE VIEW edopsys_observability.v_authority_health AS +SELECT r.repository,CASE WHEN count(a.*)=0 OR count(a.*) FILTER(WHERE freshness_status='UNKNOWN')>0 THEN 'UNKNOWN' WHEN count(a.*) FILTER(WHERE freshness_status='CONFLICT' AND execution_blocking)>0 THEN 'BLOCKED' WHEN count(a.*) FILTER(WHERE freshness_status='FRESHNESS_REVIEW_DUE')>0 THEN 'DEGRADED' ELSE 'HEALTHY' END health +FROM (SELECT DISTINCT repository FROM edopsys_observability.repository_baseline) r LEFT JOIN edopsys_observability.authority_records a USING(repository) GROUP BY r.repository; +CREATE VIEW edopsys_observability.v_governance_drift AS +SELECT r.repository,count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P0','P1')) blocking_open_count,count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P2','P3')) nonblocking_open_count, +CASE WHEN count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P0','P1'))>0 THEN 'BLOCKED' WHEN count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P2','P3'))>0 THEN 'DEGRADED' ELSE 'HEALTHY' END health +FROM (SELECT DISTINCT repository FROM edopsys_observability.repository_baseline) r LEFT JOIN edopsys_observability.governance_drift_findings d USING(repository) GROUP BY r.repository; +CREATE VIEW edopsys_observability.v_governance_assertion_current AS +SELECT DISTINCT ON(repository,subject,predicate) * FROM edopsys_observability.governance_status_assertions WHERE valid_to IS NULL AND status IN('CURRENT','CONFLICT','UNKNOWN') ORDER BY repository,subject,predicate,authority_rank DESC,observed_at DESC,assertion_id DESC; +CREATE VIEW edopsys_observability.v_governance_timeline AS +SELECT repository,observed_at occurred_at,'ASSERTION' event_kind,assertion_id event_id,jsonb_build_object('subject',subject,'predicate',predicate,'status',status) details FROM edopsys_observability.governance_status_assertions +UNION ALL SELECT repository,observed_at,'SUPERSESSION',receipt_id,jsonb_build_object('superseded',superseded_assertion_id,'superseding',superseding_assertion_id) FROM edopsys_observability.governance_supersession_receipts +UNION ALL SELECT repository,detected_at,'DRIFT',finding_id,jsonb_build_object('type',finding_type,'severity',severity,'resolution',resolution_status) FROM edopsys_observability.governance_drift_findings; +CREATE VIEW edopsys_observability.v_repository_health AS +WITH b AS(SELECT DISTINCT ON(repository)* FROM edopsys_observability.repository_baseline ORDER BY repository,observed_at DESC,id DESC),bu AS(SELECT DISTINCT ON(repository) repository,health FROM edopsys_observability.v_build_health WHERE canonical ORDER BY repository,observed_at DESC),ci AS(SELECT DISTINCT ON(repository) repository,ci_health FROM edopsys_observability.v_ci_health ORDER BY repository,observed_at DESC),i AS(SELECT * FROM edopsys_observability.v_integrity_health),rv AS(SELECT * FROM edopsys_observability.v_review_health),a AS(SELECT * FROM edopsys_observability.v_authority_health),d AS(SELECT * FROM edopsys_observability.v_governance_drift) +SELECT b.repository,b.canonical_head,b.latest_merged_build,COALESCE(bu.health,'UNKNOWN') build_status,COALESCE(ci.ci_health,'NO_RUN') ci_status,COALESCE(i.health,'UNKNOWN') integrity_status,COALESCE(rv.health,'UNKNOWN') review_status,COALESCE(a.health,'UNKNOWN') authority_status,COALESCE(d.health,'HEALTHY') drift_status, +(COALESCE(rv.p0,0)+COALESCE(rv.p1,0)+CASE WHEN COALESCE(i.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END+CASE WHEN COALESCE(ci.ci_health,'NO_RUN')='FAIL' THEN 1 ELSE 0 END+CASE WHEN COALESCE(a.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END+CASE WHEN COALESCE(d.health,'HEALTHY')='BLOCKED' THEN 1 ELSE 0 END) blocking_reason_count, +CASE WHEN COALESCE(bu.health,'UNKNOWN')='BLOCKED' OR COALESCE(i.health,'UNKNOWN')='BLOCKED' OR COALESCE(rv.health,'UNKNOWN')='BLOCKED' OR COALESCE(a.health,'UNKNOWN')='BLOCKED' OR COALESCE(d.health,'HEALTHY')='BLOCKED' OR COALESCE(ci.ci_health,'NO_RUN')='FAIL' THEN 'BLOCKED' +WHEN COALESCE(bu.health,'UNKNOWN')='UNKNOWN' OR COALESCE(i.health,'UNKNOWN')='UNKNOWN' OR COALESCE(rv.health,'UNKNOWN')='UNKNOWN' OR COALESCE(a.health,'UNKNOWN')='UNKNOWN' OR COALESCE(ci.ci_health,'NO_RUN') IN('NO_RUN','IN_PROGRESS') THEN 'UNKNOWN' +WHEN COALESCE(bu.health,'UNKNOWN')='DEGRADED' OR COALESCE(rv.health,'UNKNOWN')='DEGRADED' OR COALESCE(a.health,'UNKNOWN')='DEGRADED' OR COALESCE(d.health,'HEALTHY')='DEGRADED' OR COALESCE(ci.ci_health,'NO_RUN')='STALE_HEAD' THEN 'DEGRADED' ELSE 'HEALTHY' END overall_health +FROM b LEFT JOIN bu USING(repository) LEFT JOIN ci USING(repository) LEFT JOIN i USING(repository) LEFT JOIN rv USING(repository) LEFT JOIN a USING(repository) LEFT JOIN d USING(repository); +CREATE VIEW edopsys_observability.v_dashboard_summary_json AS SELECT repository,jsonb_build_object('overall_health',overall_health,'canonical_head',canonical_head,'latest_build',latest_merged_build,'blocking_reason_count',blocking_reason_count,'gates',jsonb_build_object('build',build_status,'ci',ci_status,'integrity',integrity_status,'review',review_status,'authority',authority_status,'drift',drift_status),'timeline',COALESCE((SELECT jsonb_agg(jsonb_build_object('at',occurred_at,'kind',event_kind,'id',event_id,'details',details) ORDER BY occurred_at) FROM edopsys_observability.v_governance_timeline t WHERE t.repository=r.repository),'[]'::jsonb)) dashboard FROM edopsys_observability.v_repository_health r; +COMMIT; diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/migrations/004_clp001_s_review_hardening.sql b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/004_clp001_s_review_hardening.sql new file mode 100644 index 0000000..cd78f5d --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/004_clp001_s_review_hardening.sql @@ -0,0 +1,103 @@ +BEGIN; +SET search_path=edopsys_observability,public; + +-- Stable logical key permits append-only review finding state transitions. +ALTER TABLE pr_reviews ADD COLUMN finding_key text NOT NULL DEFAULT '__summary__'; + +-- Projection-only migration: drop affected derived views in dependency order. +DROP VIEW v_dashboard_summary_json; +DROP VIEW v_repository_health; +DROP VIEW v_review_health; +DROP VIEW v_authority_health; +DROP VIEW v_governance_drift; + +CREATE VIEW v_review_health AS +WITH repos AS ( + SELECT DISTINCT repository FROM repository_baseline +), latest AS ( + SELECT DISTINCT ON(repository,pr_number,finding_key) * + FROM pr_reviews + ORDER BY repository,pr_number,finding_key,observed_at DESC,id DESC +), agg AS ( + SELECT r.repository, + count(l.*) FILTER(WHERE l.severity='P0' AND NOT l.resolved AND NOT l.superseded) p0, + count(l.*) FILTER(WHERE l.severity='P1' AND NOT l.resolved AND NOT l.superseded) p1, + count(l.*) FILTER(WHERE l.severity='P2' AND NOT l.resolved AND NOT l.superseded) p2, + count(l.*) review_count, + count(l.*) FILTER(WHERE l.reviewed_sha=l.expected_head_sha AND l.finding_status IN('APPROVED','CLEAN')) exact_head_clean_count + FROM repos r LEFT JOIN latest l USING(repository) GROUP BY r.repository +) +SELECT *,CASE + WHEN review_count=0 THEN 'UNKNOWN' + WHEN p0>0 OR p1>0 THEN 'BLOCKED' + WHEN p2>0 THEN 'DEGRADED' + WHEN exact_head_clean_count>0 THEN 'HEALTHY' + ELSE 'UNKNOWN' END health +FROM agg; + +CREATE VIEW v_authority_health AS +SELECT r.repository,CASE + WHEN count(a.*) FILTER(WHERE freshness_status='CONFLICT' AND execution_blocking)>0 THEN 'BLOCKED' + WHEN count(a.*)=0 OR count(a.*) FILTER(WHERE freshness_status='UNKNOWN')>0 THEN 'UNKNOWN' + WHEN count(a.*) FILTER(WHERE freshness_status='FRESHNESS_REVIEW_DUE')>0 THEN 'DEGRADED' + ELSE 'HEALTHY' END health +FROM (SELECT DISTINCT repository FROM repository_baseline) r +LEFT JOIN authority_records a USING(repository) GROUP BY r.repository; + +CREATE VIEW v_governance_drift AS +SELECT r.repository, + count(d.*) drift_observation_count, + count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P0','P1')) blocking_open_count, + count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P2','P3')) nonblocking_open_count, + CASE + WHEN count(d.*)=0 THEN 'UNKNOWN' + WHEN count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P0','P1'))>0 THEN 'BLOCKED' + WHEN count(d.*) FILTER(WHERE resolution_status='OPEN' AND severity IN('P2','P3'))>0 THEN 'DEGRADED' + ELSE 'HEALTHY' END health +FROM (SELECT DISTINCT repository FROM repository_baseline) r +LEFT JOIN governance_drift_findings d USING(repository) GROUP BY r.repository; + +CREATE VIEW v_repository_health AS +WITH b AS ( + SELECT DISTINCT ON(repository)* FROM repository_baseline ORDER BY repository,observed_at DESC,id DESC +), bu AS ( + SELECT DISTINCT ON(repository) repository,build_id,health FROM v_build_health WHERE canonical ORDER BY repository,observed_at DESC +), i AS (SELECT * FROM v_integrity_health), +rv AS (SELECT * FROM v_review_health),a AS (SELECT * FROM v_authority_health),d AS (SELECT * FROM v_governance_drift) +SELECT b.repository,b.canonical_head,b.latest_merged_build, + CASE WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 'BLOCKED' + WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CURRENT') THEN 'CURRENT' + ELSE 'UNKNOWN' END governance_status, + COALESCE(bu.health,'UNKNOWN') build_status, + COALESCE(ci.ci_health,'NO_RUN') ci_status, + COALESCE(i.health,'UNKNOWN') integrity_status, + COALESCE(rv.health,'UNKNOWN') review_status, + COALESCE(a.health,'UNKNOWN') authority_status, + COALESCE(d.health,'UNKNOWN') drift_status, + (COALESCE(rv.p0,0)+COALESCE(rv.p1,0) + +CASE WHEN COALESCE(bu.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(i.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(ci.ci_health,'NO_RUN')='FAIL' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(a.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(d.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 1 ELSE 0 END) blocking_reason_count, + CASE + WHEN COALESCE(bu.health,'UNKNOWN')='BLOCKED' OR COALESCE(i.health,'UNKNOWN')='BLOCKED' OR COALESCE(rv.health,'UNKNOWN')='BLOCKED' OR COALESCE(a.health,'UNKNOWN')='BLOCKED' OR COALESCE(d.health,'UNKNOWN')='BLOCKED' OR COALESCE(ci.ci_health,'NO_RUN')='FAIL' OR EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 'BLOCKED' + WHEN COALESCE(bu.health,'UNKNOWN')='UNKNOWN' OR COALESCE(i.health,'UNKNOWN')='UNKNOWN' OR COALESCE(rv.health,'UNKNOWN')='UNKNOWN' OR COALESCE(a.health,'UNKNOWN')='UNKNOWN' OR COALESCE(d.health,'UNKNOWN')='UNKNOWN' OR COALESCE(ci.ci_health,'NO_RUN') IN('NO_RUN','IN_PROGRESS') OR NOT EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CURRENT') THEN 'UNKNOWN' + WHEN COALESCE(bu.health,'UNKNOWN')='DEGRADED' OR COALESCE(rv.health,'UNKNOWN')='DEGRADED' OR COALESCE(a.health,'UNKNOWN')='DEGRADED' OR COALESCE(d.health,'UNKNOWN')='DEGRADED' OR COALESCE(ci.ci_health,'NO_RUN')='STALE_HEAD' THEN 'DEGRADED' + ELSE 'HEALTHY' END overall_health +FROM b +LEFT JOIN bu ON bu.repository=b.repository +LEFT JOIN v_ci_health ci ON ci.repository=b.repository AND ci.build_id=b.latest_merged_build +LEFT JOIN i ON i.repository=b.repository +LEFT JOIN rv ON rv.repository=b.repository +LEFT JOIN a ON a.repository=b.repository +LEFT JOIN d ON d.repository=b.repository; + +CREATE VIEW v_dashboard_summary_json AS +SELECT repository,jsonb_build_object( + 'overall_health',overall_health,'canonical_head',canonical_head,'latest_build',latest_merged_build,'blocking_reason_count',blocking_reason_count, + 'gates',jsonb_build_object('governance',governance_status,'build',build_status,'ci',ci_status,'integrity',integrity_status,'review',review_status,'authority',authority_status,'drift',drift_status), + 'timeline',COALESCE((SELECT jsonb_agg(jsonb_build_object('at',occurred_at,'kind',event_kind,'id',event_id,'details',details) ORDER BY occurred_at) FROM v_governance_timeline t WHERE t.repository=r.repository),'[]'::jsonb) +) dashboard FROM v_repository_health r; +COMMIT; diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/migrations/005_clp001_s_canonical_binding.sql b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/005_clp001_s_canonical_binding.sql new file mode 100644 index 0000000..ff9fd07 --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/005_clp001_s_canonical_binding.sql @@ -0,0 +1,153 @@ +BEGIN; +SET search_path=edopsys_observability,public; + +-- Bind integrity evidence to a specific build without mutating historical rows. +CREATE TABLE artifact_integrity_scope( + id text PRIMARY KEY REFERENCES artifact_integrity(id), + repository text NOT NULL, + build_id text NOT NULL, + observed_at timestamptz NOT NULL +); +CREATE TRIGGER artifact_integrity_scope_append_only +BEFORE UPDATE OR DELETE ON artifact_integrity_scope +FOR EACH ROW EXECUTE FUNCTION public.clp_reject_mutation(); + +-- Projection-only hardening: every health gate is bound to the active baseline. +DROP VIEW v_dashboard_summary_json; +DROP VIEW v_repository_health; +DROP VIEW v_integrity_health; +DROP VIEW v_review_health; +DROP VIEW v_authority_health; + +CREATE VIEW v_integrity_health AS +WITH b AS ( + SELECT DISTINCT ON(repository) * + FROM repository_baseline + ORDER BY repository,observed_at DESC,id DESC +), current_integrity AS ( + SELECT a.*,s.build_id + FROM artifact_integrity a + JOIN artifact_integrity_scope s ON s.id=a.id AND s.repository=a.repository +), agg AS ( + SELECT b.repository, + count(a.*) FILTER(WHERE a.required) required_count, + count(a.*) FILTER(WHERE a.required AND a.status IN('MISSING','HASH_MISMATCH','SIZE_MISMATCH')) blocked_count, + count(a.*) FILTER(WHERE a.required AND a.status='UNVERIFIED') unverified_count + FROM b + LEFT JOIN current_integrity a + ON a.repository=b.repository AND a.build_id=b.latest_merged_build + GROUP BY b.repository +) +SELECT repository,CASE + WHEN blocked_count>0 THEN 'BLOCKED' + WHEN required_count=0 OR unverified_count>0 THEN 'UNKNOWN' + ELSE 'HEALTHY' END health +FROM agg; + +CREATE VIEW v_review_health AS +WITH b AS ( + SELECT DISTINCT ON(repository) * + FROM repository_baseline + ORDER BY repository,observed_at DESC,id DESC +), cb AS ( + SELECT b.repository,b.latest_merged_build,v.implementation_sha + FROM b + LEFT JOIN v_build_health v + ON v.repository=b.repository AND v.build_id=b.latest_merged_build +), latest AS ( + SELECT DISTINCT ON(p.repository,p.pr_number,p.finding_key) p.* + FROM pr_reviews p + JOIN cb ON cb.repository=p.repository AND cb.implementation_sha=p.reviewed_sha + ORDER BY p.repository,p.pr_number,p.finding_key,p.observed_at DESC,p.id DESC +), agg AS ( + SELECT b.repository, + count(l.*) FILTER(WHERE l.severity='P0' AND NOT l.resolved AND NOT l.superseded) p0, + count(l.*) FILTER(WHERE l.severity='P1' AND NOT l.resolved AND NOT l.superseded) p1, + count(l.*) FILTER(WHERE l.severity='P2' AND NOT l.resolved AND NOT l.superseded) p2, + count(l.*) review_count, + count(l.*) FILTER(WHERE l.reviewed_sha=cb.implementation_sha AND l.expected_head_sha=cb.implementation_sha AND l.finding_status IN('APPROVED','CLEAN')) exact_head_clean_count + FROM b + LEFT JOIN cb ON cb.repository=b.repository + LEFT JOIN latest l ON l.repository=b.repository + GROUP BY b.repository +) +SELECT *,CASE + WHEN review_count=0 THEN 'UNKNOWN' + WHEN p0>0 OR p1>0 THEN 'BLOCKED' + WHEN p2>0 THEN 'DEGRADED' + WHEN exact_head_clean_count>0 THEN 'HEALTHY' + ELSE 'UNKNOWN' END health +FROM agg; + +CREATE VIEW v_authority_health AS +WITH repos AS ( + SELECT DISTINCT repository FROM repository_baseline +), latest AS ( + SELECT DISTINCT ON(repository,authority_id) * + FROM authority_records + ORDER BY repository,authority_id,observed_at DESC,id DESC +), agg AS ( + SELECT r.repository, + count(a.*) FILTER(WHERE a.freshness_status NOT IN('SUPERSEDED','HISTORICAL_ONLY')) active_count, + count(a.*) FILTER(WHERE a.freshness_status='CONFLICT' AND a.execution_blocking) blocking_conflict_count, + count(a.*) FILTER(WHERE a.freshness_status='UNKNOWN') unknown_count, + count(a.*) FILTER(WHERE a.freshness_status='FRESHNESS_REVIEW_DUE') freshness_due_count, + count(a.*) FILTER(WHERE a.freshness_status='CONFLICT' AND NOT a.execution_blocking) nonblocking_conflict_count + FROM repos r + LEFT JOIN latest a ON a.repository=r.repository + GROUP BY r.repository +) +SELECT repository,CASE + WHEN blocking_conflict_count>0 THEN 'BLOCKED' + WHEN active_count=0 OR unknown_count>0 THEN 'UNKNOWN' + WHEN freshness_due_count>0 OR nonblocking_conflict_count>0 THEN 'DEGRADED' + ELSE 'HEALTHY' END health +FROM agg; + +CREATE VIEW v_repository_health AS +WITH b AS ( + SELECT DISTINCT ON(repository) * + FROM repository_baseline + ORDER BY repository,observed_at DESC,id DESC +), bu AS ( + SELECT repository,build_id,health + FROM v_build_health +), i AS (SELECT * FROM v_integrity_health), +rv AS (SELECT * FROM v_review_health),a AS (SELECT * FROM v_authority_health),d AS (SELECT * FROM v_governance_drift) +SELECT b.repository,b.canonical_head,b.latest_merged_build, + CASE WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 'BLOCKED' + WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CURRENT') THEN 'CURRENT' + ELSE 'UNKNOWN' END governance_status, + COALESCE(bu.health,'UNKNOWN') build_status, + COALESCE(ci.ci_health,'NO_RUN') ci_status, + COALESCE(i.health,'UNKNOWN') integrity_status, + COALESCE(rv.health,'UNKNOWN') review_status, + COALESCE(a.health,'UNKNOWN') authority_status, + COALESCE(d.health,'UNKNOWN') drift_status, + (COALESCE(rv.p0,0)+COALESCE(rv.p1,0) + +CASE WHEN COALESCE(bu.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(i.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(ci.ci_health,'NO_RUN')='FAIL' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(a.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(d.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 1 ELSE 0 END) blocking_reason_count, + CASE + WHEN COALESCE(bu.health,'UNKNOWN')='BLOCKED' OR COALESCE(i.health,'UNKNOWN')='BLOCKED' OR COALESCE(rv.health,'UNKNOWN')='BLOCKED' OR COALESCE(a.health,'UNKNOWN')='BLOCKED' OR COALESCE(d.health,'UNKNOWN')='BLOCKED' OR COALESCE(ci.ci_health,'NO_RUN')='FAIL' OR EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 'BLOCKED' + WHEN COALESCE(bu.health,'UNKNOWN')='UNKNOWN' OR COALESCE(i.health,'UNKNOWN')='UNKNOWN' OR COALESCE(rv.health,'UNKNOWN')='UNKNOWN' OR COALESCE(a.health,'UNKNOWN')='UNKNOWN' OR COALESCE(d.health,'UNKNOWN')='UNKNOWN' OR COALESCE(ci.ci_health,'NO_RUN') IN('NO_RUN','IN_PROGRESS') OR NOT EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=b.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CURRENT') THEN 'UNKNOWN' + WHEN COALESCE(bu.health,'UNKNOWN')='DEGRADED' OR COALESCE(rv.health,'UNKNOWN')='DEGRADED' OR COALESCE(a.health,'UNKNOWN')='DEGRADED' OR COALESCE(d.health,'UNKNOWN')='DEGRADED' OR COALESCE(ci.ci_health,'NO_RUN')='STALE_HEAD' THEN 'DEGRADED' + ELSE 'HEALTHY' END overall_health +FROM b +LEFT JOIN bu ON bu.repository=b.repository AND bu.build_id=b.latest_merged_build +LEFT JOIN v_ci_health ci ON ci.repository=b.repository AND ci.build_id=b.latest_merged_build +LEFT JOIN i ON i.repository=b.repository +LEFT JOIN rv ON rv.repository=b.repository +LEFT JOIN a ON a.repository=b.repository +LEFT JOIN d ON d.repository=b.repository; + +CREATE VIEW v_dashboard_summary_json AS +SELECT repository,jsonb_build_object( + 'overall_health',overall_health,'canonical_head',canonical_head,'latest_build',latest_merged_build,'blocking_reason_count',blocking_reason_count, + 'gates',jsonb_build_object('governance',governance_status,'build',build_status,'ci',ci_status,'integrity',integrity_status,'review',review_status,'authority',authority_status,'drift',drift_status), + 'timeline',COALESCE((SELECT jsonb_agg(jsonb_build_object('at',occurred_at,'kind',event_kind,'id',event_id,'details',details) ORDER BY occurred_at) FROM v_governance_timeline t WHERE t.repository=r.repository),'[]'::jsonb) +) dashboard FROM v_repository_health r; +COMMIT; diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/migrations/006_clp001_s_exact_evidence_binding.sql b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/006_clp001_s_exact_evidence_binding.sql new file mode 100644 index 0000000..3dc960a --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/migrations/006_clp001_s_exact_evidence_binding.sql @@ -0,0 +1,118 @@ +BEGIN; +SET search_path=edopsys_observability,public; + +-- v1.0.2 hardening: derive integrity from recorded measurements and bind CI +-- to both the active baseline build and the active implementation SHA. +DROP VIEW v_dashboard_summary_json; +DROP VIEW v_repository_health; +DROP VIEW v_integrity_health; + +CREATE VIEW v_integrity_health AS +WITH b AS ( + SELECT DISTINCT ON(repository) * + FROM repository_baseline + ORDER BY repository,observed_at DESC,id DESC +), current_integrity AS ( + SELECT a.*,s.build_id + FROM artifact_integrity a + JOIN artifact_integrity_scope s ON s.id=a.id AND s.repository=a.repository +), agg AS ( + SELECT b.repository, + count(a.*) FILTER(WHERE a.required) required_count, + count(a.*) FILTER( + WHERE a.required AND ( + a.status IN('MISSING','HASH_MISMATCH','SIZE_MISMATCH') + OR a.observed_sha256 IS NULL + OR a.observed_bytes IS NULL + OR a.expected_sha256 IS NULL + OR a.expected_bytes IS NULL + OR a.expected_sha256 IS DISTINCT FROM a.observed_sha256 + OR a.expected_bytes IS DISTINCT FROM a.observed_bytes + ) + ) blocked_count, + count(a.*) FILTER(WHERE a.required AND a.status='UNVERIFIED') unverified_count + FROM b + LEFT JOIN current_integrity a + ON a.repository=b.repository AND a.build_id=b.latest_merged_build + GROUP BY b.repository +) +SELECT repository,CASE + WHEN blocked_count>0 THEN 'BLOCKED' + WHEN required_count=0 OR unverified_count>0 THEN 'UNKNOWN' + ELSE 'HEALTHY' END health +FROM agg; + +CREATE VIEW v_repository_health AS +WITH b AS ( + SELECT DISTINCT ON(repository) * + FROM repository_baseline + ORDER BY repository,observed_at DESC,id DESC +), bu AS ( + SELECT repository,build_id,implementation_sha,health + FROM v_build_health +), active AS ( + SELECT b.*,bu.implementation_sha,bu.health build_health + FROM b + LEFT JOIN bu ON bu.repository=b.repository AND bu.build_id=b.latest_merged_build +), ci_latest AS ( + SELECT DISTINCT ON(c.repository,c.build_id,c.head_sha) c.* + FROM ci_runs c + JOIN active x + ON x.repository=c.repository + AND x.latest_merged_build=c.build_id + AND x.implementation_sha=c.head_sha + ORDER BY c.repository,c.build_id,c.head_sha,c.observed_at DESC,c.id DESC +), ci AS ( + SELECT x.repository,x.latest_merged_build build_id, + CASE + WHEN x.implementation_sha IS NULL THEN 'NO_RUN' + WHEN c.id IS NULL THEN 'NO_RUN' + WHEN c.status IN('queued','in_progress') THEN 'IN_PROGRESS' + WHEN c.conclusion='success' AND c.head_sha=x.implementation_sha THEN 'PASS' + WHEN c.conclusion IN('failure','cancelled','timed_out','action_required','startup_failure') THEN 'FAIL' + ELSE 'NO_RUN' + END ci_health + FROM active x + LEFT JOIN ci_latest c + ON c.repository=x.repository + AND c.build_id=x.latest_merged_build + AND c.head_sha=x.implementation_sha +), i AS (SELECT * FROM v_integrity_health), +rv AS (SELECT * FROM v_review_health),a AS (SELECT * FROM v_authority_health),d AS (SELECT * FROM v_governance_drift) +SELECT x.repository,x.canonical_head,x.latest_merged_build, + CASE WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=x.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 'BLOCKED' + WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=x.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CURRENT') THEN 'CURRENT' + ELSE 'UNKNOWN' END governance_status, + COALESCE(x.build_health,'UNKNOWN') build_status, + COALESCE(ci.ci_health,'NO_RUN') ci_status, + COALESCE(i.health,'UNKNOWN') integrity_status, + COALESCE(rv.health,'UNKNOWN') review_status, + COALESCE(a.health,'UNKNOWN') authority_status, + COALESCE(d.health,'UNKNOWN') drift_status, + (COALESCE(rv.p0,0)+COALESCE(rv.p1,0) + +CASE WHEN COALESCE(x.build_health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(i.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(ci.ci_health,'NO_RUN')='FAIL' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(a.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN COALESCE(d.health,'UNKNOWN')='BLOCKED' THEN 1 ELSE 0 END + +CASE WHEN EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=x.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 1 ELSE 0 END) blocking_reason_count, + CASE + WHEN COALESCE(x.build_health,'UNKNOWN')='BLOCKED' OR COALESCE(i.health,'UNKNOWN')='BLOCKED' OR COALESCE(rv.health,'UNKNOWN')='BLOCKED' OR COALESCE(a.health,'UNKNOWN')='BLOCKED' OR COALESCE(d.health,'UNKNOWN')='BLOCKED' OR COALESCE(ci.ci_health,'NO_RUN')='FAIL' OR EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=x.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CONFLICT') THEN 'BLOCKED' + WHEN COALESCE(x.build_health,'UNKNOWN')='UNKNOWN' OR COALESCE(i.health,'UNKNOWN')='UNKNOWN' OR COALESCE(rv.health,'UNKNOWN')='UNKNOWN' OR COALESCE(a.health,'UNKNOWN')='UNKNOWN' OR COALESCE(d.health,'UNKNOWN')='UNKNOWN' OR COALESCE(ci.ci_health,'NO_RUN') IN('NO_RUN','IN_PROGRESS') OR NOT EXISTS(SELECT 1 FROM v_governance_assertion_current g WHERE g.repository=x.repository AND g.subject='G0' AND g.predicate='designation_status' AND g.status='CURRENT') THEN 'UNKNOWN' + WHEN COALESCE(x.build_health,'UNKNOWN')='DEGRADED' OR COALESCE(rv.health,'UNKNOWN')='DEGRADED' OR COALESCE(a.health,'UNKNOWN')='DEGRADED' OR COALESCE(d.health,'UNKNOWN')='DEGRADED' THEN 'DEGRADED' + ELSE 'HEALTHY' END overall_health +FROM active x +LEFT JOIN ci ON ci.repository=x.repository AND ci.build_id=x.latest_merged_build +LEFT JOIN i ON i.repository=x.repository +LEFT JOIN rv ON rv.repository=x.repository +LEFT JOIN a ON a.repository=x.repository +LEFT JOIN d ON d.repository=x.repository; + +CREATE VIEW v_dashboard_summary_json AS +SELECT repository,jsonb_build_object( + 'overall_health',overall_health,'canonical_head',canonical_head,'latest_build',latest_merged_build,'blocking_reason_count',blocking_reason_count, + 'gates',jsonb_build_object('governance',governance_status,'build',build_status,'ci',ci_status,'integrity',integrity_status,'review',review_status,'authority',authority_status,'drift',drift_status), + 'timeline',COALESCE((SELECT jsonb_agg(jsonb_build_object('at',occurred_at,'kind',event_kind,'id',event_id,'details',details) ORDER BY occurred_at) FROM v_governance_timeline t WHERE t.repository=r.repository),'[]'::jsonb) ++) dashboard FROM v_repository_health r; + +COMMIT; diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/receipts/BUILD-CLP-001-S-verification.json b/governance/clp-001/builds/BUILD-CLP-001-S/receipts/BUILD-CLP-001-S-verification.json new file mode 100644 index 0000000..501f929 --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/receipts/BUILD-CLP-001-S-verification.json @@ -0,0 +1,19 @@ +{ + "authority_boundary": "OBSERVABILITY_ONLY_NO_EXECUTION_AUTHORITY", + "build_id": "BUILD-CLP-001-S", + "version": "1.0.2", + "parent_baseline": "b0f19f2d0ce8a086604ed1f08d1202cd5650dae8", + "source_manifest_sha256": "aba8841c7e0c175c308e7e6410367874a9e41ec562de53bfd38e5820a728ea25", + "workflow_sha256": "TO_BE_RECORDED_FROM_FINAL_EXACT_HEAD_RUN", + "prior_exact_head_review_commit": "544b694f69796631ed17a5cdfa4184a88b33f2f4", + "prior_exact_head_review_result": "BLOCKED_BY_1_P1_AND_1_P2", + "remediation_migration": "006_clp001_s_exact_evidence_binding.sql", + "remediation_tests": "T15-T16_PLUS_T1-T14_REGRESSION", + "ci_binding": "ACTIVE_BUILD_ID_PLUS_ACTIVE_IMPLEMENTATION_SHA", + "integrity_semantics": "DERIVED_FROM_EXPECTED_VS_OBSERVED_HASH_AND_BYTE_MEASUREMENTS", + "degradation_reason": "AUTH-APPLEVALLEY-155360 freshness review due", + "stale_g0_drift": "SUPERSEDED_NON_BLOCKING", + "source_manifest_enforcement": "HARD_CODED_DIGEST_PLUS_RECEIPT_DIGEST_PLUS_EXACT_INVENTORY", + "final_exact_head_gate": "PENDING_AFTER_WORKFLOW_FREEZE", + "independent_exact_head_review": "REQUIRED_AFTER_FINAL_CI" +} diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/receipts/S-source-manifest.json b/governance/clp-001/builds/BUILD-CLP-001-S/receipts/S-source-manifest.json new file mode 100644 index 0000000..79cc9bb --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/receipts/S-source-manifest.json @@ -0,0 +1,67 @@ +{ + "build_id": "BUILD-CLP-001-S", + "version": "1.0.2", + "parent_baseline": "b0f19f2d0ce8a086604ed1f08d1202cd5650dae8", + "files": [ + { + "path": "migrations/003_clp001_s_governance_health.sql", + "bytes": 12694, + "sha256": "627e8123b7ad9028930bb114abc6564334cd81e1d7c18e0e0d8dd514e869d730" + }, + { + "path": "migrations/004_clp001_s_review_hardening.sql", + "bytes": 6725, + "sha256": "8fa03938fbd79d7bd92afa9125187c0f7794aaea4c5280becfa869bcebf7ecfe" + }, + { + "path": "migrations/005_clp001_s_canonical_binding.sql", + "bytes": 8194, + "sha256": "5c2b7997062ccc6027388095594cfa5add10072643ee3cdbb5bc8407538e3413" + }, + { + "path": "migrations/006_clp001_s_exact_evidence_binding.sql", + "bytes": 6515, + "sha256": "e82548de31db5ad7dd2af2b6da2e925fa0250bbf5bfebf310f7fe33c76fde2dc" + }, + { + "path": "tests/s-health.sql", + "bytes": 14026, + "sha256": "b2926005e54f868dd46c6d3c78bf38a5fb26bbf5243c7374d2d1af5977d4505f" + }, + { + "path": "tests/s-health-v102.sql", + "bytes": 4092, + "sha256": "ac9ca41431e0b1a6af2160c777f13a5644391db878c2932e8eed9a8b6cc1b810" + }, + { + "path": "fixtures/repository-observations.sql", + "bytes": 4945, + "sha256": "396b4c1d5aa37a97af1c3fc2aa5caf18149fe2ad87e05b0cc96a7074769fac5f" + }, + { + "path": "fixtures/G0-STATUS-SUPERSESSION.json", + "bytes": 1096, + "sha256": "16013daf1de953f037df69ba9f5534cade3e09eb37f3eb9d32eaf2962a965c96" + }, + { + "path": "fixtures/R-INDEPENDENT-REVIEW-RECEIPT.json", + "bytes": 609, + "sha256": "23234beff4dac072956f38fbdfdf097b8810d6e5f1ef2dfa586015f0f5b687d9" + }, + { + "path": "README-S.md", + "bytes": 1700, + "sha256": "1bb532af45b7ecce305b07a724af988b79dd2d617e76f814864c429b633b93b0" + }, + { + "path": "docs/BUILD-CLP-001-S-SPEC.md", + "bytes": 1600, + "sha256": "2ba76b70d32133fc19300d8c86ffb390c46ee14578683c60201ddad2a01e7622" + }, + { + "path": "docs/2026-10-04-build-clp-001-s-plan.md", + "bytes": 2666, + "sha256": "b6e6aa00a7b0f8ada186667e21eff944dd5d65bd7737905fe75fb07f30454c10" + } + ] +} diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health-v102.sql b/governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health-v102.sql new file mode 100644 index 0000000..63d401a --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health-v102.sql @@ -0,0 +1,34 @@ +BEGIN; +SET search_path=edopsys_observability,public; +CREATE OR REPLACE FUNCTION pg_temp.assert_eq(actual text,expected text,label text) RETURNS void LANGUAGE plpgsql AS $$BEGIN IF actual IS DISTINCT FROM expected THEN RAISE EXCEPTION '% expected %, got %',label,expected,actual; END IF;END$$; +CREATE OR REPLACE FUNCTION pg_temp.obs(repo text,id text,typ text) RETURNS void LANGUAGE plpgsql AS $$BEGIN INSERT INTO obs_observations VALUES(id,repo,typ,id,NULL,clock_timestamp(),'sha256:'||repeat('a',64),'{}');END$$; +CREATE OR REPLACE FUNCTION pg_temp.good(repo text,prefix text) RETURNS void LANGUAGE plpgsql AS $$BEGIN + PERFORM pg_temp.obs(repo,prefix||'-base','REPOSITORY_HEAD');INSERT INTO repository_baseline VALUES(prefix||'-base',repo,'head','BUILD-X','g0','g1','p','q','r',clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-build','BUILD_RECEIPT');INSERT INTO build_status VALUES(prefix||'-build',repo,'BUILD-X',true,'impl','merge','parent',1,1,'success','APPROVED',0,true,clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-ci','CI_RUN');INSERT INTO ci_runs VALUES(prefix||'-ci',repo,'BUILD-X',1,'impl','impl','completed','success','success',clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-rev','PR_REVIEW');INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES(prefix||'-rev',repo,1,'impl','impl','reviewer',NULL,'APPROVED',true,false,false,clock_timestamp(),'__summary__'); + PERFORM pg_temp.obs(repo,prefix||'-int','ARTIFACT_INTEGRITY');INSERT INTO artifact_integrity VALUES(prefix||'-int',repo,'required',true,'PASS','x','x',1,1,clock_timestamp());INSERT INTO artifact_integrity_scope VALUES(prefix||'-int',repo,'BUILD-X',clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-auth','AUTHORITY_RECORD');INSERT INTO authority_records VALUES(prefix||'-auth',repo,'AUTH','v1','SC-0','J','h','CURRENT',false,clock_timestamp()); + INSERT INTO governance_status_assertions VALUES(prefix||'-g0',repo,'G0','designation_status','"DESIGNATED"','g0.json','sha',clock_timestamp(),NULL,NULL,2,'CURRENT'); + INSERT INTO governance_drift_findings VALUES(prefix||'-drift',repo,'ASSESSMENT','repository','P3','RESOLVED',NULL,clock_timestamp()); +END$$; + +-- T15: same build ID advances to a new implementation SHA. Old successful CI MUST NOT authorize it. +SELECT pg_temp.good('t15','t15'); +SELECT pg_temp.obs('t15','t15-build-new','BUILD_RECEIPT'); +INSERT INTO build_status VALUES('t15-build-new','t15','BUILD-X',true,'impl-new','merge-new','parent',1,1,'success','APPROVED',0,true,clock_timestamp()+interval '2 seconds'); +SELECT pg_temp.obs('t15','t15-review-new','PR_REVIEW'); +INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES('t15-review-new','t15',2,'impl-new','impl-new','reviewer',NULL,'APPROVED',true,false,false,clock_timestamp()+interval '2 seconds','__summary__'); +SELECT pg_temp.assert_eq((SELECT ci_status FROM v_repository_health WHERE repository='t15'),'NO_RUN','T15-ci-implementation-binding'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t15'),'UNKNOWN','T15-fail-closed'); + +-- T16: caller-supplied PASS cannot override contradictory or incomplete measurements. +SELECT pg_temp.good('t16','t16'); +SELECT pg_temp.obs('t16','t16-bad-integrity','ARTIFACT_INTEGRITY'); +INSERT INTO artifact_integrity VALUES('t16-bad-integrity','t16','bad-pass',true,'PASS','expected','observed',10,9,clock_timestamp()+interval '1 second'); +INSERT INTO artifact_integrity_scope VALUES('t16-bad-integrity','t16','BUILD-X',clock_timestamp()+interval '1 second'); +SELECT pg_temp.assert_eq((SELECT integrity_status FROM v_repository_health WHERE repository='t16'),'BLOCKED','T16-measurement-derived-integrity'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t16'),'BLOCKED','T16-fail-closed'); + +SELECT 'S_T15_T16_EXACT_EVIDENCE_BINDING_PASS'; +ROLLBACK; diff --git a/governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health.sql b/governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health.sql new file mode 100644 index 0000000..8a5f00a --- /dev/null +++ b/governance/clp-001/builds/BUILD-CLP-001-S/tests/s-health.sql @@ -0,0 +1,121 @@ +BEGIN; +SET search_path=edopsys_observability,public; +CREATE OR REPLACE FUNCTION pg_temp.assert_eq(actual text,expected text,label text) RETURNS void LANGUAGE plpgsql AS $$BEGIN IF actual IS DISTINCT FROM expected THEN RAISE EXCEPTION '% expected %, got %',label,expected,actual; END IF;END$$; +CREATE OR REPLACE FUNCTION pg_temp.assert_gt0(actual bigint,label text) RETURNS void LANGUAGE plpgsql AS $$BEGIN IF actual IS NULL OR actual<=0 THEN RAISE EXCEPTION '% expected >0, got %',label,actual; END IF;END$$; +CREATE OR REPLACE FUNCTION pg_temp.obs(repo text,id text,typ text) RETURNS void LANGUAGE plpgsql AS $$BEGIN INSERT INTO obs_observations VALUES(id,repo,typ,id,NULL,clock_timestamp(),'sha256:'||repeat('a',64),'{}');END$$; +CREATE OR REPLACE FUNCTION pg_temp.base(repo text,id text) RETURNS void LANGUAGE plpgsql AS $$BEGIN PERFORM pg_temp.obs(repo,id,'REPOSITORY_HEAD');INSERT INTO repository_baseline VALUES(id,repo,'head','BUILD-X','g0','g1','p','q','r',clock_timestamp());END$$; +CREATE OR REPLACE FUNCTION pg_temp.core(repo text,prefix text) RETURNS void LANGUAGE plpgsql AS $$BEGIN + PERFORM pg_temp.base(repo,prefix||'-b'); + PERFORM pg_temp.obs(repo,prefix||'-build','BUILD_RECEIPT');INSERT INTO build_status VALUES(prefix||'-build',repo,'BUILD-X',true,'impl','merge','parent',1,1,'success','APPROVED',0,true,clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-ci','CI_RUN');INSERT INTO ci_runs VALUES(prefix||'-ci',repo,'BUILD-X',1,'impl','impl','completed','success','success',clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-rev','PR_REVIEW');INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES(prefix||'-rev',repo,1,'impl','impl','reviewer',NULL,'APPROVED',true,false,false,clock_timestamp(),'__summary__'); + PERFORM pg_temp.obs(repo,prefix||'-int','ARTIFACT_INTEGRITY');INSERT INTO artifact_integrity VALUES(prefix||'-int',repo,'required',true,'PASS','x','x',1,1,clock_timestamp());INSERT INTO artifact_integrity_scope VALUES(prefix||'-int',repo,'BUILD-X',clock_timestamp()); + PERFORM pg_temp.obs(repo,prefix||'-auth','AUTHORITY_RECORD');INSERT INTO authority_records VALUES(prefix||'-auth',repo,'AUTH','v1','SC-0','J','h','CURRENT',false,clock_timestamp()); + INSERT INTO governance_status_assertions VALUES(prefix||'-g0',repo,'G0','designation_status','"DESIGNATED"','g0.json','sha',clock_timestamp(),NULL,NULL,2,'CURRENT'); +END$$; +CREATE OR REPLACE FUNCTION pg_temp.good(repo text,prefix text) RETURNS void LANGUAGE plpgsql AS $$BEGIN + PERFORM pg_temp.core(repo,prefix); + INSERT INTO governance_drift_findings VALUES(prefix||'-drift',repo,'ASSESSMENT','repository','P3','RESOLVED',NULL,clock_timestamp()); +END$$; + +-- T1 unresolved P1 -> BLOCKED; blocked canonical build contributes blocker count. +SELECT pg_temp.good('t1','t1'); SELECT pg_temp.obs('t1','t1-p1','PR_REVIEW'); +INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES('t1-p1','t1',1,'impl','impl','reviewer','P1','OPEN',false,false,true,clock_timestamp()+interval '1 second','F1'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t1'),'BLOCKED','T1-P1'); +SELECT pg_temp.good('t1b','t1b'); SELECT pg_temp.obs('t1b','t1b-build2','BUILD_RECEIPT'); +INSERT INTO build_status VALUES('t1b-build2','t1b','BUILD-X',false,'impl2',NULL,'parent',1,1,'success','APPROVED',0,true,clock_timestamp()+interval '1 second'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t1b'),'BLOCKED','T1-build'); +SELECT pg_temp.assert_gt0((SELECT blocking_reason_count FROM v_repository_health WHERE repository='t1b'),'T1-build-blocker-count'); + +-- T2 append-only later resolution of same logical finding removes block. +SELECT pg_temp.good('t2','t2'); SELECT pg_temp.obs('t2','t2-p1-open','PR_REVIEW'); +INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES('t2-p1-open','t2',1,'impl','impl','reviewer','P1','OPEN',false,false,true,clock_timestamp(),'F1'); +SELECT pg_sleep(0.01); SELECT pg_temp.obs('t2','t2-p1-resolved','PR_REVIEW'); +INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES('t2-p1-resolved','t2',1,'impl','impl','reviewer','P1','RESOLVED',true,false,false,clock_timestamp(),'F1'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t2'),'HEALTHY','T2'); + +-- T3 missing required artifact -> BLOCKED. +SELECT pg_temp.good('t3','t3'); SELECT pg_temp.obs('t3','t3-miss','ARTIFACT_INTEGRITY'); +INSERT INTO artifact_integrity VALUES('t3-miss','t3','missing',true,'MISSING','x',NULL,1,NULL,clock_timestamp());INSERT INTO artifact_integrity_scope VALUES('t3-miss','t3','BUILD-X',clock_timestamp()); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t3'),'BLOCKED','T3'); + +-- T4 hash mismatch -> BLOCKED. +SELECT pg_temp.good('t4','t4'); SELECT pg_temp.obs('t4','t4-hash','ARTIFACT_INTEGRITY'); +INSERT INTO artifact_integrity VALUES('t4-hash','t4','bad',true,'HASH_MISMATCH','x','y',1,1,clock_timestamp());INSERT INTO artifact_integrity_scope VALUES('t4-hash','t4','BUILD-X',clock_timestamp()); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t4'),'BLOCKED','T4'); + +-- T5 canonical exact-head CI remains PASS despite newer non-canonical failure. +SELECT pg_temp.good('t5','t5'); SELECT pg_temp.obs('t5','t5-ci-y','CI_RUN'); +INSERT INTO ci_runs VALUES('t5-ci-y','t5','BUILD-Y',2,'bad','bad','completed','failure','failure',clock_timestamp()+interval '2 seconds'); +SELECT pg_temp.assert_eq((SELECT ci_health FROM v_ci_health WHERE repository='t5' AND build_id='BUILD-X'),'PASS','T5-ci'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t5'),'HEALTHY','T5-health'); + +-- T6 stale-head CI on canonical build -> STALE_HEAD / DEGRADED. +SELECT pg_temp.good('t6','t6'); SELECT pg_temp.obs('t6','t6-ci2','CI_RUN'); +INSERT INTO ci_runs VALUES('t6-ci2','t6','BUILD-X',2,'old','new','completed','success','success',clock_timestamp()+interval '1 second'); +SELECT pg_temp.assert_eq((SELECT ci_health FROM v_ci_health WHERE repository='t6' AND build_id='BUILD-X'),'STALE_HEAD','T6-ci'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t6'),'DEGRADED','T6-health'); + +-- T7 stale historical G0 superseded -> current designation and no block. +SELECT pg_temp.good('t7','t7'); +INSERT INTO governance_status_assertions VALUES('t7-old','t7','G0','designation_status','"BLOCKED"','old.json',NULL,clock_timestamp()-interval '2 sec',clock_timestamp()-interval '1 sec','t7-g0',1,'SUPERSEDED'); +INSERT INTO governance_supersession_receipts VALUES('t7-rec','t7','t7-old','t7-g0','later authority supersedes earlier status','sha256:'||repeat('b',64),clock_timestamp()); +INSERT INTO governance_drift_findings VALUES('t7-drift2','t7','STALE_STATUS','G0','P2','SUPERSEDED','t7-rec',clock_timestamp()); +SELECT pg_temp.assert_eq((SELECT value#>>'{}' FROM v_governance_assertion_current WHERE repository='t7' AND subject='G0'),'DESIGNATED','T7-current'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t7'),'HEALTHY','T7-health'); + +-- T8 missing required observations -> UNKNOWN, including missing drift assessment. +SELECT pg_temp.base('t8','t8-b'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t8'),'UNKNOWN','T8-missing-many'); +SELECT pg_temp.core('t8d','t8d'); +SELECT pg_temp.assert_eq((SELECT drift_status FROM v_repository_health WHERE repository='t8d'),'UNKNOWN','T8-drift-gate'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t8d'),'UNKNOWN','T8-drift-overall'); + +-- T9 freshness review due -> DEGRADED; blocking authority conflict outranks UNKNOWN. +SELECT pg_temp.good('t9','t9'); SELECT pg_temp.obs('t9','t9-auth2','AUTHORITY_RECORD'); +INSERT INTO authority_records VALUES('t9-auth2','t9','AUTH2','v1','SC-0','J','h','FRESHNESS_REVIEW_DUE',false,clock_timestamp()+interval '1 second'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t9'),'DEGRADED','T9-freshness'); +SELECT pg_temp.good('t9c','t9c'); SELECT pg_temp.obs('t9c','t9c-unknown','AUTHORITY_RECORD'); SELECT pg_temp.obs('t9c','t9c-conflict','AUTHORITY_RECORD'); +INSERT INTO authority_records VALUES('t9c-unknown','t9c','AUTH-U','v1','SC-0','J','h','UNKNOWN',false,clock_timestamp()),('t9c-conflict','t9c','AUTH-C','v1','SC-0','J','h','CONFLICT',true,clock_timestamp()+interval '1 second'); +SELECT pg_temp.assert_eq((SELECT authority_status FROM v_repository_health WHERE repository='t9c'),'BLOCKED','T9-conflict-gate'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t9c'),'BLOCKED','T9-conflict-overall'); + +-- T10 append-only rejects observability and CLP mutation. +DO $$BEGIN BEGIN UPDATE repository_baseline SET canonical_head='mutated' WHERE repository='t1'; RAISE EXCEPTION 'T10 observability mutation unexpectedly succeeded'; EXCEPTION WHEN SQLSTATE '55000' THEN NULL; END; +BEGIN INSERT INTO clp_events(event_id,correlation_id,aggregate_id,aggregate_version,event_type,decision,event_hash,payload) VALUES('t10-event','t10','a',1,'Test','REPORTED','h','{}'); UPDATE clp_events SET event_type='mutated' WHERE event_id='t10-event'; RAISE EXCEPTION 'T10 CLP mutation unexpectedly succeeded'; EXCEPTION WHEN SQLSTATE '55000' THEN NULL; END;END$$; + +-- T11 baseline advances without build observation -> UNKNOWN, never stale historical build health. +SELECT pg_temp.good('t11','t11'); SELECT pg_temp.obs('t11','t11-base-y','REPOSITORY_HEAD'); +INSERT INTO repository_baseline VALUES('t11-base-y','t11','head-y','BUILD-Y','g0','g1','p','q','r',clock_timestamp()+interval '2 seconds'); +SELECT pg_temp.assert_eq((SELECT build_status FROM v_repository_health WHERE repository='t11'),'UNKNOWN','T11-build-binding'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t11'),'UNKNOWN','T11-overall'); + +-- T12 latest observation for one logical authority clears historical conflict. +SELECT pg_temp.good('t12','t12'); SELECT pg_temp.obs('t12','t12-auth-conflict','AUTHORITY_RECORD'); +INSERT INTO authority_records VALUES('t12-auth-conflict','t12','AUTH','v2','SC-0','J','h2','CONFLICT',true,clock_timestamp()+interval '1 second'); +SELECT pg_temp.assert_eq((SELECT authority_status FROM v_repository_health WHERE repository='t12'),'BLOCKED','T12-conflict'); +SELECT pg_temp.obs('t12','t12-auth-current','AUTHORITY_RECORD'); +INSERT INTO authority_records VALUES('t12-auth-current','t12','AUTH','v3','SC-0','J','h3','CURRENT',false,clock_timestamp()+interval '2 seconds'); +SELECT pg_temp.assert_eq((SELECT authority_status FROM v_repository_health WHERE repository='t12'),'HEALTHY','T12-latest-authority'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t12'),'HEALTHY','T12-overall'); + +-- T13 old review cannot authorize a newly active build head. +SELECT pg_temp.good('t13','t13'); SELECT pg_temp.obs('t13','t13-base-y','REPOSITORY_HEAD'); SELECT pg_temp.obs('t13','t13-build-y','BUILD_RECEIPT'); SELECT pg_temp.obs('t13','t13-ci-y','CI_RUN'); SELECT pg_temp.obs('t13','t13-int-y','ARTIFACT_INTEGRITY'); +INSERT INTO repository_baseline VALUES('t13-base-y','t13','head-y','BUILD-Y','g0','g1','p','q','r',clock_timestamp()+interval '2 seconds'); +INSERT INTO build_status VALUES('t13-build-y','t13','BUILD-Y',true,'impl-y','merge-y','parent',1,1,'success','APPROVED',0,true,clock_timestamp()+interval '2 seconds'); +INSERT INTO ci_runs VALUES('t13-ci-y','t13','BUILD-Y',2,'impl-y','impl-y','completed','success','success',clock_timestamp()+interval '2 seconds'); +INSERT INTO artifact_integrity VALUES('t13-int-y','t13','required-y',true,'PASS','y','y',1,1,clock_timestamp()+interval '2 seconds');INSERT INTO artifact_integrity_scope VALUES('t13-int-y','t13','BUILD-Y',clock_timestamp()+interval '2 seconds'); +SELECT pg_temp.assert_eq((SELECT review_status FROM v_repository_health WHERE repository='t13'),'UNKNOWN','T13-review-binding'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t13'),'UNKNOWN','T13-overall'); + +-- T14 old integrity cannot authorize a newly active build. +SELECT pg_temp.good('t14','t14'); SELECT pg_temp.obs('t14','t14-base-y','REPOSITORY_HEAD'); SELECT pg_temp.obs('t14','t14-build-y','BUILD_RECEIPT'); SELECT pg_temp.obs('t14','t14-ci-y','CI_RUN'); SELECT pg_temp.obs('t14','t14-rev-y','PR_REVIEW'); +INSERT INTO repository_baseline VALUES('t14-base-y','t14','head-y','BUILD-Y','g0','g1','p','q','r',clock_timestamp()+interval '2 seconds'); +INSERT INTO build_status VALUES('t14-build-y','t14','BUILD-Y',true,'impl-y','merge-y','parent',1,1,'success','APPROVED',0,true,clock_timestamp()+interval '2 seconds'); +INSERT INTO ci_runs VALUES('t14-ci-y','t14','BUILD-Y',2,'impl-y','impl-y','completed','success','success',clock_timestamp()+interval '2 seconds'); +INSERT INTO pr_reviews(id,repository,pr_number,reviewed_sha,expected_head_sha,reviewer,severity,finding_status,resolved,superseded,merge_blocking,observed_at,finding_key) VALUES('t14-rev-y','t14',2,'impl-y','impl-y','reviewer',NULL,'APPROVED',true,false,false,clock_timestamp()+interval '2 seconds','__summary__'); +SELECT pg_temp.assert_eq((SELECT integrity_status FROM v_repository_health WHERE repository='t14'),'UNKNOWN','T14-integrity-binding'); +SELECT pg_temp.assert_eq((SELECT overall_health FROM v_repository_health WHERE repository='t14'),'UNKNOWN','T14-overall'); + +SELECT 'S_T1_T14_CANONICAL_BINDING_PASS'; +ROLLBACK;