Persistent participant registry (plans_participants + API)
Some checks failed
CI / Frontend Lint (pull_request) Failing after 7s
CI / Frontend Type Check (pull_request) Failing after 7s
CI / Frontend Build (pull_request) Failing after 7s
CI / Frontend E2E Tests (pull_request) Failing after 10s
CI / Orchestrator Build (pull_request) Failing after 6s
CI / Contracts Compile (pull_request) Failing after 7s
CI / Contracts Test (pull_request) Failing after 5s
Code Quality / SonarQube Analysis (pull_request) Failing after 20s
Code Quality / Code Quality Checks (pull_request) Failing after 7s
Security Scan / Dependency Vulnerability Scan (pull_request) Failing after 4s
Security Scan / OWASP ZAP Scan (pull_request) Failing after 4s

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 commit is contained in:
Devin
2026-04-22 18:15:26 +00:00
parent b66ec0a78f
commit 5741fd5d9b
6 changed files with 454 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ import { logger } from "./logging/logger";
import { getMetrics, httpRequestDuration, httpRequestTotal, register } from "./metrics/prometheus";
import { healthCheck, readinessCheck, livenessCheck } from "./health/health";
import { listPlansEndpoint, createPlan, getPlan, getPlanState, getPlanEvents, streamPlanEvents, addSignature, validatePlanEndpoint } from "./api/plans";
import { listParticipants, addParticipant, removeParticipant } from "./api/participants";
import { streamPlanStatus } from "./api/sse";
import { executionCoordinator } from "./services/execution";
import { runMigration } from "./db/migrations";
@@ -94,6 +95,9 @@ app.get("/api/plans/:planId/events", getPlanEvents);
app.get("/api/plans/:planId/events/stream", streamPlanEvents);
app.post("/api/plans/:planId/signature", addSignature);
app.post("/api/plans/:planId/validate", validatePlanEndpoint);
app.get("/api/plans/:planId/participants", listParticipants);
app.post("/api/plans/:planId/participants", auditLog("ADD_PARTICIPANT", "plan"), addParticipant);
app.delete("/api/plans/:planId/participants/:role/:participantId", auditLog("REMOVE_PARTICIPANT", "plan"), removeParticipant);
// Execution endpoints
import { executePlan, getExecutionStatus, abortExecution } from "./api/execution";