--- id: TREV-WP-0006 type: workplan title: "Trust Service reference implementation (PRD Phase 4b)" domain: infotech repo: target-revenue status: active owner: claude topic_slug: infotech created: "2026-07-29" updated: "2026-07-29" state_hub_workstream_id: "03f63e7e-c17a-4dcc-aa34-a79824dafcf3" --- # Trust Service reference implementation (PRD Phase 4b) Builds the hosted Trust Service that WP-0002 deliberately deferred: Phase Registry, Extension Registry, hosted Target Ledger, Metrics, and Conversion Attestation publication, serving multiple repos rather than the single offline golden-Phase package. This is the piece explicitly named in `SCOPE.md` §3 as out of scope until now. **Unblocked as of 2026-07-29:** `SCOPE.md` §4 rule 2 required (a) WP-0003's core extract deliverables to exist, and (b) working defaults for Longstop, currency, recognition, and minimum evidence to be published, before full Trust Service implementation could start. Both conditions are now met (WP-0003 finished 2026-07-29; `specs/OpenQuestions-WorkingDefaults.md` published since Stage 0). This workplan is the first to actually start that implementation. **Why now:** the midterm goal is to govern and monetize the evolution of repos across the `coulomb` Forgejo org's product lines (`coulomb-loop`, `net-kingdom`, `helix-forge`, the `railiance-*` family) — that requires a real, multi-repo-capable Trust Service, not the single-Phase offline library WP-0002 produced. **Does not include:** accepting real payments or tracking a real Phase for any production repo — see `workplans/TREV-WP-0008-governance-and-pilot-rollout.md` for the human-gated go-live step. This workplan builds the infrastructure; it does not turn it on for anyone's real money. ## Trust Service Product Requirements Document ```task id: TREV-WP-0006-T01 status: done priority: high state_hub_task_id: "c98a1871-ae5c-4c91-b59c-88a6e4ccc193" ``` Produce `specs/TrustServiceProductRequirementsDocument.md`: scope, stakeholders, and requirements for the hosted service, building directly on `specs/TechnicalSpecificationDocument.md` §4 (component architecture) and §3's schemas. Must state explicitly which of WP-0002's Stage 0 guarantees (determinism, offline verifiability, no Trust Service discretion over conversion) the hosted service inherits unchanged versus which Stage-0-only constraints (single golden Phase, no auth, no multi-tenancy) it must now lift. **Result:** `specs/TrustServiceProductRequirementsDocument.md` produced. Nine stakeholders identified (including Enforcement Partner, a category that did not exist at framework-PRD-drafting time). §3 states five inherited-unchanged Stage 0 guarantees (determinism, offline verifiability, no discretionary conversion authority, append-only ledger semantics, closed core vocabulary); §4 tables ten Stage-0-only constraints that must lift, mapped to their owning T03–T08 task, plus one flagged gap: no WP-0006 task currently owns the Breach/Compliance Record hosting component (TSD §4.1's 2026-07-29 addition, post-dates WP-0002) — recommend either a new T09 or folding it into T06 before implementation starts. Nine functional requirements (TS-FR-1–9) elaborate framework PRD FR-8/9/10 for a hosted, multi-tenant, authenticated context without redefining any schema field. ## Stack and storage ADR (hosted service — distinct scope from ADR-0001) ```task id: TREV-WP-0006-T02 status: done priority: high human_accept_required: true human_accepted_by: Bernd human_accepted_at: "2026-07-29" state_hub_task_id: "06eabd46-5de5-4d80-9bb7-c70ef6d80df9" ``` `docs/adr/ADR-0001-stage0-library-stack.md` explicitly scoped out hosting, storage, and multi-tenancy decisions (its Revisit trigger names this exact moment). Record a new ADR for: storage engine for the append-only Target Ledger at multi-repo scale, authentication/authorization model for Phase Registry writes, and hosting/deployment target — `railiance-infra` and `railiance-cluster` are the existing platform-infrastructure repos in this Forgejo org and are the natural first candidates to investigate, not assumed by default. **Human accept gate:** per the same policy as ADR-0001 — agents may draft, must not treat as accepted without explicit maintainer sign-off. **Result:** Accepted 2026-07-29 by the maintainer (Bernd), no changes requested. `docs/adr/ADR-0002-hosted-trust-service-stack.md`: PostgreSQL (append-only enforced at the database-grant/trigger level, not just convention) for storage; per-Licensor API token for write/read-grant access control, decoupled from the existing Ed25519 per-entry signature; `railiance-cluster`'s existing k3s/Helm/GitOps baseline (on the `railiance-infra`-provisioned HostEurope server) for hosting, rather than new infrastructure; Python reusing `src/target_revenue/` directly behind a thin HTTP layer. T03–T08 may now build against this decision. ## Phase Registry and Extension Registry hosting ```task id: TREV-WP-0006-T03 status: done priority: high state_hub_task_id: "fb9f00e5-5755-44e4-ad07-ba0dc73596b8" ``` Implement hosted versions of the Phase Registry and Extension Registry components (`specs/TechnicalSpecificationDocument.md` §4.1), serving multiple Phase Manifests and extension registrations across repos rather than one golden fixture. Reject non-conformant manifests/extensions at registration, exactly as the Stage 0 validators already do — this task adds multi-tenancy and persistence, not new validation logic. **Result:** Implemented per ADR-0002. `migrations/0001_registries.sql` creates `licensors`, `phase_manifests`, `extensions` tables, a `trf_app` role with **no UPDATE/DELETE grant** on `phase_manifests` or `extensions` (database-enforced append-only, not just application convention), and a `set_extension_status()` SECURITY DEFINER function as the only sanctioned path to `canonical`/`deprecated` — canonicalization is therefore a recorded, attributable governance action the application role cannot perform via ordinary UPDATE. `src/target_revenue/registry.py` wraps the existing `validation.py` checks (no new validation logic) with persistence and per-Licensor token authentication. `src/target_revenue/service/app.py` exposes a thin FastAPI surface (`POST/GET /phases`, `POST/GET /extensions`). Added a `service`/`service-dev` optional-dependency group (`pyproject.toml`) so the core offline library keeps zero new hard dependencies. `tests/test_registry_hosting.py` (7 tests, requires Docker, auto-skips otherwise) spins an ephemeral, disposable Postgres container — never the shared state-hub `infra-postgres-1`/`custodian` instance — covering registration, rejection with diff, duplicate-`phase_id` rejection, unknown-token rejection, extension canonicalization via the governance function, and two explicit database-privilege tests proving `trf_app` cannot UPDATE/DELETE `phase_manifests` or UPDATE `extensions` directly. Original 36-test offline suite verified unchanged and passing with plain system Python (no service deps required). ## Hosted Target Ledger append API ```task id: TREV-WP-0006-T04 status: done priority: high state_hub_task_id: "591e87d6-3b64-4f1f-b870-edf834edc522" ``` Implement an authenticated append API for Target Ledger entries per Phase, preserving WP-0002's append-only, hash-chained, deterministically-foldable guarantees exactly. Any party who can compute the fold offline from an export must get the same Outstanding Target as the hosted service — this is the property to test most aggressively, since it's the one a hosted service could most easily and least visibly break. **Result:** `migrations/0002_ledger.sql` adds `ledger_entries` (`GENERATED ALWAYS AS IDENTITY` sequence for exact append order; `trf_app` again has no UPDATE/DELETE grant). `src/target_revenue/ledger.py`'s `append_entry()`: rejects any caller-supplied `previous_entry_hash`/ `signature` outright (server-computed only), enforces phase ownership (a Licensor may only append to its own registered Phase — TS-FR-8 isolation), serializes concurrent appends per Phase via `pg_advisory_xact_lock`, computes the chain tip from the last stored entry and signs with the Trust Service instance's own Ed25519 key (`service/keys.py`, env-configured or ephemeral-with-warning for dev), reusing `validation.py`'s existing schema/currency checks unchanged. `service/app.py` adds `POST/GET /phases/{id}/ledger` and an unauthenticated `GET /public-key` (so an external party can verify signatures without trusting this API's own access control at all). Fixed an unrelated route ordering bug found while wiring this in: `{phase_id:path}` on the plain `GET /phases/{id}` route was greedily matching `/ledger`-suffixed paths too, since phase IDs contain colons but no slashes and never needed the `:path` converter — switched all phase routes to plain `{phase_id}`. `tests/test_ledger_hosting.py` (8 tests, Docker-gated): hash-chain linkage across appends, forged-hash/signature rejection, cross-Licensor isolation, currency-mismatch rejection, duplicate-entry-id rejection, DB-level UPDATE/DELETE privilege checks, signature verification via the public-key endpoint, and — the task's own highest-priority property — appending a mixed development-credit/remission-credit/credit-reversal sequence through the API, exporting it, and confirming `fold.fold_outstanding_target` over the export reproduces the exact expected Development Credit, Remission Credit, and Outstanding Target. Offline 36-test suite re-verified unchanged with plain system Python; no stray Docker containers left running. ## Metrics service ```task id: TREV-WP-0006-T05 status: done priority: medium state_hub_task_id: "6bab5e64-0091-4a25-906d-758310cbe723" ``` Implement the public metrics set from `specs/OpenQuestions-WorkingDefaults.md` Q9 (Initial Target, cumulative credits, Outstanding Target, conversion status, last checkpoint, Longstop timestamp as mandatory; velocity/forecast as recommended, clearly labeled as forecasts per concept §14.6). **Result:** `src/target_revenue/metrics.py`'s `compute_metrics(manifest, entries, as_of)` — pure and deterministic like `fold.py` (the only input that varies with wall-clock time, `as_of`, is an explicit parameter, never read internally), reusing `fold.py`/`conversion.py` unchanged. Returns three explicitly separated blocks per TrustServicePRD TS-FR-5: `facts` (Q9's mandatory set — Initial Target, cumulative Development/Remission Credit, Outstanding Target, conversion status, last ledger entry id, Longstop timestamp), `calculations` (target satisfaction percentage, Development/Remission Credit velocity per day, days since last material progress), and `forecasts` (projected conversion date, `null` whenever already converted or velocity is zero/negative — never populated as a disguised fact). Added `GET /phases/{id}/metrics` to `service/app.py`, unauthenticated per FR-9/FR-10. `tests/test_metrics.py` (6 tests, no Docker/Postgres required, runs under plain system Python — no new hard dependency) covers the mandatory-facts set, fact/calculation/forecast separation, percentage correctness, the zero-material-entries case, and `as_of` timezone-awareness. Added one Docker-gated test to `tests/test_ledger_hosting.py` proving the hosted `/metrics` response (fetched with no Authorization header) exactly equals `compute_metrics()` run offline against the same exported Manifest + Ledger. Full suite (offline 36 + metrics 6 + Docker-gated 22) verified passing; no stray containers left running. ## Conversion Attestation publication ```task id: TREV-WP-0006-T06 status: todo priority: high state_hub_task_id: "f08d3d73-4c75-4049-97d0-c27ae8513336" ``` Implement Conversion Attestation generation and publication as a hosted service, preserving the non-discretionary rule from `src/target_revenue/conversion.py`: the service publishes evidence of a conversion already true from the Manifest + Ledger, never a precondition for it. Any repo's own tooling must be able to recompute conversion status without querying this service at all. ## Multi-repo onboarding flow ```task id: TREV-WP-0006-T07 status: todo priority: medium state_hub_task_id: "44c5846e-1f37-41fe-8ac0-fc7d88628e9f" ``` Define and implement how a repo (e.g. `coulomb-loop`, `net-kingdom`, `helix-forge`, a `railiance-*` repo) registers a Phase against the hosted Trust Service: what it commits to its own repo (a Phase Manifest file, per `specs/PhaseManifestSpecification.md`) versus what it submits to the Trust Service (the registration call). Coordinate with `workplans/TREV-WP-0008-governance-and-pilot-rollout.md`, which selects the actual first repos — this task defines the mechanism, not the pilot selection. ## Conformance test suite at hosted scale ```task id: TREV-WP-0006-T08 status: todo priority: medium state_hub_task_id: "359c9c5e-a49a-40c1-82ea-2bf80e93e7d6" ``` Extend WP-0002's conformance suite to run against the hosted service: multiple concurrent Phases across different repos, the golden Phase example replayed through the hosted API rather than only the offline library, and a specific regression test that hosted and offline folds of the same exported ledger always agree.