03 — Phase 2 Scope

Phase 1 is the AI-Safe CRUD register: all 19 models, the menu, the dashboard and a coherent seeded scenario. The source pack also specifies runtime behaviour — state machines, a validation engine, guard rules 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. Request & submission state machines

The pack defines request and submission transition graphs. In Phase 1 status is a free field a user sets; Phase 2 would enforce the transitions and their guards:

Request:    DRAFT → ISSUED → ACKNOWLEDGED → IN_PREPARATION → SUBMITTED → VALIDATING → ACCEPTED/REJECTED → CLOSED
Submission: RECEIVED → (QUARANTINED) → VALIDATING → EXCEPTION_OPEN → ACCEPTED/REJECTED/SUPERSEDED

with conditions from the child records (e.g. "a blocking validation failure → EXCEPTION_OPEN", "all blocking rules pass and reconciliations match → eligible for ACCEPTED").

2. The validation engine

Phase 1 stores ValidationRules, ValidationRuns and per-rule ValidationResults as data. Phase 2 would execute the rules against a submission (evaluating each expression), compute the run tallies (passed/warning/failed/blocking) and the overall outcome, and raise an IntakeException automatically for blocking failures.

3. Control-total reconciliation

ControlTotalDefinition carries a calculation_rule and tolerance; Reconciliation carries source/received/variance and an outcome. Phase 2 would compute the received value, the variance and the MATCHED / WITHIN_TOLERANCE / OUTSIDE_TOLERANCE outcome rather than storing them as entered.

4. Acceptance guard rules

The rules that must all pass before a SubmissionDecision may be ACCEPTED:

  1. Validation clean — the latest ValidationRun has no blocking_failures.
  2. Reconciled — every mandatory ControlTotalDefinition reconciles MATCHED/WITHIN_TOLERANCE.
  3. No blocking exceptions — no open blocking IntakeException for the submission.
  4. Authorised & in-scope — the request sits under a current agreement and permitted scope.

In the demo these fail for SUB-01 (blocking gross >= net failure) and hold for the corrected SUB-02, which is why SUB-01 is REJECTED and SUB-02 ACCEPTED. Phase 1 lets an operator record any decision; Phase 2 makes the guards hard.

5. 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 (request.issued, submission.received, validation.completed, submission.accepted, disposal.completed, …). It is dropped from Phase 1 because there is no publisher yet; it returns when ADIDAM is wired to the orchestrator/event layer.

6. Access & retention automation

AccessGrant (expiry/revocation) and RetentionDisposition (retain-until, legal hold, disposal status) are records in Phase 1. Phase 2 would expire access on schedule and drive the disposal status (NOT_DUE → DUE → …→ COMPLETED) from retain_until and legal holds.


What Phase 1 deliberately dropped from the source pack

  • Tenancy / audit columnstenant_id, created_at/by, updated_at/by, row_version.
  • Integration columnssource_system, source_reference, external_correlation_key.
  • DomainEvent outbox table (§5).
  • unique / indexes blocks — advisory in this codebase's DSL.

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