We let AI do the boring parts. We don't let it bypass the controls.
Most 'AI for accounting' tools either hand the model a service-role key and hope, or train on customer data without disclosing it. We do neither. The AI is bound by the same row-level security policies as a junior bookkeeper — not more. Your data is never used to train models. Posted entries are immutable at the database level, not just in application code.
A balanced double-entry journal: total debits equal total credits at 34,160.00, a balance the database trigger enforces at commit time before any row can post.
PROOF — the database enforces this, not the app
A posted entry the system cannot un-balance
The shape of the trust model
Three independent layers. Bypassing one bypasses none of the others.
The hard accounting invariants live in the database — in Postgres triggers and SECURITY DEFINER functions — not in application code an AI bug or a malicious actor could route around. Tenancy is enforced at the row, not the request. And the model never holds more privilege than the human it acts for.
Database-enforced
The invariants live in Postgres
Double-entry balance, posted-entry immutability and the append-only audit trail are database triggers and constraints — they hold even against a service-role write. There is no application-layer override path.
- DR = CR checked at commit, within ±0.0001 SAR
- Posted entries blocked from edit by a guard trigger
- Audit log: SELECT only, no INSERT/UPDATE/DELETE path
Tenant-isolated
Isolation at the row, not the request
Row-level security is enabled on every business table — zero exceptions in production. A user from one firm cannot read, write or delete another firm’s rows, enforced by Postgres rather than by a session check the web app could forget.
- RLS on every ledger + audit table
- Two levels: firm (org) and books (client)
- Cross-tenant references rejected at the foreign-key layer
AI-bound
The model holds no extra keys
When the AI extracts a document or drafts an entry, it acts through the same SECURITY DEFINER RPCs a human would call — with strict tool-use schemas. There is no AI path that writes data it could not otherwise touch.
- Extracted text treated as untrusted input, never instructions
- Per-call + per-batch cost ceilings — no surprise bills
- Low-confidence output flagged for human review
- RLS on every business table
- DR = CR enforced by trigger
- Posted entries immutable
- Append-only audit log
- Cross-tenant FK guards
- Signed-URL document access
- Encrypted at rest + TLS 1.2+
- EU-hosted · KSA-resident option
- 11-year audit retention
- Model output treated as untrusted
Connect → books, end to end
One platform, seven hops — and a control on every one.
A seller connects Amazon once. From there, settlements become balanced journal entries, inventory relieves at weighted-average cost, GCC VAT is captured per line, the trial balance ties, and the period closes — all inside one ledger. Here is the whole path, and the guard that holds at each step so nothing — not a bug, not the AI, not another tenant — can route around it.
Connect
Read-only Amazon link
The Selling Partner API connection is scoped to read settlements, orders and fees — it never holds write access to your store. OAuth tokens live in server-side secrets, never in a browser bundle or a committed workflow file.
OAuth tokens server-side onlySettlement
Each payout, decomposed
A settlement is parsed into its revenue, referral and FBA fees, refunds and reimbursements. The raw report is stored in private storage, reachable only through a tenant-scoped signed URL with a 10-minute time-to-live.
Signed-URL access · 10-min TTLJournal entry
Drafted, never auto-posted
The decomposed settlement becomes a double-entry draft. SUM(debits) must equal SUM(credits) within ±0.0001 SAR — checked by a constraint trigger at commit. An unbalanced entry cannot exist in the database.
DR = CR enforced by triggerWAC COGS
Inventory relieved at cost
Units shipped from FBA relieve the perpetual inventory subledger at weighted-average cost, and the matching cost-of-goods-sold entry is drafted in the same balanced JE. The subledger reconciles to the GL inventory account.
Perpetual subledger ties to GLVAT
GCC tax, per line
Output and input VAT are captured per line at the correct GCC rate (KSA 15% / UAE 5%), with the tax-invoice UUID, QR payload and hash recorded. A missing-QR invoice is flagged at extraction for review.
ZATCA fields captured + flaggedTrial balance
A TB that reconciles
Every posted entry rolls into a materialised trial balance per client. Because each JE balances and tenancy is enforced at the row, the TB ties by construction — and drills back to the source settlement and the extraction job that produced it.
Full drill-down to the source pixelClose
Period sealed, audit-logged
A period closes only when the trial balance is within ±SAR 0.01. A closed period refuses new entries unless an admin flags an explicit adjustment. The close, and every state change before it, writes an append-only audit-log row.
Close gate ±0.01 · append-only logThe control register
What the database guarantees, stated so your auditor can verify it.
These are not aspirations. Each one is a trigger, a constraint, or an RLS policy you can point a database introspection query at. The balance below is the same entry from the proof above — debits tie to credits, and the trigger is what makes that non-negotiable.
| Account | Debit | Credit |
|---|---|---|
| 1100Amazon clearing | 19,100.00 | — |
| 5210Referral & selling fees | 3,200.00 | — |
| 5220FBA fulfilment fees | 1,800.00 | — |
| 4001Sales returns & refunds | 700.00 | — |
| 4000Amazon sales — US | — | 24,800.00 |
| 5000Cost of goods sold (WAC) | 9,360.00 | — |
| 1330Inventory — FBA (WAC) | — | 9,360.00 |
| Totals | 34,160.00 | 34,160.00 |
| Source | Base | Rate | VAT |
|---|---|---|---|
| Amazon sales — KSA | 24,800.00 | 15% | 3,720.00 |
| Amazon sales — UAE | 24,800.00 | 5% | 1,240.00 |
| Output VAT captured | 4,960.00 | ||
- DR = CR tolerance, every posted entry±0.0001SAR
- Posted-entry edit attempts permitted0
- Same-day fat-finger un-post window24h
- Audit-log mutation paths from a session0
- Signed-URL time-to-live for source docs10min
- Accounting-record retention design11yr
- 34,160.00JE-018291Prepared
Senior accountant prepares the draft
- 34,160.00JE-018291Checked
Finance manager checks the entry
- 34,160.00JE-018291Posted
CEO / admin approves — then it posts
Why one platform is the safer platform
The stitched stack has seams. Seams are where data leaks and numbers drift.
The typical setup runs a settlement connector, a general cloud ledger, and spreadsheets for inventory and VAT. Each handoff is a CSV export, a re-keyed figure, a fourth place your data lives. Nexus does all three jobs in one audited ledger — so there is one access model to govern and one trail end to end.
| Concern | Connector + ledger + spreadsheets | Nexus — one platform |
|---|---|---|
| Data copies to secure | Settlement data lands in the connector, is exported, re-imported into the ledger, then copied again into spreadsheets — four resting places, four access models. | One ledger holds the settlement, the JE, inventory and VAT. One RLS-enforced access model governs all of it; no CSV hop between systems. |
| Audit trail | Each tool logs its own slice. Reconstructing who changed what across the connector, the ledger and a spreadsheet is manual — and a spreadsheet logs nothing. | One append-only audit log spans connect → settlement → JE → close, with actor, timestamp and payload-diff on every transition. Nothing edits it from a session. |
| Balance integrity | The ledger enforces double-entry; the spreadsheet does not. Inventory and VAT worked in a sheet can silently drift from the books. | DR = CR is a database trigger and inventory relieves at WAC inside the same balanced JE — the figures cannot drift apart, because they are the same rows. |
| AI privilege | Bolting an AI assistant onto a stitched stack usually means handing it broad API keys across several systems. | The AI acts only through the same tenant-scoped RPCs a human calls, with strict tool-use schemas and per-batch cost caps. It holds no key a person would not. |
| GCC tax | Most connectors and general ledgers are US/EU-shaped; GCC VAT, ZATCA fields and GOSI are bolted on in spreadsheets. | KSA 15% / UAE 5% VAT, ZATCA invoice fields and GOSI salary splits are first-class in the schema and the extraction prompts, inside the same secured ledger. |
Data copies to secure
Connector + ledger + spreadsheets
Settlement data lands in the connector, is exported, re-imported into the ledger, then copied again into spreadsheets — four resting places, four access models.
Nexus — one platform
One ledger holds the settlement, the JE, inventory and VAT. One RLS-enforced access model governs all of it; no CSV hop between systems.
Audit trail
Connector + ledger + spreadsheets
Each tool logs its own slice. Reconstructing who changed what across the connector, the ledger and a spreadsheet is manual — and a spreadsheet logs nothing.
Nexus — one platform
One append-only audit log spans connect → settlement → JE → close, with actor, timestamp and payload-diff on every transition. Nothing edits it from a session.
Balance integrity
Connector + ledger + spreadsheets
The ledger enforces double-entry; the spreadsheet does not. Inventory and VAT worked in a sheet can silently drift from the books.
Nexus — one platform
DR = CR is a database trigger and inventory relieves at WAC inside the same balanced JE — the figures cannot drift apart, because they are the same rows.
AI privilege
Connector + ledger + spreadsheets
Bolting an AI assistant onto a stitched stack usually means handing it broad API keys across several systems.
Nexus — one platform
The AI acts only through the same tenant-scoped RPCs a human calls, with strict tool-use schemas and per-batch cost caps. It holds no key a person would not.
GCC tax
Connector + ledger + spreadsheets
Most connectors and general ledgers are US/EU-shaped; GCC VAT, ZATCA fields and GOSI are bolted on in spreadsheets.
Nexus — one platform
KSA 15% / UAE 5% VAT, ZATCA invoice fields and GOSI salary splits are first-class in the schema and the extraction prompts, inside the same secured ledger.
Every control, in depth
Six domains. One frame.
The same specific commitments a security questionnaire asks for — pick a domain and the panel reconciles in place.
The accounting invariants are enforced in Postgres, not in application code that an AI bug or a malicious actor could bypass.
Double-entry enforced by trigger
Every journal entry must satisfy SUM(debits) = SUM(credits) within ±0.0001 SAR. The check runs as a CONSTRAINT TRIGGER on the journal-entry-lines table — even a service-role write that violates the rule is rejected at COMMIT time. There is no application-layer override.
Posted entries are immutable
Once an entry is posted, a guard trigger blocks any UPDATE to its accounts, amounts or narratives, and the RLS delete policy refuses to delete it. Corrections happen via reversal entries, not edits. One narrow, audit-logged exception: the same user who posted an entry can un-post it within 24 hours, and only while nothing downstream has consumed the posting.
Append-only audit log
Every workflow transition writes a row with actor, timestamp, from-state, to-state and a payload-diff. Application roles hold SELECT only; the table has no INSERT, UPDATE or DELETE path from any client session. Once written, a log row cannot be altered through the application.
Built around the GCC regulators
The specifics an auditor asks for — and where each one lives in the system.
These are design commitments encoded in the schema, the prompts and the migrations, not certifications. Stated explicitly so your auditor can point a query at each one.
Personal data, isolated and resident
Personal data inside documents is isolated per client by row-level security, reachable only via signed URLs. Data is hosted in the EU (Stockholm) under a DPA with SCC-equivalent transfer terms; a KSA-resident self-hosted path is offered on Pro + Enterprise.
E-invoice fields captured
Tax invoices capture the UUID, QR payload and hash on extraction. A missing-QR invoice is flagged for review rather than posted blind. Phase 1 consumes ZATCA inputs; outbound clearance is a later phase.
IFRS-aligned chart of accounts
The default chart of accounts is SOCPA-endorsed IFRS-aligned, with per-client customisation via the import wizard. Every account carries an English and an Arabic name so the books are statutory-bilingual.
Salary splits per nationality
Salary journal templates split GOSI contributions per nationality automatically (the Saudi-national vs expat employer rates), so payroll entries post with the right liability accounts without a manual spreadsheet.
Multi-jurisdiction VAT engine
VAT is captured per line at the correct GCC rate inside the ledger, with a VAT register that reconciles to posted entries — not a separate sheet a reviewer has to trust.
11-year append-only retention
Posted entries and audit-log rows are designed for ≥11-year retention, matching GCC document-retention statutes. No automatic deletion of accounting data; hard delete only via an admin RPC with an audit-log entry.
Before you send the questionnaire
The questions procurement asks — answered up front.
Do you train AI models on our data?
No. We do not opt customer extractions or chat history into any model-training pipeline. Anonymised, aggregated counts (pages, entries, document-type mix) may inform product improvement; the underlying content never does. This is contractual in the agreement and operational in the subprocessor configuration.
Can one of your customers see another customer’s data?
No. Row-level security is enabled on every business table, with no production exceptions, and keys on both the firm (org) and the books (client). Dedicated foreign-key triggers reject any cross-tenant reference before it commits. The bypass key never reaches the browser.
Can a posted journal entry be edited or deleted?
No. A guard trigger blocks any edit to a posted entry and the delete policy refuses it; corrections are made via reversal entries. The one narrow exception is a same-user, 24-hour un-post for a fat-finger, only while nothing downstream has consumed the posting — and it is itself audit-logged.
Where is our data hosted, and can it stay in KSA?
Data is hosted in the EU (Stockholm) today on every tier, under a Data Processing Addendum with SCC-equivalent transfer terms. For tenants whose data must remain inside KSA, a customer-managed in-KSA deployment with the same Postgres + RLS + audit-log stack is offered on Pro and Enterprise as a custom engagement.
Can your engineers see our books?
Not routinely. There is no “log in as the customer” path. Read-only access to a single tenant requires a written authorisation, a time-bounded grant that auto-revokes after 24 hours, and a matching audit-log entry. Break-glass access is alerted.
Do you hold SOC 2 or ISO 27001?
Not yet — both are targeted in the hardening phase. The current posture is built to be compliant: the controls (RLS, the DR=CR trigger, the append-only audit log, least-privilege access) already exist, so certification formalises them rather than building them. We respond to security questionnaires within two business days.
Want our DPA, a security-questionnaire response, or a walkthrough of the controls?
We respond to security questionnaires within two business days. The DPA is signed before any pilot uploads its first document.