46 lines
5.3 KiB
Markdown
46 lines
5.3 KiB
Markdown
# Dual-Control Signing Ceremonies (M-of-N Threshold)
|
|
|
|
## Module
|
|
Signer
|
|
|
|
## Status
|
|
VERIFIED
|
|
|
|
## Description
|
|
Orchestrator for M-of-N threshold signing ceremonies requiring multiple authorized participants to approve key operations, with API endpoints for ceremony initiation, participant enrollment, share submission, and ceremony completion.
|
|
|
|
## Implementation Details
|
|
- **CeremonyOrchestrator**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/CeremonyOrchestrator.cs` -- full M-of-N orchestration: CreateCeremonyAsync (configurable threshold/expiration per operation type), ApproveCeremonyAsync (duplicate detection, approver validation via ICeremonyApproverValidator, signature verification), ExecuteCeremonyAsync (only from Approved state), CancelCeremonyAsync, ProcessExpiredCeremoniesAsync (batch expiry); ICeremonyAuditSink for all lifecycle events
|
|
- **CeremonyStateMachine**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/CeremonyStateMachine.cs` -- enforces valid state transitions: Pending -> PartiallyApproved -> Approved -> Executed; terminal states (Executed/Expired/Cancelled); CanAcceptApproval, CanExecute, CanCancel guards; ComputeStateAfterApproval for threshold-based transitions
|
|
- **CeremonyModels**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/CeremonyModels.cs` -- Ceremony, CeremonyApproval, CeremonyResult, CeremonyFilter, CeremonyState enum (Pending/PartiallyApproved/Approved/Executed/Expired/Cancelled), CeremonyOperationType enum (KeyGeneration/KeyRotation/KeyRevocation/KeyExport/KeyImport/KeyRecovery), CeremonyErrorCode enum
|
|
- **CeremonyOptions**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/CeremonyOptions.cs` -- configurable thresholds and expiration per operation type
|
|
- **CeremonyAuditEvents**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/CeremonyAuditEvents.cs` -- Initiated, Approved, ApprovalRejected, ThresholdReached, Executed, Cancelled, Expired audit event types
|
|
- **ICeremonyOrchestrator**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/ICeremonyOrchestrator.cs` -- interface contract
|
|
- **ICeremonyRepository**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/Ceremonies/ICeremonyRepository.cs` -- persistence interface: CreateAsync, GetByIdAsync, HasApprovedAsync, AddApprovalAsync, UpdateStateAsync, ListAsync, GetExpiredCeremoniesAsync, MarkExpiredAsync
|
|
- **CeremonyEndpoints**: `src/Signer/StellaOps.Signer/StellaOps.Signer.WebService/Endpoints/CeremonyEndpoints.cs` -- REST API at `/api/v1/ceremonies`: POST / (create, ceremony:create), GET / (list with state/operationType/initiatedBy/tenantId/limit/offset filters), GET /{ceremonyId} (get by ID), POST /{ceremonyId}/approve (ceremony:approve, base64 signature required), POST /{ceremonyId}/execute (ceremony:execute), DELETE /{ceremonyId} (ceremony:cancel); all require ceremony:read authorization
|
|
- **Tests**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Tests/Ceremonies/CeremonyOrchestratorIntegrationTests.cs`, `CeremonyStateMachineTests.cs`
|
|
- **Source**: SPRINT_20260112_018_SIGNER_dual_control_ceremonies.md
|
|
|
|
## E2E Test Plan
|
|
- [x] POST /api/v1/ceremonies creates a new ceremony with threshold, expiration, and operation type; verify 201 response with ceremonyId
|
|
- [x] POST /{ceremonyId}/approve accepts approval with base64 signature; verify duplicate approval returns 409, unauthorized approver returns 403
|
|
- [x] Verify state transitions: Pending -> PartiallyApproved (after first approval) -> Approved (when threshold reached) -> Executed (after execution)
|
|
- [x] POST /{ceremonyId}/execute succeeds only when state is Approved; verify 409 for non-approved states
|
|
- [x] DELETE /{ceremonyId} cancels ceremony; verify only non-terminal ceremonies can be cancelled
|
|
- [x] Verify expired ceremonies cannot accept approvals or be executed (409)
|
|
- [x] GET / returns filtered list with pagination (limit/offset) and state/operationType filters
|
|
- [x] Verify audit events are recorded for all lifecycle transitions (Initiated, Approved, Executed, Cancelled, Expired)
|
|
|
|
## Verification
|
|
- **Run ID**: run-001
|
|
- **Date**: 2026-02-10
|
|
- **Method**: Tier 1 code review + Tier 2d existing test verification
|
|
- **Build**: PASS (0 errors, 0 warnings)
|
|
- **Tests**: PASS (491/491 signer tests pass)
|
|
- **Code Review**:
|
|
- CeremonyOrchestrator: Complete M-of-N orchestration verified. CreateCeremonyAsync generates UUID ceremony ID, sets Pending state with configurable threshold. ApproveCeremonyAsync checks for duplicate approvals, validates approver via ICeremonyApproverValidator, verifies signature, calls ComputeStateAfterApproval. ExecuteCeremonyAsync gate-checks Approved state. CancelCeremonyAsync rejects terminal states. ProcessExpiredCeremoniesAsync batch-processes expired ceremonies.
|
|
- CeremonyStateMachine: Deterministic state transitions verified. Pending -> PartiallyApproved (first approval), PartiallyApproved -> Approved (threshold met). Terminal states (Executed/Expired/Cancelled) reject all transitions.
|
|
- CeremonyEndpoints: Full REST API at /api/v1/ceremonies. All endpoints require ceremony:read authorization. CRUD + approve + execute + cancel operations verified with correct HTTP status codes.
|
|
- Tests: CeremonyOrchestratorIntegrationTests (end-to-end flow with in-memory repository), CeremonyStateMachineTests (all state transitions, guards, edge cases).
|
|
- **Verdict**: PASS
|