Implement WP-0015-T01/T04/T06: Phase provenance schema + ledger UI

Schema: phase.milestone_release gains required repo_hub/repo_hub_uri/
repo_id/repo_name; phase gains optional base_phase_id. Backfilled the
golden phase-001 fixture (placeholder values, it's synthetic) and the
three real pilot-candidate manifests with actual Forgejo repo ids
confirmed live (net-kingdom=67, vergabe-teilnahme=62,
info-tech-canon=47, all coulomb/*).

Discovered along the way: the schema change alone would have broken
the existing Control Plane registration form, since nothing collected
the four new fields. Fixed inline rather than leaving it broken
between tasks -- this also completes T04's ledger UI change (drop the
hand-typed ledger input, auto-compute /phases/{id}/ledger, add a
drill-down reference link on phase_detail.html) since both changes
touch the same form/route.

Full suite: 94 passing offline (was 84), 158 passing with Docker
(was 146).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-03 20:43:30 +02:00
parent 11800c7da1
commit 2a176d9961
13 changed files with 204 additions and 20 deletions

View file

@ -198,26 +198,41 @@ def phase_new_submit(
phase_id: str = Form(...),
milestone_release_name: str = Form(...),
source_revision: str = Form(...),
repo_hub: str = Form(...),
repo_hub_uri: str = Form(...),
repo_id: int = Form(...),
repo_name: str = Form(...),
base_phase_id: str = Form(""),
initial_target_amount: float = Form(...),
currency: str = Form(...),
future_license: str = Form(...),
degeneration_policy: str = Form(...),
longstop_at: str = Form(...),
ledger_uri: str = Form(..., alias="ledger"),
):
manifest = {
"framework": "TRF-0.1",
"license": "TRSL-0.1",
"phase": {
"id": phase_id,
"milestone_release": {"name": milestone_release_name, "source_revision": source_revision},
"milestone_release": {
"name": milestone_release_name,
"source_revision": source_revision,
"repo_hub": repo_hub,
"repo_hub_uri": repo_hub_uri,
"repo_id": repo_id,
"repo_name": repo_name,
},
"initial_target": {"amount": initial_target_amount, "currency": currency},
"future_license": future_license,
"degeneration_policy": degeneration_policy,
"longstop_at": longstop_at,
"ledger": ledger_uri,
# Auto-computed, never hand-typed (WP-0012-T04) -- this Trust
# Service instance is always the ledger's host in Stage 0.
"ledger": f"/phases/{phase_id}/ledger",
},
}
if base_phase_id:
manifest["phase"]["base_phase_id"] = base_phase_id
try:
control_plane.register_phase(conn, licensor, manifest)
except (control_plane.ControlPlaneError, registry.RegistrationError) as exc: