Engine-first, AI-assisted.
AI understands intent and predicts. A deterministic engine produces every authoritative figure. Security is evaluated for the actual person on every path. Here is how that works in the current build.
Three layers, three jobs, no overlap.
Intent, clarification, layout, narration
- Proposals validated against an allow-list and a schema
- The user confirms a restated goal before anything runs
- No code path writes a model response into a stored number
- Its output carries no provenance label - deliberately
Forecasts, trends, anomalies
- Always stored and shown as predictions
- Drawn as separate series, never mixed into actuals
- Runs on the history the requesting user can see
Every authoritative figure
- Exact decimal arithmetic
- No floating point, clock or randomness
- Linked to driver version and calculation run
- Replay check confirms results still match
In the recorded demo the language layer is a local open-weight model (Qwen 2.5 Coder through Ollama). A language model is optional: without one, a deterministic parser handles every action.
Figures you can open and trace.
- Driver formulas are parsed by the engine and never executed as code.
- Records are pre-aggregated per unit, period and attribute as they are written; screens read compact cells, never raw transactions.
- Opening a figure shows its provenance tag, formula and version, calculation run, inputs and the contributing units with their effective weights.
- The goal-seeking scenario engine searches for options computed by the driver engine on the organisation's own data.

Screens bind to meaning, not to tables.
By name
Objects bind to the measures, units and dimensions of the live model - never to raw tables or hand-written queries.
Only what you may see
The binding catalogue offers only what the author is allowed to see; anything else is marked as not bound instead of guessed.
Values at view time
A screen stores names. Values exist only when someone views it, and are composed for that person.

Actions run as the person who clicks.
- The browser sends only which screen and which button; the action comes from the stored screen version and is re-validated on every run.
- Forecasts always take the ML path; recalculation always takes the deterministic path; scenarios take the path the author chose. The path is recorded.
- Long work runs in a worker pool; each step commits on its own, so finished steps stay done.
- Outcomes are distinct: finished, stopped part way, could not finish, or not allowed for your role.
Authorisation evaluated for the actual person.
Tenant isolation
Every tenant row carries its organisation, and the data layer applies that boundary to every query. Sessions are server-side with anti-forgery protection.
Two-axis permissions
Roles grant verbs on modules. Access is scoped by organisation units and by measures (all, an allow-list, or all except a deny-list), evaluated together on every request.
Per viewer, clicker and recipient
Composition reads only the cells inside the person's scope. Out-of-scope units, hidden measures and missing data all return the same empty result.
Database backstop In validation
PostgreSQL row-level security on every tenant table has been built and is being validated on PostgreSQL.
Who changed it, who published it, who received it.
- Data writes with before and after values.
- Screen versions and publishing, with the approver.
- Button executions: actor, button, action class, path, parameters, outcome.
- Every send and trigger firing, down to the evaluated value and each recipient's outcome.

A modular monolith with separated engines.
Build status: pre-production. Scale testing and PostgreSQL validation are in progress.