[Senate] Transparency log for governance decisions

← All Specs

Goal

Senate decisions — quality-gate verdicts, lifecycle transitions
(active → deprecated, under_review → falsified), Elo penalties,
honeypot retirements, pause grants — happen across a dozen modules
(scidex/senate/decision_engine.py, scidex/senate/integrity_sweeper.py, scidex/senate/governance.py, scidex/senate/edit_emitter.py, scidex/senate/sandbox_audit.py). Each writes to its own table or
just logs. There is no single transparency surface where a researcher
can ask "show me every governance decision that affected this
hypothesis" or an auditor can ask "who approved Senate alert X". This
task ships a unified, hash-chained, externally-readable transparency
log of all governance decisions, modelled on Certificate Transparency.

Effort: deep

Acceptance Criteria

☐ Migration migrations/20260428_governance_transparency.sql:

CREATE TABLE governance_decision (
        id BIGSERIAL PRIMARY KEY,
        decided_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
        decision_kind   TEXT NOT NULL,    -- 'lifecycle_change','elo_penalty',
                                          -- 'pause_grant','gate_verdict',
                                          -- 'attestation_revoke','provenance_break'
        subject_kind    TEXT NOT NULL,    -- 'hypothesis','analysis','agent','skill','quest'
        subject_id      TEXT NOT NULL,
        decided_by      TEXT NOT NULL,    -- 'senate.auto' or human user id
        rationale       TEXT NOT NULL,
        before_state    JSONB,
        after_state     JSONB,
        ref_alert_ids   BIGINT[],
        chain_seq       BIGINT             -- audit_chain seq, set after chain append
      );
      CREATE INDEX idx_gd_subject ON governance_decision(subject_kind, subject_id);
      CREATE INDEX idx_gd_kind    ON governance_decision(decision_kind);
      CREATE INDEX idx_gd_when    ON governance_decision(decided_at DESC);

☐ New module scidex/senate/transparency_log.py:
- record(*, decision_kind, subject_kind, subject_id,
decided_by, rationale, before_state, after_state,
ref_alert_ids=None) -> int
— inserts the row and appends
to audit_chain (event_kind='governance_decision'),
backfilling chain_seq.
- All call sites must use this helper rather than writing
the table directly so chain integrity is enforced.
Wire-up — patch the following call sites to record their
decisions:
- scidex/senate/decision_engine.py gate verdicts.
- scidex/senate/integrity_sweeper.py orphan-quarantine
decisions.
- scidex/atlas/lifecycle_constants.py callers (any caller
that flips a lifecycle field) — wrap via a small
decorator-pattern helper with_transparency(...).
- q-trust-signed-artifact-attestations revoke calls.
- q-rt-adversarial-debate-runner Elo penalties.
- q-safety-emergency-pause senate_pause writes.
Public read surface:
- GET /api/senate/decisions?subject_id=... returns
decisions for one subject, newest first. No auth (it's a
transparency log).
- GET /api/senate/decisions/recent?kind=...&since=ISO
streamable bulk read for auditors. Paginated.
- GET /senate/decisions/{decision_id} HTML detail page
showing before/after diff, rationale, chain proof
(chain_seq, chain_hash).
Per-subject overlay — every hypothesis / analysis detail
page renders a "Governance history" tab with the decision
stream for that subject. Wiring lives in the existing detail-
page templates; reuse the artifact-page tab pattern.
Inclusion proof — for any decision row, an auditor can
ask GET /api/senate/decisions/{id}/proof and receive the
audit_chain rows from genesis to the row's chain_seq,
plus the externally-published head from
data/scidex-papers/audit_chain_head.log. The auditor
verifies inclusion locally; SciDEX never asks them to trust
a server-side claim.
Daily digest — once per day a markdown digest of all
decisions in the trailing 24h is committed to
data/scidex-papers/governance/YYYY-MM-DD.md (in the papers
submodule), giving us an external git-history record of
governance activity. Reuse commit_artifact with
q-gov-attribution-audit trailers.
☐ Tests tests/test_transparency_log.py:
record-roundtrip; chain backfill (chain_seq non-null after
record); subject-query path; inclusion-proof reconstruction
against a fixture chain; daily-digest writer.

Approach

  • Migration + record helper + tests.
  • Wire the six call sites one at a time, each in its own commit so
  • regressions can be isolated.
  • Public read surface + per-subject overlay tab on hypothesis
  • detail page; smoke against a fixture decision.
  • Inclusion-proof endpoint; verify locally with a small CLI script.
  • Daily-digest writer; first commit logged to Work Log.
  • Dependencies

    • q-trust-audit-log-hash-chain — chain-append target.
    • q-gov-attribution-audit — daily digest commits ride on the
    attribution trailers.

    Dependents

    • Future: external auditor self-service portal.

    Work Log

    2026-04-27 — Public read surface + per-subject overlay [task:b2c3304f-c965-4c28-943a-e7f768a80dfd]

    Prior work (commit 10e207dda, squash of dff08e77) landed:

    • Migration migrations/20260428_governance_transparency.sql
    • Module scidex/senate/transparency_log.py with record(), chain-append, backfill ✅
    • Wire-up: decision_engine.py gate verdicts, integrity_sweeper.py quarantine ✅
    • governance_digest.py daily markdown writer ✅
    • 17 unit tests in tests/test_transparency_log.py (all pass) ✅

    This run adds the missing public read surface and per-subject overlay:
    • GET /api/senate/decisions — query by subject_id, newest first, paginated ✅
    • GET /api/senate/decisions/recent — bulk auditor stream, kind+since filter ✅
    • GET /api/senate/decisions/{id}/proof — audit_chain inclusion proof ✅
    • GET /senate/decisions/{id} — HTML detail page (before/after diff, chain proof) ✅
    • Hypothesis detail page: new Governance tab showing decision stream for that subject ✅
    • _build_governance_history_html() helper in api.py

    Pending (deferred to follow-on tasks):
    • lifecycle_constants callers with_transparency(...) decorator
    • attestation_revoke, elo_penalty, senate_pause wire-ups
    • Analysis detail page overlay (pattern same as hypothesis)

    Tasks using this spec (1)
    [Senate] Transparency log for governance decisions
    Senate done P87
    File: q-trust-governance-transparency-log_spec.md
    Modified: 2026-05-01 20:13
    Size: 6.6 KB