target-revenue/specs/PhaseLifecycleUseCases.md
tegwick 8e545fa965 Complete WP-0012-T01: Phase lifecycle use-cases document
specs/PhaseLifecycleUseCases.md enumerates all nine use cases from the
workplan systematically, grounded in the actual schema, code, and the
three real pilot-candidate manifests rather than abstractly. Two
findings surfaced beyond the original scope: first-Phase and
successive-Phase provenance turn out to be one shared modeling
question (both feed T02), and breach-record publication already has a
decided Operator+ rights tier per the Control Plane concept doc while
extension registration/canonicalization does not — recorded as an
explicit open question for WP-0014-T01 instead of an assumption.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 20:01:47 +02:00

11 KiB
Raw Blame History

Phase Lifecycle Use Cases

workplans/TREV-WP-0012-phase-provenance-and-policy-modeling.md T01. Written after using the Control Plane UI (WP-0009-T04) for the first time surfaced that the Phase Manifest schema and the UI built on top of it don't yet cover several use cases the framework's own normative documents already commit to. This document enumerates those use cases systematically — as a map of what exists, what's missing, and what's out of scope by design — before T02T05 turn any of the gaps into schema or UI decisions.

This is a documentation-only artifact. It does not itself change any schema, code, or UI.


1. First Phase ever declared for a repo

The common case today: a repo has never had a Phase before, and one is declared for its first governed Milestone Release.

Real examples (examples/pilot-candidates/*/manifest.json, specs/PilotPhaseCandidateSurvey.md): net-kingdom-local-identity, railiance-vergabe-teilnahme, info-tech-canon-service-surface. All three currently use a trsl:phase:draft-... id — none has actually been registered against the hosted Trust Service. That's intentional: no real Phase go-live is authorized yet (workplans/TREV-WP-0008-governance-and-pilot-rollout.md T05).

What the manifest captures today: milestone_release.name (a free-text label, e.g. "vergabe-teilnahme-v1 (RAILIANCE-WP-0002/RAILIANCE-WP-0014)") and milestone_release.source_revision (a bare short SHA, e.g. "398b0fe"). What it does not capture: which repo, or which Forgejo instance, that revision belongs to. The workplan references embedded in the name string are the only thing tying a Phase back to its source today, and they're prose, not structured data — a human convention, not something the schema or the UI can rely on.

Gap → WP-0012-T02 (repo identification fields).


2. A successive Phase on a repo that already had an earlier Phase

FR-11 (specs/ProductRequirementsDocument.md) requires the framework to "support multiple independently governed, sequential Phases over a software's lifetime, each identifying its base release, included change set, Milestone Release, Initial Target, Future License, degeneration policy, and ledger." Rule 7 (specs/TargetRevenueFrameworkCore.md §4) then requires that rights already granted by an earlier converted Milestone Release can never be withdrawn or restricted by a later Phase.

None of this is modeled in the schema today. There is no field anywhere in phase_manifest.schema.json for "the Phase this one succeeds" or "the base release this Phase's change set is measured against." A second Phase for the same repo today would look, structurally, identical to a completely unrelated repo's first Phase — the only difference would be human-readable text in milestone_release.name.

This matters concretely: railiance-vergabe-teilnahme's candidate manifest already names two workplans (RAILIANCE-WP-0002/RAILIANCE-WP-0014) inside a single Milestone Release's name — a preview of exactly this use case arriving before the schema was ready for it.

Open question this use case raises, not yet answered: what does a first-ever Phase put in a "base Phase" field that a successive Phase would use? A null/absent value works structurally, but the Trust Service's fold and validation logic downstream should treat "no prior Phase" and "prior Phase exists" as two branches it explicitly recognizes, not an accidentally-empty string.

Gap → WP-0012-T02 (repo identification fields, same task — the two questions are tightly coupled: "which repo" and "which prior Phase for that repo" are really one provenance model, not two).


3. Operator registers a Phase; Contributor proposes; Operator/Admin reviews

Already built (workplans/TREV-WP-0009-target-revenue-control-plane.md, all four tasks done). Included here for completeness and cross-reference, not to redesign it:

  • Rights model: Viewer / Contributor / Operator / Admin, ordinal via registry.RIGHTS_TIERS/has_right() (specs/TargetRevenueControlPlaneConcept.md §2's table).
  • Operator+ registers a Phase (control_plane.register_phase) and appends Development Credit directly (control_plane.append_development_credit).
  • Contributor submits a proposed entry instead (control_plane.propose_ledger_entry); Operator+ approves (appending under the reviewer's own credential, control_plane.approve_proposed_entry) or rejects (control_plane.reject_proposed_entry).
  • Every action is recorded in the Control Plane's own audit log (control_plane.record_audit_event/get_audit_log), independent of the Trust Service's own signed records, which only ever attest "the binky tenant acted," never which individual human.
  • UI: service/control_plane_app.py + service/control_plane_templates/ (WP-0009-T04).

No gap here, no follow-up workplan.


4. Remission Credit accrual over time under the active degeneration policy

trsl:policy:linear-longstop-v0 (the accepted v1 norm, specs/OpenQuestions-WorkingDefaults.md Q7) defines R(t) = T0 × clamp((t t0)/(tL t0), 0, 1), with discrete remission-credit ledger entries computed on a published schedule. FR-6 (specs/ProductRequirementsDocument.md) requires this to actually happen.

Nothing in this codebase computes or writes these entries. fold.py can consume a remission-credit entry if one exists in the ledger; nothing produces one. This is not a Control Plane UI gap — it predates the UI entirely, and was never in scope for WP-0006 (Trust Service) either. It surfaced now only because working through this use-case list prompted a fuller look at what a Phase's lifecycle actually requires end to end, not because anything about the recent UI work introduced it.

Gap → workplans/TREV-WP-0013-remission-credit-automation.md (its own workplan, not folded into this modeling pass, since it's a missing implementation, not a missing decision).


5. Conversion Event fires; Attestation published

FR-7 defines the Conversion Event as the objective moment Outstanding Target reaches zero, computable from the Manifest + Ledger alone, with no Trust Service declaration required (attestation.py's module docstring: "a Conversion Event is true the instant the ledger fold first reaches Outstanding Target = 0, independent of whether anything ever publishes an attestation about it"). attestation.publish_attestation is implemented, tested, and exposed at GET /phases/{id}/attestation — idempotent, publish-on-first-observation, never regenerated.

What's missing is purely presentational: the Control Plane UI has no view of a Phase's Attestation once one exists. A caller has to know to hit the Trust Service endpoint directly.

Gap → workplans/TREV-WP-0014-control-plane-extensions-breach-attestation-ui.md T03.


6. Monetization Extension registration and canonical-status review

FR-4 defines the six-field extension contract; registry.register_extension and registry.promote_extension_canonical are implemented and tested. Canonicalization is a governance action (set_extension_status, SECURITY DEFINER, never a plain UPDATE) — the same pattern already used for credential revocation and proposed-entry review elsewhere in this project.

Two things are missing, one of them a real open question, not just UI:

  • No Control Plane UI to register an extension or review/promote one.
  • Unresolved: specs/TargetRevenueControlPlaneConcept.md §2's rights table (cited in use case 3 above) does not mention extension registration or canonicalization at all — unlike breach records (use case 7), which the table explicitly assigns to Operator+. Whether registering a new extension should require any rights tier at all (the Trust Service's own registry.register_extension doesn't gate it today — any authenticated tenant can call it directly), and who should be able to canonicalize one, needs an explicit answer before UI work starts, not an assumption made while building the form.

Gap → workplans/TREV-WP-0014-control-plane-extensions-breach-attestation-ui.md T01.


7. Breach/Compliance Record publication

FR-10 and License V1C1 §7.4: a Licensor's own breach/termination determination, anonymized (Phase + category only) by default, named only with an explicit Commercial Use Agreement opt-in. breach_record.publish_breach_event/get_breach_records are implemented and tested. Unlike extension registration, this one's rights tier is already decided: specs/TargetRevenueControlPlaneConcept.md §2 assigns "publish breach/compliance records" to Operator+ explicitly, alongside Phase registration and direct ledger append. No open rights question here — purely a missing UI.

Gap → workplans/TREV-WP-0014-control-plane-extensions-breach-attestation-ui.md T02.


8. A second Licensor tenant besides binky onboards

Today, binky is the only Licensor identity in every environment (test fixtures, the local dev instance, presumably any eventual deployment). registry.create_licensor_identity/issue_sub_credential support a second tenant structurally and are exercised in tests, but never in any real onboarding flow — there is no "onboard a new Licensor" use case documented anywhere, only "issue another credential for the Licensor that already exists."

Judged not to need its own workplan (per the decision recorded in workplans/TREV-WP-0012-phase-provenance-and-policy-modeling.md's closing section) — this is squarely a governance matter and belongs under workplans/TREV-WP-0008-governance-and-pilot-rollout.md if and when a second real tenant is actually on the table. Revisit that call if it turns out to need real design work once that happens, rather than speculatively designing it now.


9. An external auditor verifies a Phase's evidence package offline

FR-8/FR-9: a complete Phase evidence package (manifest, ledger, extensions, attestation) can be exported in an open format and independently verified — recomputing the fold, checking the Ed25519 signature chain — without trusting, or even being able to reach, the Trust Service or the Control Plane at all (NFR-1 determinism/ reproducibility; attestation.py's own docstring makes the same point about conversion status specifically).

This use case has, by design, no Control Plane UI surface. Recording it here explicitly so it doesn't get silently miscounted as "not yet built" alongside cases 47 above, which are real gaps. fold.py and hashing.py are the offline-verifiable surface this use case depends on; both are already implemented, tested, and covered by the hosted conformance suite (tests/test_hosted_conformance.py).


Summary table

# Use case Status
1 First Phase for a repo Partially modeled — no repo/provenance fields (→ T02)
2 Successive Phase, same repo Not modeled at all (→ T02)
3 Register / propose / review (rights model) Done (WP-0009)
4 Remission Credit accrual Not implemented (→ WP-0013)
5 Conversion Attestation view Backend done, no UI (→ WP-0014-T03)
6 Extension registration/canonicalization Backend done, no UI, rights tier undecided (→ WP-0014-T01)
7 Breach/Compliance Record Backend done, no UI, rights tier already decided (→ WP-0014-T02)
8 Second Licensor tenant onboarding Structurally supported, no onboarding flow — deferred to WP-0008
9 Offline evidence verification Done by design, no UI needed