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>
245 lines
11 KiB
Markdown
245 lines
11 KiB
Markdown
# 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 T02–T05 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 4–7 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 |
|