- Documentation
- /
- Fins
- /
- Phase 2 — Runtime Engine Scope
Phase 2 — Runtime Engine Scope
Phase 1 (built) renders the 23-model schema as an AI-Safe CRUD register: master data, journals, accounting documents, inbound messages, attempts, errors, acknowledgements, simulation rules and events — browsable, with a dashboard. But the states are static: the seed shows a batch already POSTED, a document already created, an ack already returned. Nothing is validated, posted or simulated by the system.
Phase 2 is the runtime that makes it a live test-double — accepting inbound messages, validating against master data, posting to accounting documents, enforcing idempotency, evaluating simulation rules and delivering outbound events. This app's whole purpose is to be the finance endpoint the Orchestrator and domain apps integrate against, so its Phase 2 is literally the integration engine.
Everything below is drawn from the pack's .rules.yaml, .workflows.yaml, .simulation.yaml,
.events.yaml and .orchestrator_mappings.yaml. It is a scope, not a design.
A. Inbound message intake & idempotency
An HTTP endpoint accepts JOURNAL_VALIDATE / JOURNAL_POST / JOURNAL_STATUS messages, writes
an InboundMessage (keyed on message_sid), and de-duplicates: a repeat message_id returns
the original outcome with acknowledgement type DUPLICATE (recording duplicate_of_message_sid)
rather than posting twice. This is the idempotency guarantee a real ERP interface needs.
B. Validation engine
Before posting, validate the mapped JournalBatch against real master data:
- Balance:
total_debit == total_creditper batch; each entry balanced. - Master data: every
gl_account_codeexists, isposting_allowed, active;cost_centre_code/profit_centre_codeexist and are valid (the demo'sBAD-MINE→COST_CENTRE_INVALID);requires_cost_centre/requires_profit_centrehonoured;tax_codevalid wheretax_relevant. - Fiscal period:
posting_datefalls in an OPEN period for the company (a CLOSED/LOCKED period → rejection).
Each check that fails writes a PostingError (with field_name, rejected_value, retryable),
and the message → REJECTED with a VALIDATED-fail or REJECTED acknowledgement.
C. Posting engine
On a valid JOURNAL_POST, allocate a document number from the matching
DocumentNumberSequence (advancing next_number), create the AccountingDocument +
AccountingDocumentLines, set the batch POSTED, and return a POSTED acknowledgement with
the document number and fiscal year. Each try is a PostingAttempt (VALIDATE then POST) with
timing and HTTP status.
D. Failure simulation
Before/around real processing, evaluate the enabled SimulationRules in priority order:
- MATCH (field/operator/value), PROBABILITY, LATENCY, FORCED_RESPONSE.
- A matching rule can force REJECTED / TEMPORARY_FAILURE / DELAY_ONLY, inject an
error_code/latency_ms, andstop_processing. Each firing writes aSimulationRuleHit.
This is what lets an integration test exercise retries, temporary failures and deterministic rejections on demand — the core reason this simulator exists.
E. Acknowledgement & outbound events
Every terminal state produces an Acknowledgement (VALIDATED / POSTED / REJECTED / DUPLICATE /
TEMPORARY_FAILURE) with the error count and a payload. A successful post also writes an
OutboundEvent (finance.document.posted) delivered to each enabled WebhookSubscription
(with signing), tracking delivery_status and retrying on failure — the callback the
Orchestrator consumes to close the loop with the originating domain app.
How it would be built
- A posting service (the intake/validation/posting engine, A–C) behind an HTTP API — this is the app's product, not an optional add-on.
- A simulation evaluator (D) invoked in the pipeline, config-driven from
SimulationRule. - An outbox deliverer (E) — reuse the orchestrator client for webhook delivery + retry.
- Tests straight from the pack's
demo_transactions.yaml(valid posting, invalid cost centre, closed period, duplicate, simulated temporary failure) — these are ready-made acceptance cases.
Suggested sequencing
- Intake + idempotency (A) — the endpoint and dedup, the integration contract.
- Validation engine (B) — deterministic rejections against master data + fiscal period.
- Posting engine (C) — document creation + numbering + POSTED ack.
- Failure simulation (D) — the raison d'être: forced failures for test harnesses.
- Acknowledgement + outbound delivery (E) — close the loop back to the Orchestrator.
Each slice is independently shippable and demoable. The orchestrator (built and run live this session) is both the client this simulator serves and the working template for the outbox/tests.