Security whitepaper

Aegis by CLAB — Security & Architecture Whitepaper

How Aegis protects data, controls access, and produces evidence. Every claim below maps to code or schema in the Aegis repository, with file references inline so a reviewer can verify each statement directly.

AudienceEnterprise and government procurement, security, and compliance reviewers.
ProductAegis by CLAB — a multi-tenant AI governance gateway.
Live deploymentclab.stellarchd.com
Platform.NET 10, SQL Server 2025, IIS on Windows.

A note on language used throughout this document: where we discuss regulatory regimes (SOC 2, ISO 27001, HIPAA, GDPR, DPDP and similar), we describe the architecture as designed to support or intended to help you meet those regimes. Aegis holds no third-party certification or attestation, and this document makes no such claim. See Section 7 and Section 9.

1.Executive summary

Aegis sits between your users and one or more large language models (LLMs). Its core function is to ensure that personally identifiable information never reaches an LLM in cleartext.

The mechanism is a deterministic redaction pipeline. Before any prompt is forwarded to a model — whether a frontier provider, an open model, or the sovereign local model — Aegis detects sensitive spans, replaces each with an opaque placeholder token (for example <<EMAIL_1>>), stores the real value in a session-scoped, encrypted vault, and forwards only the placeholder-bearing text to the model. When the model answers, Aegis re-injects the real values into the response — but only for the verified owner of that session. The model never sees, stores, or learns the underlying personal data.

Around that core, Aegis layers governance (role-based access control, topic firewalls, supervisor approvals, multi-tier quotas), defence-in-depth guards (prompt-injection detection, hallucinated-identifier detection), encryption at rest, and per-request auditing that records what types and how many PII items were handled — never the values themselves.

Key design facts a reviewer should take away:

2.Threat model & design principles

2.1 What we defend against

2.2 Principles

Fail closed. Every gate, when uncertain, denies rather than permits. If the PII detector throws, the orchestrator does not forward the prompt — it returns a DetectorFailure outcome (PiiDetectionStage.cs). If a PII rule times out, the engine logs and re-throws rather than continuing (src/Clab.PiiGuard/Engine/PiiDetectionEngine.cs). If at-rest encryption is enabled but the master key is missing or the wrong length, dependency-injection registration throws at startup rather than silently running unencrypted (src/Clab.Security/SecurityOptions.cs, SpTenantKeyStore decodes the key eagerly in its constructor). A row flagged encrypted whose payload is not valid ciphertext is surfaced as a cryptographic failure, never returned as text (src/Clab.Security/MessageCipher.cs).

Least privilege. Re-injection of real PII values is gated on session ownership: only the (tenantId, userId) that owns a session can have that session's placeholders restored (src/Clab.PiiGuard/Vault/PiiReinjectionService.cs, SessionOwnershipStage). BYOK secrets and decryption keys live in process memory and gitignored configuration, never in the database in usable form.

Defence in depth. PII protection does not rely on a single technique. The redaction pipeline composes deterministic regex/rule packs (one universal pack, ten country/region packs — nine single-country plus an EU-GDPR regional pack — three domain packs, and tenant-custom rules) with an optional transformer NER model, then adds independent guards on the way in (prompt injection) and on the way out (PII-leak and hallucinated-identifier validation of the model's response). A failure or gap in any one layer is backstopped by others.

Stored-procedure-only data access. The entire data-access layer is stored-procedure-based with tenant filtering in each procedure; there is no ORM and no inline SQL. This narrows the attack surface and makes data-locality and isolation work a port rather than a rewrite (docs/strategy/SOVEREIGN-RESIDENCY-DESIGN.md).

3.Data protection: the redaction pipeline

3.1 The guarantee

The single most important property of Aegis: the LLM sees placeholders, not people. Real personal data is removed before forwarding and restored only for the verified owner afterwards.

3.2 Pipeline flow

The orchestrator runs an ordered sequence of stages and writes an append-only audit event per request (best-effort; a failed write is logged and never blocks the request — src/Clab.Pipeline/PipelineOrchestrator.cs, src/Clab.Pipeline/ServiceCollectionExtensions.cs, src/Clab.Data/Repositories/SpAuditLogger.cs). The PII-relevant stages, in order:

  1. Session ownership is claimed/verified.
  2. Access policy firewall (PolicyGuardStage) enforces the tenant's work-hours window, IP-CIDR allow/block lists, and country allow/block lists; when an allow-list is active and the caller's location or IP cannot be determined, it fails closed.
  3. Prompt-injection guard inspects the input.
  4. PII detection + sanitisation (PiiDetectionStage.cs):
    • The detector runs all applicable rule sets. On any detector exception the request is refused (fail closed) — it is never forwarded to a model.
    • The sanitiser (src/Clab.PiiGuard/Engine/PiiSanitizer.cs) walks the detected spans, replaces each with a vault placeholder token, stores the real value in the vault, and produces the sanitised text. From this point on, downstream stages operate only on the sanitised text.
  5. Strict-mode guard (PiiModeGuardStage.cs): if the tenant's policy is block (or redact with specific blocked types), a detected hit refuses the prompt entirely — not even placeholders are forwarded.
  6. Intent resolution, quota gates, topic firewall, semantic cache.
  7. LLM call (LlmCallStage.cs): the sanitised, placeholder-bearing prompt is sent to the routed provider.
  8. Response validation (ResponseValidationStage.cs): the model's answer is checked for leaked PII and hallucinated identifiers before anything is returned.
  9. Re-injection (PiiReinjectionStage.cs): placeholders in the answer are restored to real values — only if the caller owns the session.

3.3 Detection layers

Detection composes several rule sets per tenant (PiiDetectionEngine.ResolveRuleSets):

In total the registry ships one universal pack, ten country/region packs (nine single-country plus the EU-GDPR regional pack), and three domain packs; tenant custom rules are layered on at runtime.

Overlapping detections are resolved deterministically (higher severity, then longer, then earlier span wins), so the same input always sanitises the same way.

Transformer NER augmentation (optional, off by default). A multilingual DistilBERT model (Davlan/distilbert-base-multilingual-cased-ner-hrl) served via ONNX Runtime on CPU can be enabled to catch named entities (PER/ORG/LOC) that pattern rules miss (src/Clab.PiiGuard/Ner/NerEntityRecognizer.cs, NerAugmentedDetector.cs). It is augmentation, not the authoritative detector: NerOptions.Enabled defaults to false, and the deterministic regex/rule engine always runs first and remains authoritative. NER spans are merged in only where they do not overlap a more specific rule hit. Critically, NER can never weaken detection: if the model is disabled, missing, or fails inference, the augmenter logs and falls back to the regex spans — it never throws out of detection. The model is trained on ten languages (ar/de/en/es/fr/it/lv/nl/pt/zh); Hindi is not one of them, so Hindi PII is covered by the deterministic Hindi rule packs rather than the model. Confidence threshold and windowing are configurable (NerOptions.cs). See Section 9 for an honest note on language coverage.

3.4 The vault

Detected values are stored in a session-scoped vault (src/Clab.Data/Repositories/SpPiiVault.cs, stored-procedure backed):

3.5 Audit stores counts, not values

The audit log is append-only and records, per request, the types and counts of PII detected — never the underlying values. The orchestrator builds a Type -> count map (PipelineOrchestrator.Finalise); the logger serialises that map into the PiiCountsJson column and writes nothing else PII-derived (SpAuditLogger.cs). The table itself is documented in db/100_schema.sql as "types and counts only — NEVER values." A reviewer auditing a leaked database backup would find detection statistics, not personal data, in the audit trail.

4.Encryption at rest

4.1 Envelope scheme

Aegis encrypts tenant message content at rest using AES-256-GCM authenticated encryption in an envelope scheme (src/Clab.Security/AesGcmEnvelope.cs):

4.2 Per-tenant DEK, master KEK

The scheme is two-tiered:

4.3 What is encrypted, and the production status

tbMessage.SanitizedContent — the stored conversation content, which already holds placeholder text rather than raw PII — is encrypted at rest. This is enabled in production now (db/320, src/Clab.Security/MessageCipher.cs). Encryption is gated by a master switch (Clab:Security:EncryptMessages); when on, the KEK must decode to exactly 32 bytes or startup fails (fail closed). The same envelope protects BYOK secrets (Section 5.3).

4.4 Honest limit: key rotation and backfill

  • DEK rotation is not yet implemented. There is a single active key per tenant. The schema anticipates rotation (a KeyVersion column and an insert-or-replace upsert that supports re-wrap), but an automated rotation process has not been built.
  • Pre-encryption rows may remain plaintext until backfilled. Encryption was introduced additively: each message row carries an IsEncrypted flag, existing rows default to plaintext, and an in-application backfill job (usp_Message_BackfillPage / usp_Message_SetEncrypted, version-controlled in db/320) converts them. Until that optional backfill runs for a given tenant, some historical rows may still be plaintext.

These limits are restated in Section 9.

5.Data sovereignty, training, and BYOK

5.1 We never train on your data unless you opt in

A tenant's prompts and outputs are never used to train the shared CLAB model unless that tenant explicitly opts in. The opt-in defaults to off.

This is enforced at the data layer, not merely promised in policy. The tbTenant.TrainingOptIn flag defaults to 0, and migration 310 flips the historical default and sets every existing tenant to 0 so nobody contributes without a deliberate, recorded opt-in (db/310_tenant_sovereignty.sql). The shared-corpus export procedure (usp_Corpus_ExportContributed) joins on TrainingOptIn = 1 — opted-out tenants' data is structurally excluded from the export that feeds shared training. Exports return sanitised (placeholder) content only, never raw PII; the Python export utility is python/clab_trainer/export_tenant_corpus.py.

5.2 Private per-tenant adapters

A tenant may train a private adapter on only their own data. The per-tenant corpus export (usp_Corpus_ExportForTenant) returns only that tenant's sanitised messages, and tbTenant.PrivateModelTag records the name of that tenant's own private model. This path does not touch, and is not mixed into, the shared model.

5.3 Bring your own key (BYOK)

A tenant may supply their own upstream provider API key (for example their own Anthropic or OpenAI key). The gateway then uses that key for that tenant's calls to that provider instead of the shared platform key (src/Clab.Gateway/Byok, db/330_byok.sql).

5.4 Sovereign local inference

Aegis ships its own model, CLAB-Aegis (a QLoRA fine-tune of an open base), served via a local Ollama runtime, alongside other open models. When a tenant uses the local model, inference is fully local — nothing leaves the host. Frontier providers remain available via BYOK or shared platform keys for tenants who want them.

6.Access control & governance

7.Auditability & compliance support

Aegis produces evidence designed to support a compliance programme:

The append-only audit trail (Section 3.5) is the foundation: an audit event is written per request (best-effort — a failed write is logged and never blocks the request) recording outcome, provider/model, token and cost figures, latency, and PII type/count metadata — never values.

On regulatory regimes. Aegis is designed to support, and helps you meet the obligations under, regimes such as SOC 2, ISO 27001, HIPAA, GDPR, and India's DPDP — through PII minimisation before third-party processing, encryption at rest, access control, data-subject tooling, and auditability. Aegis does not hold any certification or attestation under these regimes, and nothing in this document should be read as a claim of certification, compliance, or audit attestation. See Section 9.

8.Deployment & residency

Today. Aegis runs as a single-region SaaS on the founder's infrastructure (.NET 10 on IIS / Windows, SQL Server 2025). Each tenant record carries a DataRegion column (db/230_ops.sql), set at creation and validated against a known set of region codes (AE, IN, EU, SG, US, KSA, QA, KW, BH, OM); this tags the tenant's declared residency and is surfaced for transparency.

Roadmap (designed, not yet built). A three-tier residency model — region-pinned SaaS, dedicated database per tenant, and a fully sovereign on-premise appliance where data stays entirely on the client's servers — is designed in docs/strategy/SOVEREIGN-RESIDENCY-DESIGN.md. That document is explicitly marked a design, not a build commitment. The stored-procedure-only DAL makes these tiers a port rather than a rewrite, but they are not shipping features today. There is currently a single region with no high-availability or multi-region deployment.

9.Current limitations & roadmap

We state these plainly because serious buyers test for them, and because a vendor that hides limits cannot be trusted on the claims it does make.

  • No third-party security audit or penetration test has been performed. Aegis has not undergone an external security audit or pen test, and we make no such attestation. Internal red-teaming has been conducted; that is not a substitute for third-party assurance.
  • No certifications held. Aegis is not SOC 2, ISO 27001, HIPAA, GDPR, or DPDP certified. We describe the architecture only as designed to support / helps you meet these regimes (Section 7).
  • DEK rotation is not implemented. One active data-encryption key per tenant; the schema anticipates rotation but no automated rotation process exists yet (Section 4.4).
  • Pre-encryption rows may remain plaintext until the optional in-application backfill runs for a tenant (Section 4.4).
  • Single region, no HA / multi-region. Dedicated-database-per-tenant isolation and the sovereign on-prem appliance are designed but not built (Section 8). We do not claim a 99.9% uptime SLA, multi-region, or high availability.
  • NER language coverage is bounded by the trained model. The optional transformer NER model (Davlan/distilbert-base-multilingual-cased-ner-hrl, off by default) detects PER/ORG/LOC across ten trained languages (ar/de/en/es/fr/it/lv/nl/pt/zh). Hindi is not a trained language for this model; Hindi PII is covered by deterministic Hindi rule packs and tenant-custom rules rather than the model. NER is an augmentation, never the sole detector — the deterministic regex/rule engine is always authoritative.

Where these items are scheduled, they appear in the strategy roadmap (docs/strategy/NEXT-12-MONTHS.md, SOVEREIGN-RESIDENCY-DESIGN.md).

Document version: v1.0 — 2026-06-19

Prepared by: CLAB / Aegis engineering, for procurement and security review.

Verification basis: Every claim in this document was checked against the Aegis source tree (src/Clab.PiiGuard, src/Clab.Pipeline, src/Clab.Security, src/Clab.Gateway/Byok, db/100, db/310, db/320, db/330) at the date above. Code evolves; re-verify against the named files before relying on a specific claim in a contractual context.