03 — Phase 2 Scope

Phase 1 is the AI-Safe CRUD register: all 16 models, the menu, the dashboard and a coherent seeded scenario. The source pack also specifies runtime behaviour — a state machine, guard rules, operations and an event outbox. Those are not built in Phase 1; they are recorded here so the model stays honest about what enforces itself versus what a user maintains by hand today.

1. Recommendation lifecycle state machine

The pack defines the transition graph (RecommendationLifecycle). In Phase 1 status is a free field a user sets; Phase 2 would enforce the transitions and their guards:

DRAFT → ISSUED → RESPONSE_DUE → RESPONSE_RECEIVED → IMPLEMENTATION_IN_PROGRESS
     → EVIDENCE_PENDING → VALIDATION_PENDING → { EXCEPTION_OPEN ⇄ } READY_FOR_CLOSURE → CLOSED

Each edge has a condition (e.g. "all mandatory evidence requirements have submitted evidence", "any blocking validation is insufficient") that would be evaluated from the child records rather than asserted manually.

2. Closure guard rules

Four rules must all pass before a ClosureApproval may be APPROVED:

  1. Evidence validated — all mandatory validation tests are SUFFICIENT or NOT_APPLICABLE.
  2. No blocking exceptionscount(open, closure_blocking) == 0.
  3. Completion declared — the linked ClosureRequest.declared_complete == true.
  4. Completed actions carry completion metadata — a COMPLETED action has reported_complete_at and reported_complete_by.

In the demo these hold for Recommendation 1 (closed) and deliberately fail for Recommendation 2 (an open blocking exception), but nothing stops an operator overriding them in Phase 1 — Phase 2 makes them hard gates.

3. Operations (guarded transitions)

The pack lists operations that would bundle an effect with its precondition and emit an event: IssueRecommendation, SubmitManagementResponse (mark prior response current=false), ReportActionComplete, SubmitEvidence, CompleteValidation, RaiseException, ResolveException, ApproveClosure. Phase 2 would expose these as buttons/endpoints that also append a StatusHistory row.

4. The DomainEvent outbox

The source model includes a DomainEvent table (correlation/causation ids, idempotency key, publish status/attempts) — the transactional outbox for notifying downstream systems (recommendation.issued, response.submitted, evidence.submitted, validation.completed, exception.raised, recommendation.closed, …). It is dropped from Phase 1 because there is no publisher yet; it returns when AREA is wired to the orchestrator/event layer.

5. Response versioning

ManagementResponse carries response_version and a current flag. Phase 2 would enforce "one current response per recommendation" and flip the prior version's current on submit.


What Phase 1 deliberately dropped from the source pack

  • Tenancy / audit columnstenant_id, created_at/by, updated_at/by, row_version (framework concerns, not domain).
  • Integration columnssource_system, source_reference, external_correlation_key (return with the event layer).
  • DomainEvent outbox table (§4).
  • unique / indexes blocks — advisory in this codebase's DSL.

Everything else in the pack maps 1:1 to a Phase-1 model and field.