Back to portfolio
Narrate Compliance · Build notes

Compliance, written as software

A multi-standard ISO compliance platform that takes an organisation from gap assessment to certification readiness — with AI throughout, and a dedicated auditor toolkit that's actually nice to use.

~12 min readNext.js 14 · Supabase · OpenAI / Anthropic / Azure · StripeProduction · paying customers

What this is

§01

Narrate is Tom's commercial ISO compliance SaaS. It is the largest project on this portfolio by a wide margin — 36 numbered modules, 50+ migration files, four distinct user-type experiences, and 19 supported standards with full cross-mapping between them.

Take an organisation from gap assessment to certification readiness, in one place, with AI on every surface that benefits from it — and an auditor experience that doesn't make external auditors hate you by week two.
Audience
Mid-market and enterprise companies pursuing ISO certification (27001, 42001, 9001, SOC 2 etc.), consultancies managing multiple client engagements, and the external auditors who eventually audit both.
Business model
Three tiers — Starter £399/mo, Growth £999/mo (or £9,990/yr), Scale on enquiry. Annual billing on Growth saves ~£1,998/yr. Multi-currency Stripe checkout (GBP base; USD, EUR, CAD, AUD, JPY, CHF, SGD, INR).
Stack
Next.js 14 (App Router) + TypeScript + Tailwind + Supabase (Postgres / Auth / Storage) + OpenAI (GPT-4o, GPT-4o-mini, Whisper) + Anthropic Claude + Azure OpenAI + Stripe + Resend + Vercel.
Position
Most compliance tools are either generic GRC platforms (broad, shallow) or single-standard tools (deep, narrow). Narrate is built around multi-standard cross-mapping — implementing one standard automatically credits you for overlapping controls in every other active standard.

Nineteen standards, cross-mapped

§02

The product covers nineteen separate compliance regimes, each with its own control catalogue, 100–200+ document templates, and assessment workflow. The interesting bit isn't the count — it's what happens between them.

ISO 42001AI Management SystemFull
ISO 27001Information Security ManagementFull
ISO 9001Quality ManagementFull
ISO 27701Privacy Information ManagementFull
ISO 14001Environmental ManagementFull
ISO 45001Occupational Health & SafetyFull
ISO 22301Business ContinuityFull
ISO 31000Risk ManagementFull
ISO 22000Food SafetyFull
ISO 50001Energy ManagementFull
SOC 2Service Organisation ControlFull
EU AI ActEuropean AI RegulationFull
GDPREU Data ProtectionFull
Cyber EssentialsUK Cyber Security CertFull
PCI DSSPayment Card IndustryFull
HIPAAUS Healthcare DataFull
DORADigital Operational ResilienceFull
TISAXAutomotive Information SecurityFull
NIST CSF 2.0Cybersecurity FrameworkFull

The cross-mapping engine

Most controls don't exist in isolation. ISO 27001 A.5.1 (Information Security Policies) maps to NIST CSF GV.PO-01, SOC 2 CC1.1, TISAX 1.1.1, and several others. Implementing it once and re-typing the evidence for every standard is the kind of busywork that drives compliance teams to quit.

The cross-mapping engine handles this automatically:

  • Cross-standard mapping badges — controls show 'Also in: ISO 27001 · 2' with hover-listing of mapped IDs.
  • Bidirectional auto-alignment — marking a control as Implemented in one standard credits mapped controls in every other active standard, with an 'Auto-aligned via [Standard] [Control]' badge so the audit trail is clean.
  • Transitive mapping — TISAX → SOC 2 through shared ISO 27001 controls, via getAllLinkedControls() which resolves the full transitive graph rather than just direct edges.
  • Cross-standard summary banner — 'X of Y controls already addressed by your ISO 27001 implementation' at the top of each standard's align page.
  • 'Show only uncovered controls' filter — hide the auto-aligned ones and focus on what still needs hands.
  • Override / opt-out — any auto-alignment can be manually overridden if the user disagrees with the mapping.

The mapping data is static and hand-verified against authoritative sources (VDA ISA 6.0, NIST crosswalks, ISO Annex SL alignments). It lives in lib/cross-standard-mappings.ts so it can be audited and updated without a migration.

Four user types, four experiences

§03

The product serves four genuinely distinct audiences with different information needs, permission boundaries, and even login portals. Each gets a tailored experience rather than a flag-gated version of the same one.

User type
Company users

Direct SaaS customers managing their own compliance. Scoped by company_id. Get the full module set: align, toolkit, evidence, tasks, CAPA, risk register, AI governance, training, calendar, reports, settings. Role-gated within company (Owner / Admin / Member).

User type
Consultants

Multi-client practitioners with a dedicated dashboard showing a client list with pipeline stages and health scores. Switch into any client to get the full company experience for that client, scoped by client_id. White-label branding, AI usage limits bypassed.

User type
Auditors

External audit firms invited via email with a 30-day access window. Dedicated login portal (/auditor/login). Get a different set of 11 modules optimised for auditing — read-only data plus private scratchpad, RFI workflow, temporal vault, smart sampler, and the audit pack export. See §05.

User type
Client portal users

External client contacts invited by consultants. Magic-link login to a scoped portal at /client-portal/[clientId] with access to training and compliance progress for their organisation. Also where they approve consultant AI access requests.

The dual-scope data model

Underneath, every user-data table supports both company_id (for direct customers) and client_id (for consultant-managed organisations). Row-Level Security policies enforce both. Every company-user feature has a consultant equivalent at /consultant/client/[id]/...; every auditor module has both /auditor/company/[id]/ and /auditor/client/[id]/ variants. It doubles the route count but the data layer stays single-sourced.

The module catalogue

§04

Thirty-six numbered modules, condensed into the families they actually fall into. Each company-user module also has a consultant mirror under /consultant/client/[id]/.

Assessment & evidence
  • Align — control-by-control gap assessment with cross-standard badges and auto-alignment
  • Toolkit — 100–200+ documents per standard with status workflow, rich editor, PDF/Word/XLSX export
  • Evidence — drag-drop upload, AI analysis (GPT-4o vision + OCR), mapping matrix export
  • Evidence Harvester — GitHub, Jira, Confluence, SharePoint, webhook integrations
  • Knowledge Base — searchable doc library with versioning and AI control mapping
  • Governance Recorder — Whisper-transcribed meetings auto-mapped to ISO 27001 Clause 9.3
Workflow
  • Tasks — 3-step wizard, maker/checker verification, share tokens for external assignees
  • CAPA Register — full NCR lifecycle, 5 Whys / Fishbone root cause analysis
  • Risk Register — 5×5 matrix, inherent + residual scoring, treatment plans
  • AI Governance — system inventory with DPIA / Bias / Security assessments and EU AI Act compliance tracking
  • Compliance Calendar — recurring events, document review cycles, AI system review dates
  • Internal Audit — planning, scheduling, finding documentation
  • SoA — ISO 27001 6.1.3 Statement of Applicability
  • Readiness — pre-audit self-assessment with category scoring
Reporting & training
  • Reports — 7 report types with branded PDF generation and AI executive summaries
  • Training Portal — interactive course modules per standard with assignment tracking
  • Policy Acknowledgments — magic-link sign-off for external users
  • Audit Logs — immutable, exportable, powers the auditor Temporal Vault
  • Narrative Generator — AI-powered control narrative generation with chat refinement
  • Trust Centre — public compliance posture sharing at a custom slug
Platform
  • Multi-Standard Unified Framework — combined score + cross-mapping insights across all active standards
  • Compliance Autopilot — drift detection cron, auto-task creation
  • Bring Your Own AI — OpenAI / Azure / Anthropic / custom endpoint with encrypted credentials
  • Privacy Firewall — Standard / Redacted / Disabled modes
  • External API — key-based auth at /api/v1/
  • Consultant Branding — white-label colours, logo, portal title
  • Settings & team — role-based access control, invitation flow

The Auditor Toolkit

§05

Most compliance tools treat auditors as a footnote — read-only access bolted onto the main UI, maybe a signed-URL evidence export. Narrate's auditor portal is a separate experience built for external audit firms with eleven dedicated modules.

Why this matters commercially

When a Big Four audit firm walks into a Narrate-using customer, they don't need a tour of the customer's workspace. They open the auditor portal, see the eleven modules they need, work through them, and leave with a signed audit pack. The customer's subscription value goes up because their auditor wants them on Narrate. It's the demand-side moat.

The eleven modules

  1. 01
    Control Status (Align)

    Read-only view of the customer's gap-assessment progress with per-control inline notes.

  2. 02
    Documents (Toolkit)

    Read-only access to all policies, procedures, records, and forms.

  3. 03
    Evidence

    Browse evidence files with 24-hour signed download URLs scoped to the auditor's session.

  4. 04
    Audit Trail

    Immutable audit log access for the entire organisation — read-only but fully filterable.

  5. 05
    RFI Requests

    Create Requests for Information linked to specific controls, set priority and due dates, review responses. Email notifications to company on creation; back the other way on publish.

  6. 06
    Private Scratchpad & Findings

    Private notes the auditor can take while reviewing — strict RLS means only the creating auditor sees them. 'Publish Finding' converts a note into a Major NCR / Minor NCR / Observation / OFI in the customer's CAPA register with source='external_audit'.

  7. 07
    Temporal Vault

    Point-in-time document viewing — reconstruct what any document looked like on any past date using the audit_logs old_values / new_values JSONB. Quick presets for 1 / 3 / 6 months ago. Yellow 'historical snapshot' banner so the auditor knows what they're reading.

  8. 08
    Smart Sampler

    Random sampling from evidence, documents, tasks, audit logs, NCRs, risks. Uses PostgreSQL's ORDER BY RANDOM() LIMIT N for genuine random selection with session history tracking — auditors can show their sampling methodology to a peer reviewer.

  9. 09
    Traceability Visualizer

    Three-column Risk → Control → Evidence chain view. Pick a control, see linked risks, linked policies, linked evidence, linked knowledge documents. Cross-references the entire data layer.

  10. 10
    Readiness Heatmap

    CSS grid coloured by evidence freshness — green (<3mo), yellow (3–6mo), red (none or >6mo). Per-clause / per-section. Click a cell for a detail popover.

  11. 11
    Audit Pack Export

    ZIP with all evidence files + XLSX mapping matrix + index.html table of contents + per-control _summary.txt. Optional filters for findings, RFIs, control filter, heatmap summary. Export logged to auditor_activity_logs with file count and checksum.

Every auditor module exists in both /auditor/company/[id]/ and /auditor/client/[id]/ flavours — so auditors of consultant-managed clients get the same experience. Shared helpers (verifyAccess(), logActivity()) reduce the boilerplate of the duplication.

AI as a surface, not a chatbot

§06

The instinct with AI in B2B SaaS is to bolt a chatbot in the corner and call it a feature. Narrate has AI in twelve distinct surfaces, each doing something specific.

Evidence Analysis
GPT-4o vision + OCR over uploaded evidence files. Returns findings, recommendations, confidence score, recency check, control-fit assessment. Per-operation usage-metered.
AI Compliance Copilot
Per-control sparkle button. Returns urgency level, 3–5 specific action steps (each typed: evidence / document / process / task), suggested evidence document types, optional policy hint. Rendered as a collapsible in-card panel, not a modal — keeps the workflow in place.
AI Audit Coach (deterministic)
Dashboard widget surfacing top 3 red-status controls ordered by priority and risk score. No AI call — just reads already-loaded audit data. The 'AI Suggestions' button deep-links to the actual Copilot for that control.
Gap Analysis
Full org-wide gap analysis. NLP summary of strengths, weaknesses, and priority recommendations.
Document AI
Toolkit document rewriting and improvement suggestions, with a suggestion-application workflow.
Narrator (assistant)
Conversational AI for ad-hoc compliance queries grounded in company data. Respects the privacy firewall.
Knowledge Analysis
AI analysis of uploaded knowledge documents with automatic control mapping suggestions.
Cross-Standard Mapping AI
Map controls between standards (e.g. ISO 42001 → ISO 27001), identify overlapping requirements. Used to seed the static mappings file and for one-off explorations.
AI Risk Assessment
Structured DPIA / Bias & Fairness / Security questionnaires for AI systems. Scoring is calibrated; recommendations can be promoted directly to the Risk Register.
Narrative Generator
Generate control narratives from evidence, tasks, timeline. Chat interface for iterative refinement.
Compliance Autopilot
Cron job that detects compliance drift and auto-creates tasks. Stale evidence on green controls, unevidenced gaps on red controls, dedup against existing open tasks, summary email to admin. Configurable per company via feature_flags.
Report Generation
GPT-4o-mini executive narrative summaries baked into the 7 branded PDF report types.

Bring Your Own AI

§07

Growth and Scale customers can configure their own AI provider instead of using Narrate's default OpenAI. Enterprises that already have approved AI vendors don't need to add a new one to their procurement list.

Supported providers

  • OpenAI (direct API)
  • Azure OpenAI (for orgs whose data residency rules require Azure-hosted models)
  • Anthropic Claude
  • Any OpenAI-compatible endpoint — covers local LLMs, regional providers, and emerging models

The factory pattern

Every AI call site in the application routes through a single factory function, getAIClient() in lib/ai/get-client.ts. Twelve call sites total. The resolution order:

  1. Privacy firewall check — if disabled_high_risk mode, throw
  2. Consultant approval check — for consultant-managed clients, AI is off by default until the client approves via magic link
  3. Tier check — Starter doesn't get BYOAI
  4. Custom provider config — if set, instantiate that provider
  5. Fall through to Narrate's default OpenAI key — the catch-all

Credentials are encrypted at rest using AES-256-GCM. Test connection in the settings UI before saving; revert button to roll back. Only admin-role users can configure provider settings.

Consultant approval workflow

A subtle bit: for consultant-managed clients, AI features are off by default. The consultant must explicitly request AI access via the client's settings page; the client receives a magic-link email and approves or rejects via /client-portal/ai-approval. An amber banner shows on the client overview page until approved. Reports generate without their AI narrative section when AI is disabled — the rest of the report still works.

The privacy firewall

§08

AI features can leak data. Compliance customers care about this more than anyone. The privacy firewall is a three-mode gate that sits between every AI call site and the actual upstream call.

Mode
Standard

All AI features work normally. Data goes to whichever provider the customer's BYOAI config (or Narrate default) points at.

Mode
Redacted

A PII regex engine scrubs emails, credit cards, SSNs, IP addresses, and phone numbers from any text before it leaves the server. The AI sees patterns and structure but not identities. The redactor lives in lib/privacy/redactor.ts.

Mode
Disabled (High Risk)

All AI features are blocked entirely. The frontend components check via the usePrivacyMode() hook and render a disabled state. The server-side applyFirewall() in lib/privacy/apply-firewall.ts enforces it again — defence in depth.

Frontend and server both enforce the firewall, so a misbehaving client cannot bypass the customer's privacy setting. Settings live at /settings/privacy.

The data model

§09

PostgreSQL via Supabase with Row-Level Security on every table. 50+ migration files managing the schema's evolution. The interesting choices:

Dual-scope (company_id + client_id) on every user-data table

Each row belongs to either a direct company or a consultant-managed client. RLS enforces both. The pattern doubles every route under /consultant/client/[id]/ but the data layer stays single-sourced. Tested in the Auditor Toolkit too — every module has /auditor/company/[id]/ and /auditor/client/[id]/ variants. Shared helpers in lib/auditor/ keep the API route duplication manageable.

Generated columns for computed risk scores

PostgreSQL GENERATED ALWAYS AS ... STORED for inherent_risk_level and residual_risk_level on the risk register. The score is always consistent with the underlying likelihood × impact, can't drift if a column is updated, and is index-able. The application code never has to remember to recompute.

JSONB everywhere there's flexibility

behavioral_controls on AI systems, linked_controls on AI systems (an array of cross-standard mappings), feature_flags on companies (subscription tier overrides plus runtime settings like autopilot config), corrective_action_details on NCRs, root_cause_analysis on NCRs, treatment_actions on risks, old_values / new_values on audit_logs. GIN indexes where queried. The trade-off — schema enforcement moves to TypeScript — is worth it for these specific cases.

Control linkage by text ID, not foreign key

Controls are referenced by their text identifier ('A.5.2', '7.5.1') rather than a numeric foreign key. This is a deliberate choice — it lets us re-seed the control catalogue without rewriting every link, and matches how compliance professionals actually talk about controls. Costs us referential integrity checks; gains us flexibility and clarity.

Magic-link tokens for external participants

Policy acknowledgments, AI approval requests, team invites, auditor invitations, public task views — all use single-use secure tokens with expiry. The external participant never needs a Narrate account. Implementations live in app/acknowledge/[token]/, /client-portal/ai-approval/, /tasks/[token]/view/, /auditor/accept-invite/.

audit_logs powers the Temporal Vault

Every change captures old_values and new_values as JSONB. Beyond standard compliance evidence, this is what makes the auditor Temporal Vault possible — point-in-time reconstruction is just replaying the audit log backward to any past date. The same table that handles 'who changed what' also handles 'show me what it looked like in October'.

Paywall security — migration 029

Same lesson as Dad & Baby: profiles.is_pro and equivalent paywall fields are now writable only by service-role webhook handlers. Pre-029, an authenticated user could PATCH their own subscription tier to Scale. Lock it down at the database, not the application. (Webhook flow: Stripe event → /api/stripe/webhook → service-role write → next request reads fresh state.)

Compliance Autopilot

§10

One feature worth pulling out for its own treatment: an opt-in cron job that watches for compliance drift and creates tasks before a human notices.

What it does

On a schedule, for every company with autopilot_enabled: true:

  1. Load all audit_data sections across active standards
  2. Group evidence_files by control_id with their latest created_at
  3. Stale evidence: green controls whose latest evidence is older than the configured threshold (default 90 days) → create a task
  4. Unevidenced gaps: red controls with zero evidence → create a task
  5. Dedup — skip controls that already have an open task
  6. Insert task_assignments rows with [Autopilot] prefix, assigned to admin, due in 30 days
  7. Email summary to admin if anything was created

Settings are stored on companies.feature_flags JSONB — no schema migration needed. A "Run Now" button on the settings page bypasses the schedule for ad-hoc scans. The dashboard widget surfaces unresolved autopilot tasks separately from human-created ones so the noise is contained.

Pricing & where it goes next

§11

Three direct-sales tiers plus a consultant partner programme. Stripe handles checkout, billing, and the portal. Multi-currency: GBP base, with USD / EUR / CAD / AUD / JPY / CHF / SGD / INR converted at checkout based on IP detection.

Starter
£399 / mo
Standards
2
Seats
4
Storage
10 GB
AI credits
250 credits / mo
BYOAI
Growth
£999 / mo · £9,990 / yr
Standards
5
Seats
10
Storage
50 GB
AI credits
1,000 credits / mo
BYOAI
Yes
Scale
Contact sales
Standards
Unlimited
Seats
Unlimited
Storage
500 GB
AI credits
Unlimited
BYOAI
Yes + SSO / SAML

What's shipped vs what's next

Shipped
  • All 36 numbered modules across company / consultant / auditor / client portal
  • 19 standards with comprehensive cross-mapping
  • 12 AI surfaces routing through a single factory
  • 11-module Auditor Toolkit
  • Bring Your Own AI with 4 provider types + consultant approval workflow
  • Three-mode Privacy Firewall
  • Compliance Autopilot drift detection
  • Magic-link auth for external participants
  • Stripe multi-currency checkout + Resend transactional emails
  • Branded PDF reports (7 types) with AI executive summaries
  • External API at /api/v1/ with key-based auth
Next
  • SSO / SAML for Scale tier customers
  • More external integrations (ServiceNow, Asana)
  • Public Trust Centre customisation
  • Per-standard advanced training authoring
  • More AI providers + cost dashboards
  • Mobile companion app for evidence capture
  • Customer-customisable cross-standard mappings