Skip to content

🔬 ConformEdge — Technical Whitepaper

ConformEdge is built as a modern, full-stack SaaS application using Next.js 15 with the App Router pattern. The architecture follows a server-first approach — Server Components by default, with client-side interactivity only where required (forms, real-time UI, interactive charts).

All data mutations flow through server actions, providing a unified security boundary where authentication, authorisation, and audit logging are enforced consistently. There is no separate REST API layer for internal operations; the server action pattern eliminates an entire class of API surface area vulnerabilities.

┌─────────────────────────────────────────────────────┐
│ Client Browser │
│ Next.js App Router (React Server Components + CSR) │
└──────────────────────┬──────────────────────────────┘
┌──────────────────────▼──────────────────────────────┐
│ Next.js Server │
│ ┌──────────────┐ ┌───────────────┐ ┌───────────┐ │
│ │Server Actions│ │ API Routes │ │ Middleware │ │
│ │ (mutations) │ │(webhooks/cron)│ │ (Clerk) │ │
│ └──────┬───────┘ └───────┬───────┘ └───────────┘ │
│ │ │ │
│ ┌──────▼──────────────────▼───────┐ │
│ │ Service Layer │ │
│ │ Auth Context │ Audit Logger │ │
│ │ AI Engine │ IMS Engine │ │
│ │ Gap Detection│ Notifications │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ┌──────────────▼──────────────────┐ │
│ │ Prisma 7 ORM (adapter-pg) │ │
│ └──────────────┬──────────────────┘ │
└─────────────────┼────────────────────────────────────┘
┌─────────────▼────────────┐
│ PostgreSQL Database │
│ (25+ models, UUIDs) │
└──────────────────────────┘
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Clerk Auth │ │ Anthropic API │ │ Google Cloud │
│ (multi-tenant │ │ (Claude Haiku) │ │ Vision OCR │
│ orgs + RBAC) │ │ │ │ │
└────────────────┘ └────────────────┘ └────────────────┘
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Cloudflare R2 │ │ Resend │ │ Paystack │
│ (file storage) │ │ (email) │ │ (payments) │
└────────────────┘ └────────────────┘ └────────────────┘

LayerTechnologyVersionPurpose
FrameworkNext.js15Full-stack React framework (App Router)
LanguageTypeScript5.xType safety across the entire codebase
StylingTailwind CSSv4Utility-first CSS framework
UI Componentsshadcn/uinew-yorkAccessible, composable component library
AuthenticationClerkLatestMulti-tenant organisations, RBAC, webhooks
DatabasePostgreSQL16Primary data store
ORMPrisma7Type-safe database access with @prisma/adapter-pg
AI ClassificationAnthropic ClaudeHaikuDocument-to-clause mapping
OCRGoogle Cloud VisionLatestScanned document text extraction
File StorageCloudflare R2-S3-compatible object storage (zero egress)
PDF Generation@react-pdf/rendererLatestAudit pack and report PDFs
ChartsRechartsLatestDashboard visualisations (9 chart types)
EmailResendLatestTransactional email delivery
PaymentsPaystackLatestZAR payment processing
HostingHetzner VPS-Production deployment
CI/CDGitHub Actions-Automated deployment pipeline
Process ManagerPM2LatestNode.js process management

The AI classification pipeline processes uploaded documents through a multi-stage workflow:

Document Upload → Text Extraction → AI Classification → Gap Update
│ │ │ │
▼ ▼ ▼ ▼
Cloudflare R2 PDF/DOCX parser Claude Haiku Coverage %
(file stored) or OCR fallback (clause mapping) recalculated

Stage 1: Upload & Storage Documents are uploaded via an API route to Cloudflare R2, stored under organisation-scoped keys ({orgId}/{timestamp}-{random}.{ext}). The upload route validates file type, size, and authentication.

Stage 2: Text Extraction

  • Native PDFs and DOCX files: Text is extracted programmatically
  • Scanned documents and images: Google Cloud Vision OCR extracts text with layout preservation
  • The system automatically detects whether OCR is needed based on text extraction quality

Stage 3: AI Classification The extracted text is sent to Anthropic’s Claude Haiku model with a structured prompt that includes:

  • The document text (truncated to fit context window)
  • The full clause hierarchy for the organisation’s active standards
  • Instructions to return clause mappings with confidence scores (0.0-1.0)

The model returns a JSON array of clause matches, each containing:

{
"clauseId": "uuid",
"standardId": "uuid",
"confidence": 0.87,
"reasoning": "Document contains quality policy commitments matching Clause 5.2"
}

Stage 4: Gap Update Classification results are persisted atomically using db.$transaction() (delete existing + create new). The gap analysis engine immediately recalculates coverage percentages. If coverage for any clause drops below 25%, notifications are triggered.

  • High confidence (≥ 0.80): Direct match to clause requirements
  • Medium confidence (0.50-0.79): Partial match or supporting evidence
  • Low confidence (< 0.50): Tangential relevance, flagged for review

Cross-standard classification applies a 90% confidence decay (capped at 0.85) to ensure primary standard matches rank higher.

Bulk classification processes multiple documents with:

  • Batching: 3 concurrent API requests to respect Anthropic rate limits
  • Progress tracking: Real-time feedback to the user interface
  • Error isolation: Individual document failures do not block the batch
  • Fire-and-forget pattern with error surfacing via toast notifications

Organisations maintaining multiple ISO standards face exponential complexity. ISO 9001 (Quality), ISO 14001 (Environmental), and ISO 45001 (OH&S) share significant overlapping requirements — leadership commitment, risk management, document control, internal audit, management review — but the specific clause numbering differs across standards.

Manually tracking these overlaps across 7 standards with ~441 cross-references is impractical.

ConformEdge implements a Union-Find (disjoint-set) data structure to group equivalent clauses across standards into equivalence classes:

Standard A, Clause 4.1 ←→ Standard B, Clause 4.1 ←→ Standard C, Clause 4.1
└──────────── Equivalence Group ────────────┘

Algorithm:

  1. Load all cross-reference mappings from the database (~441 records)
  2. Build a Union-Find forest where each clause is a node
  3. For each cross-reference, union the two clauses
  4. Find operations with path compression identify equivalence groups
  5. Each group represents a set of clauses that share requirements

Benefits:

  • Transitive closure: If A↔B and B↔C, the engine automatically knows A↔C
  • O(α(n)) amortised time per operation (effectively constant)
  • Deterministic grouping regardless of insertion order

The IMS engine calculates an integration score (0-100%) based on:

  • Document coverage overlap: How many equivalence groups have documents classified across multiple standards
  • Gap symmetry: Whether gaps exist consistently or inconsistently across equivalent clauses
  • CAPA cross-linking: Whether corrective actions reference multiple standards

A high integration score indicates a well-functioning IMS where standards reinforce each other.

When a document is classified or a gap is closed for one clause, the engine:

  1. Identifies the equivalence group for that clause
  2. Recalculates coverage for all equivalent clauses across standards
  3. Generates cross-standard suggestions (e.g., “This document also satisfies ISO 14001 Clause 7.5”)
  4. Updates gap analysis dashboards in real time

This cascade effect means a single document upload can improve compliance scores across multiple standards simultaneously.

The engine generates a consolidated matrix showing:

  • All equivalence groups with their member clauses
  • Current coverage status per group
  • Documents satisfying each group
  • Outstanding gaps requiring attention

This matrix is invaluable for auditors conducting integrated management system audits.


Clerk Integration:

  • All authentication flows (sign-up, sign-in, MFA, SSO) are handled by Clerk
  • Webhook endpoint (/api/webhooks/clerk) synchronises users and organisations to the local database
  • Middleware (src/middleware.ts) protects all dashboard routes

RBAC Enforcement: Five roles with hierarchical permissions:

RoleViewCreateEditDeleteAdmin
OWNER
ADMIN
MANAGER
AUDITOR✅*
VIEWER

*Auditors can create assessments and findings only.

RBAC is enforced at the server action level via getAuthContext(), which is wrapped in React cache() for per-request deduplication. Every mutation checks canEdit, canCreate, or canDelete before proceeding.

Multi-tenant data isolation is enforced at the database query level:

  • Every query includes an organizationId filter
  • The organisation ID is derived from the authenticated Clerk session (not from user input)
  • R2 storage keys are prefixed with the organisation ID
  • Download routes verify the first key segment matches the authenticated organisation

All mutations are logged via logAuditEvent() in src/lib/audit.ts:

  • Actor (user ID, name, role)
  • Action (CREATE, UPDATE, DELETE, APPROVE, REJECT, etc.)
  • Entity type and ID
  • Timestamp
  • IP address (where available)
  • Organisation context

The audit trail is immutable and queryable via the Audit Trail dashboard page.

External access (client portal, subcontractor portal) uses token-based authentication:

  • Tokens are generated using cryptographically secure random bytes
  • The raw token is shown to the creator exactly once
  • Only the SHA-256 hash is stored in the database
  • Validation compares the hash of the presented token against the stored hash
  • Tokens have configurable expiry dates
  • Access is logged with view counts and timestamps
  • Path traversal guards validate that resolved file paths stay within allowed directories
  • R2 download route uses presigned URLs with authentication gating
  • Organisation-scoped storage keys prevent cross-tenant file access
  • Legacy file paths (/public/uploads/) are supported with the same security guards

ConformEdge leverages Clerk’s organisation feature for multi-tenancy:

Clerk Organisation ←→ ConformEdge Organisation (1:1)
│ │
├── Members ├── Documents
├── Roles ├── Assessments
└── Invitations ├── CAPAs
├── Checklists
└── Settings
  • Each Clerk organisation maps to exactly one ConformEdge organisation
  • Users can belong to multiple organisations (critical for consultants)
  • Switching organisations in Clerk automatically scopes all ConformEdge queries
  • Organisation settings (including feature flags like auto-classify) are stored in a JSON column

ISO consulting firms operate as follows:

  1. The consultant creates a Clerk organisation for each client
  2. The consultant user is added as OWNER or ADMIN to each client organisation
  3. Client users are invited to their own organisation with appropriate roles
  4. The consultant switches between organisations to manage each client
  5. Cross-client reporting is available at the consultant level

This architecture provides:

  • Full data isolation between clients
  • Independent billing per client organisation
  • Role separation — the consultant sees everything, client staff see their own data
  • Scalability — no limit on the number of client organisations

The database comprises 25+ Prisma models with the following characteristics:

  • UUID primary keys throughout (no sequential IDs)
  • Snake_case naming via @map/@@map decorators
  • Soft references where appropriate (SetNull on delete for lineage tracking)
  • JSON columns for flexible configuration (settings, field configs, responses)
ModelPurposeKey Relationships
OrganizationTenant rootHas many of all entities
UserAuthenticated usersBelongs to organizations via membership
ISOStandard7 seeded standardsHas many clauses
StandardClause49 top-level + 187 sub-clausesBelongs to standard, has cross-references
DocumentCompliance documentsHas classifications, versions
DocumentClassificationAI clause mappingsLinks document to clause with confidence
AssessmentInternal auditsHas findings, linked to standard
AssessmentFindingAudit findingsLinked to clause, may generate CAPA
CorrectiveActionCAPAsCross-standard via junction table
CapaStandardClauseCross-standard CAPA linksJunction: CAPA ↔ Clause
ChecklistTemplateReusable templatesHas items with field types
ComplianceChecklistActive checklistsFrom template, has items
ChecklistItemIndividual itemsField type, config, response (JSON)
AuditPackGenerated packsCompiled from multiple entities
SubcontractorExternal companiesHas certifications
SubcontractorCertificationCertificatesStatus: PENDING_REVIEW/APPROVED/REJECTED
ApprovalWorkflowTemplateApproval chainsHas steps (sequential)
ApprovalRequestActive approvalsFor a document, has steps
ApprovalStepIndividual approvalsReviewer, decision, comments
ShareLinkExternal access tokensHashed token, expiry, access log
ShareLinkAccessAccess audit logToken, timestamp, IP
NotificationIn-app + email alerts13 types, read/unread status
AuditEventImmutable audit trailActor, action, entity, timestamp

7 standards are seeded with comprehensive clause hierarchies:

StandardTop-Level ClausesSub-ClausesCross-References
ISO 9001:201510~40~80
ISO 14001:201510~30~70
ISO 45001:201810~30~70
ISO 27001:202210~25~60
ISO 22301:201910~20~50
ISO 37001:201610~20~55
ISO 39001:201210~22~56
Total49~187~441

Seed data is maintained in prisma/seed-data/ with individual files per standard.

Performance-critical queries are supported by targeted indexes:

  • @@index([isRecurring, isPaused, nextDueDate]) on ChecklistTemplate for cron queries
  • Organisation ID indexes on all tenant-scoped tables
  • Composite indexes on frequently filtered columns (status, type, date ranges)

A scheduled cron endpoint (/api/cron/check-expiries) handles time-based automation — this is the technical foundation of ConformEdge’s penalty prevention capability. Every deadline, every expiry, every upcoming assessment is monitored automatically so that nothing slips through the cracks:

TaskTriggerAction
Document expiry30/7/1 days before expirySend notification to document owner
Assessment overduePast scheduled dateSend notification to assessor + managers
Assessment upcoming7/1 days beforeSend reminder to assessor
Share link expiryPast expiry dateMark ACTIVE → EXPIRED
Recurring checklistsnextDueDate ≤ nowGenerate checklist, advance nextDueDate, notify assignee
CAPA escalation7 days overdueBump priority, notify managers
Checklist due dates7/1 days beforeSend reminder to assignee

Clerk webhooks (/api/webhooks/clerk) synchronise:

  • User creation, update, and deletion
  • Organisation creation, update, and deletion
  • Organisation membership changes (role assignment)

The webhook handler validates the Svix signature before processing.

File operations use Cloudflare R2 via S3-compatible SDK:

  • Upload: POST /api/upload → Multipart upload to R2
  • Download: GET /api/download/[...key] → Presigned URL redirect
  • Key format: {orgId}/{timestamp}-{random}.{ext}
  • Discrimination: isR2Key() utility distinguishes R2 keys from legacy /uploads/ paths

Resend handles all transactional email:

  • Approval request notifications
  • Assessment reminders
  • CAPA escalation alerts
  • Audit pack delivery
  • Share link invitations
  • Subcontractor portal invitations

The application runs on a single Hetzner VPS managed by PM2:

  • Max memory restart: 768 MB per process
  • Exponential backoff: 1,000 ms base delay on crash recovery
  • Health check: GitHub Actions deployment verifies endpoint availability
  • Prisma 7 with @prisma/adapter-pg for connection pooling (max 5 connections)
  • Global singleton pattern prevents connection exhaustion in development
  • UUID primary keys provide even index distribution
  • Targeted indexes on high-query columns
  • Individual classification: 2-5 seconds per document
  • Bulk classification: 3 concurrent requests, ~20 documents per minute
  • OCR fallback: 3-8 seconds additional for scanned documents
  • Classification results cached in database (re-classify on demand)

The architecture supports horizontal scaling through:

  1. Database: Migration to managed PostgreSQL (e.g., Supabase, Neon) for connection pooling and read replicas
  2. Application: PM2 cluster mode or containerised deployment (Dockerfile included)
  3. Storage: Cloudflare R2 scales automatically with zero configuration
  4. AI: Anthropic API scales with API key limits (upgradeable)
  5. CDN: Next.js static assets can be served via Cloudflare CDN

  • Primary server: Hetzner VPS (European data centre, SA-accessible)
  • File storage: Cloudflare R2 (global edge network)
  • Authentication: Clerk (US-hosted, SOC 2 Type II certified)
  • AI processing: Anthropic API (US-hosted, SOC 2 certified)
  • All document content is processed transiently for AI classification — no document content is stored by Anthropic
  • File storage in Cloudflare R2 with organisation-scoped access controls
  • Database backups configured per hosting provider standards
  • Audit trail provides full accountability for all data access and mutations

For South African customers, ConformEdge supports POPIA (Protection of Personal Information Act) compliance through:

  • Purpose limitation: Data is collected and processed solely for compliance management
  • Data minimisation: Only necessary information is stored
  • Security safeguards: Encryption in transit (TLS), access controls, audit logging
  • Right to access: Audit trail provides complete data access history
  • Data export: Reports and data can be exported in CSV and PDF formats

The architecture supports future deployment to SA-based cloud providers should data residency requirements mandate it. The containerised deployment model (Docker) enables infrastructure portability.


ComponentPath
AI Classificationsrc/lib/ai/classify-document.ts
OCR Extractionsrc/lib/ai/ocr-extract.ts
IMS Enginesrc/lib/ims/ims-engine.ts
Cross-Standard Suggestionssrc/lib/ims/cross-standard-suggestions.ts
Gap Detectionsrc/lib/gap-detection.ts
Auth Contextsrc/lib/auth.ts (cached)
Audit Loggersrc/lib/audit.ts
R2 Storagesrc/lib/r2.ts, src/lib/r2-utils.ts
Share Token Utilssrc/lib/share-tokens.ts
Recurrence Calculatorsrc/lib/recurrence.ts
Assessment Statussrc/lib/assessment-status.ts
Database Singletonsrc/lib/db.ts
Prisma Schemaprisma/schema.prisma
Clerk Middlewaresrc/middleware.ts

ConformEdge Technical Whitepaper v1.0 — ISU Technologies (Pty) Ltd