Migration 005 — plans_participants(plan_id, participant_id, role, lei, did, created_at) with composite UNIQUE(plan_id, role, participant_id) and CHECK on the role vocabulary matching types/plan.ts.
services/participants.ts — idempotent add() / bulkAdd() / listForPlan() / listByRole() / remove(). The SoD layer resolves the authorised actor set for a transition by calling listByRole().
api/participants.ts + wiring in index.ts:
GET /api/plans/:planId/participants
POST /api/plans/:planId/participants → emits participants.authorized
The Participant Registry is one of the canonical data objects in arch §4 and the source of truth for segregation-of-duties decisions (arch §13). Until this PR participants lived only on the in-flight Plan object and were discarded on restart.
Verification
npx tsc --noEmit clean.
npx jest 87/87 green.
Closes gap-analysis v2 §4 + §10.9 (Participant Registry marked "missing").
## What
- **Migration 005** — `plans_participants(plan_id, participant_id, role, lei, did, created_at)` with composite `UNIQUE(plan_id, role, participant_id)` and CHECK on the role vocabulary matching `types/plan.ts`.
- **services/participants.ts** — idempotent `add()` / `bulkAdd()` / `listForPlan()` / `listByRole()` / `remove()`. The SoD layer resolves the authorised actor set for a transition by calling `listByRole()`.
- **api/participants.ts + wiring in index.ts:**
- `GET /api/plans/:planId/participants`
- `POST /api/plans/:planId/participants` → emits `participants.authorized`
- `DELETE /api/plans/:planId/participants/:role/:participantId`
- 7 unit tests against a Map-backed query stub.
## Why
The Participant Registry is one of the canonical data objects in arch §4 and the source of truth for segregation-of-duties decisions (arch §13). Until this PR participants lived only on the in-flight Plan object and were discarded on restart.
## Verification
- `npx tsc --noEmit` clean.
- `npx jest` 87/87 green.
Closes gap-analysis v2 §4 + §10.9.
- Migration 005 adds plans_participants (plan_id, participant_id, role,
lei, did, created_at) with a composite UNIQUE(plan_id, role,
participant_id) and CHECK on role vocabulary matching types/plan.ts.
- services/participants.ts: idempotent add() / bulkAdd() / listForPlan() /
listByRole() / remove() — the SoD layer reads listByRole() to resolve
the authorised actor set for a transition.
- api/participants.ts + wiring in index.ts:
GET /api/plans/:planId/participants
POST /api/plans/:planId/participants -> participants.authorized
DELETE /api/plans/:planId/participants/:role/:participantId
- 7 unit tests against a Map-backed query stub; full suite 87/87 green.
This pull request is broken due to missing fork information.
This pull request can be merged automatically.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes gap-analysis v2 §4 + §10.9 (Participant Registry marked "missing").
What
plans_participants(plan_id, participant_id, role, lei, did, created_at)with compositeUNIQUE(plan_id, role, participant_id)and CHECK on the role vocabulary matchingtypes/plan.ts.add()/bulkAdd()/listForPlan()/listByRole()/remove(). The SoD layer resolves the authorised actor set for a transition by callinglistByRole().GET /api/plans/:planId/participantsPOST /api/plans/:planId/participants→ emitsparticipants.authorizedDELETE /api/plans/:planId/participants/:role/:participantIdWhy
The Participant Registry is one of the canonical data objects in arch §4 and the source of truth for segregation-of-duties decisions (arch §13). Until this PR participants lived only on the in-flight Plan object and were discarded on restart.
Verification
npx tsc --noEmitclean.npx jest87/87 green.Closes gap-analysis v2 §4 + §10.9. - Migration 005 adds plans_participants (plan_id, participant_id, role, lei, did, created_at) with a composite UNIQUE(plan_id, role, participant_id) and CHECK on role vocabulary matching types/plan.ts. - services/participants.ts: idempotent add() / bulkAdd() / listForPlan() / listByRole() / remove() — the SoD layer reads listByRole() to resolve the authorised actor set for a transition. - api/participants.ts + wiring in index.ts: GET /api/plans/:planId/participants POST /api/plans/:planId/participants -> participants.authorized DELETE /api/plans/:planId/participants/:role/:participantId - 7 unit tests against a Map-backed query stub; full suite 87/87 green.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.