Architecture
Two planes on one Postgres, fail-closed RLS, and the enforced AI grounding contract.
Two planes, one Postgres
insigz splits cleanly into a business plane and a data plane that share one PostgreSQL instance but are managed very differently.
- Business plane — Next.js 15 + Payload 3.77. Owns auth, admin, org/project/members, sources config, settings, invoice-only commercial, marketing CMS, and the metadata of cases and reports. This is reused wholesale from the proven estate.
- Data plane — raw-SQL tables managed by forward-only migrations. Holds the canonical model:
bitemporal, Ed25519-signed, monthly-partitioned
observations, plusentities,entity_aliases,events,cases, andreports. Never modelled as Payload collections.
Row-level security (fail-closed)
Every data-plane table has RLS enabled and forced. Three independent predicates are AND-ed:
- Tenant —
tenant_idmust match the request context. - Clearance — the user's clearance must dominate the row's classification. Unset clearance ranks as OPEN, so a no-clearance user sees only OPEN rows.
- Cell — a NULL-cell row is tenant-shared; a cell-tagged row needs a matching cell, unless the user is faculty (visibility only, never approval).
The application connects as a dedicated non-owner role (NOBYPASSRLS, NOSUPERUSER) so RLS is
actually enforced. Context is set per short transaction via SET LOCAL app.*.
The AI grounding contract
insigz-ai calls Claude through a typed tool layer (the model never gets raw DB access). Every
customer-facing claim must cite a resolvable id: [OBS-####], [EVT-####], or [DOC-####]. A
server-side validator resolves every citation against the tenant's data before the answer ships.
Dangling or uncited claims are rejected and regenerated once; failing that, the assistant returns a
plain "could not ground" response. Nothing customer-facing publishes autonomously.