KURAL is sold to compliance teams that read the architecture before the brochure. This page is the architecture, in their words. Every item below is shippable evidence — not roadmap.
Last reviewed: 2026-05-15
sub=operator_id and aud=kural-api claims. Replaces the previous shared- bearer model so a single token leak no longer = god-mode./health, /stats, /controls, OAuth callbacks, and auditor-token-gated /api/external-share/access/ paths are the only routes that bypass JWT. Everything else is 401-by- default.SuspiciousActivityReport, NoSarDecision, ResolutionRequest, ScreeningEvent, GamstopCheck, EvidenceRecord, StaffTrainingRecord. Policy: tenant_isolation with USING (operator_id = current_setting('app.tenant_id')).withTenant() — every tenant-scoped operation wraps Prisma queries in a transaction that runs SET LOCAL app.tenant_id = $1 first. The wrapper rejects operator_id values that don't match a strict allowlist regex (defence against SQL-injection into the GUC name).packages/db/rls/test-cross-tenant.sql connects as the application role with one tenant's context and asserts that SELECT on every protected table returns 0 rows for any other tenant.safeFetch() uses a custom undici Dispatcher with a lookup callback that returns the pre-verified IP, so a TOCTOU rebinding between guard-check and connect time cannot redirect the live connection. Redirects are disabled (a redirect re-does DNS).%PDF- magic-byte prefix, (b) rasterizes the PDF to PNG images via pdftocairo running inside the API container with no network egress, (c) caps the document at 20 pages, and (d) sends only the rasterized images to Claude vision. Text layers, embedded scripts, OCR-resistant invisible instructions — all discarded at the raster step.<<<DOCUMENT-START>>> ... <<<DOCUMENT-END>>> delimiters with an explicit system instruction that any text inside is to be read as data, never as command.submit_cert_extraction with the structured schema; free-form text replies are not parsed.status="needs_review" on the operator's dashboard with per-field confidence badges. No automated write to the evidence ledger without human confirm.packages/db/audit-share-allowlist.yaml. Default-deny on any new table. A CI gate (pnpm audit-share:validate) fails any PR that adds a Prisma model without an explicit include/exclude decision.collectTippingOffFindingIds() — Findings with an attached SAR or No-SAR decision are stripped from the auditor's view. EvidenceRecord rows with evidence_type ∈ SAR_EVIDENCE_TYPES are stripped too.ExternalShareAccessLog on every access.merkle_root + prev_chain_hash + chain_hash. Tampering with any historical record invalidates every subsequent chain hash.docs/security/INCIDENT-RESPONSE.md in the source repo. Covers detection, triage, containment, eradication, recovery, post-mortem. First quarterly tabletop exercise: July 2026.| Certification | Provider | Status | Target |
|---|---|---|---|
| SOC 2 Type 1 | Vanta + boutique CPA | Engagement letter signed | Q4 2026 report |
| SOC 2 Type 2 | Same auditor | Observation window after Type 1 issues | Q2 2027 report |
| ISO 27001 | BSI or DNV | Stage 1 letter | Q4 2026 (letter); Q1 2027 (cert) |
| CREST penetration test | Pentest People / NCC Group | Scoped, deposit paid | Report Q4 2026 |
| Cyber Essentials Plus | IASME-accredited certifier | Engagement letter | Q4 2026 |
| EU AI Act Annex III conformity | Bird & Bird Vienna AI practice | Scoping | Q1 2027 |
Found something? Email security@kural.tech with PGP key fingerprint listed at kural.tech/.well-known/security.txt. We respond within 24 hours, fix within agreed SLAs, and publish a CVE if applicable. Bug-bounty programme on Intigriti launches Q3 2026 with a €15k initial pool.
Email security@kural.tech or privacy@kural.tech for DPA / sub-processor questions. We respond within 5 business days.