# AEGIS CYBER — Internal Engineer Onboarding
**Audience:** New software engineers joining the AEGIS CYBER platform team
**Date:** 2026-06-08
**Rule 5 discipline:** Every capability below is labelled by verified state. Claims are derived from the codebase and the engineering record (`docs/regulatory/FOLLOW-UPS.md`), not from prior documents.

---

## 1. Read these first — in this order

Before touching any code, read these documents in sequence:

1. **`replit.md`** — architecture overview + standing-rules pointer index (21 rules). Read the full index before anything else.
2. **`docs/regulatory/STANDING_AGENT_RULES.md`** — the full text of all 21 mandatory governance rules. Rules 1, 2, 6, 7, 9, 10, 11 will directly govern your first PRs. Read every word.
3. **`docs/regulatory/AEGIS_CYBER_SECURITY_DOSSIER_FOR_BOU_2026-05-23.md`** — the calibrated capability evidence dossier. Shows what is live vs. simulated vs. not yet implemented, with source-code citations.
4. **`docs/regulatory/FOLLOW-UPS.md`** — the engineering history register. This is the source of truth for every architectural decision, incident remediation, and FU item. When you wonder "why does it work this way?" — the answer is in here.
5. **`docs/regulatory/BUILD_PRIORITY_LIST.md`** — the working build order (P0–P5, with dates and gate status). Tells you what's next and why.

Do not start coding before you have read items 1 and 2. Do not propose architecture changes before you have read item 4.

---

## 2. Stack

| Layer | Technology |
|---|---|
| Runtime | Node.js 24 (LTS) |
| Backend | Express 5 + TypeScript |
| Frontend | React 18 + TypeScript, Wouter routing, TanStack React Query, Tailwind + shadcn/ui, Framer Motion |
| Database | PostgreSQL 16 via Drizzle ORM 0.39.3 + drizzle-kit 0.31.8 |
| Sessions | `express-session` + `connect-pg-simple` |
| AI | Anthropic Claude (wired via Replit integration) |
| Security | `bcryptjs`, `helmet`, token-based CSRF, field-level encryption (AES-256-GCM) |
| Dev workflow | `npm run dev` — starts Express + Vite on a single port |

Shared types live in `shared/` schema files. Always start there for any data-model change — the frontend and backend must stay in sync.

---

## 3. Three environments — Rule 7 is non-negotiable

The platform targets three environments. Every code change must preserve all three unless the operator explicitly scopes it to one:

| Environment | What it is | Key constraint |
|---|---|---|
| **Replit dev** | Where code is built and reviewed | Your default working environment |
| **Docker laptop** | On-prem package, verified standalone | Changes must build cleanly under `docker compose up` |
| **Bank production** | Pilot deployment at a bank | Schema changes require an explicit prod runbook (Rule 2) |

**Schema changes do NOT auto-deploy.** `db:push` only touches dev. Every production schema change goes through an explicit operator runbook with a SELECT verification before and after. This is Rule 2 and it is binding.

---

## 4. What is genuinely live — current verified state

This is the honest picture as of 2026-06-08, derived from production verification evidence:

### Security substrate — prod-verified
| Capability | Evidence |
|---|---|
| Secret boot-guard — 15 required secrets, fail-closed | `secret-boot-guard.ts`; 15/15 in every prod boot |
| Multi-tenant isolation — three layers | GUC writer (`withTenantDbPhase`), session-derived tenant-resolution (x-tenant-id IDOR removed 2026-06-03), 70-table PostgreSQL RLS with USING+WITH CHECK predicates |
| RLS functional verification | 17/17 diagnostic probes PASS in prod (runId `t003-diag-*`, 2026-06-04; 17 probes post-`decision_scoring_outputs` addition) |
| Field-level encryption — secrets/credentials | `server/lib/field-encryption.ts`, AES-256-GCM, SESSION_SECRET fallback closed (FU-055, 2026-06-05) |
| Customer-PII encryption — 17 tables / 45 columns (40 AES-GCM encrypted + 2 HMAC-lookup + 3 out-of-scope) | `server/lib/pii-encryption.ts`; 20/20 encryption probe PASS in prod (ENC-PROBE-1780939715886, 2026-06-08) |
| Schema-conformance boot assertion | `server/lib/schema-conformance.ts`; 118 columns checked at every boot (tenant_id: 70/70, pii: 47/47, migration: 1/1); process.exit(1) on mismatch |
| Audit hash-chain | SHA-256 chained log; `forensicChain VERIFIED` in prod |
| RBAC | Admin / Risk-Manager / Auditor roles, enforced by middleware |
| DSAR engine + purge worker | Real DB-backed workflow; 5-minute scheduler tick; prod tick clean (failed:0) |

### Platform capabilities — prod-verified
| Capability | Evidence |
|---|---|
| KYT rules engine + hot-reload | Weighted rule-based scoring; validated JSON config; ~30s hot-reload poller |
| AI threat scoring (Anthropic Claude) | Wired; real model output when integration is active. Accuracy **not yet benchmarked** against labelled bank data |
| CBS Gateway | Finacle / Flexcube / T24 / generic; 7 POST routes with Zod validation (FU-057, 2026-06-08); unknown-provider guard at gateway layer |
| Signed Pilot-Pack bundle + public verifier | Immutable, cryptographically-signed evidence bundle; independent verifier surface |
| Examiner-token substrate | 256-bit entropy, salted SHA-256, boot-guarded, TTL/scope bounds, revocation |
| SOAR response playbooks | Automated response logic (session freeze on critical threat) |
| SBOM / A-BOM | Reads real dependency manifest |
| EOL check | Queries live `endoflife.date` |

### Simulated / not-yet-implemented (do not claim as live)
| Capability | Actual state |
|---|---|
| HSM enclave | Software stub (`server/lib/hsm-integration.ts`, `server/hsmEnclave.ts`); self-labeled as simulation. Production encryption uses env-var keys, not HSM-backed. See `docs/regulatory/AEGIS_CYBER_HSM_BOUNDARY_SPEC.md`. |
| Six-node sovereign edge, SIM-swap, offline transactions | Designed and scaffolded; synthetic statistics. Not live. |
| DR failover (Kampala → Entebbe) | In-memory simulation (`dr-failover.ts`). PostgreSQL streaming replication NOT configured. Runbook exists at `docs/regulatory/AEGIS_CYBER_DR_EXERCISE_RUNBOOK.md`. |
| Behavioural baselines (Bio-Vault) | Seeded demo profiles, not learned from real staff |
| AI scoring benchmarking | Not yet run against labelled bank data |
| Bank-prod deployment | Not yet deployed to a real bank-IT environment |

---

## 5. The security substrate — understand this before touching security code

### 5.1 Multi-tenant isolation (three layers)

Every authenticated API request goes through this chain:

1. **Tenant middleware** (`server/lib/tenant-middleware.ts`): checks out a pinned DB client, opens an explicit transaction, calls `SET LOCAL app.current_tenant_id = '<tenantId>'` via `withTenantDbPhase`. The GUC is visible to all queries within that transaction.
2. **Tenant resolution** (`source:"session"`): the tenant is derived from `user_tenant_roles` via the authenticated session — NOT from a caller-supplied header. The `x-tenant-id` header was an IDOR surface; it was audited and removed in prod 2026-06-03.
3. **Database-layer RLS** (`server/lib/rls-init.ts`): 70 tenant-scoped tables carry `ENABLE ROW LEVEL SECURITY`. The `tenant_isolation` policy uses `USING (tenant_id = current_tenant_id())` and `WITH CHECK (tenant_id = current_tenant_id())`. Enforced at the database layer against the restricted `aegis_app` role.

**The boot sequence fails fast:** `initRlsPolicies()` verifies all 70 USING+WITH CHECK predicates at the catalogue level and calls `process.exit(1)` before `registerRoutes()` if any predicate is wrong. A broken security control crashes the boot — it does not serve under a false-green state (Rule 14).

**The idempotency model is effect-idempotent, not structure-idempotent** (Rule 16): on each boot, policies are DROP+CREATE, not "skip if exists". Policy name existence does not imply predicate correctness.

**Permanent diagnostic infrastructure** (Rule 17): `POST /api/internal/rls-diagnostic` is a permanent prod endpoint (admin-gated, `RLS_DIAGNOSTIC_ENABLED=true` flag required). Re-run it after any change touching RLS/policies/grants/`current_tenant_id()`. 17/17 probes required to pass.

### 5.2 Field-level encryption

Two separate encryption surfaces:

| Surface | File | Keys | Scope |
|---|---|---|---|
| Credentials / integration keys | `server/lib/field-encryption.ts` | `ENCRYPTION_KEY` (scrypt-derived) | Service API keys, MFA seeds |
| Customer PII | `server/lib/pii-encryption.ts` | `PII_AES_MASTER_KEY` + `PII_HMAC_MASTER_KEY` | 17 PII tables, 45 columns (40 AES-GCM encrypted + 2 HMAC-lookup + 3 out-of-scope) |

PII encryption uses two treatments per column: (i) encrypt-at-rest (AES-256-GCM, for non-lookup columns like names/narratives); (ii) HMAC-derived lookup key + encrypted blob (for equality-lookup columns like national IDs, emails used in WHERE clauses). Per-column decision matrix at `docs/regulatory/T004A_DESIGN_BRIEF.md`.

### 5.3 Schema-conformance assertion

`server/lib/schema-conformance.ts` runs at every boot between `applyBootSchemaMigrations` and `initRlsPolicies`. It checks 118 columns for existence and type against `information_schema.columns`. Fails fast with `process.exit(1)` on mismatch — prod/code drift cannot survive a restart.

### 5.4 Audit chain

Every security/admin action writes to `audit_chain_entries` (SHA-256 hash-chained). The chain is verified by `forensicChain` on every read; `brokenLinks:0` is the expected state. `audit_chain_entries` has a special access boundary: `aegis_app` is SELECT-only (Option B); DML goes through `aegis_rls_bypass` (Option Y) at specific legitimate bypass surfaces.

---

## 6. Code structure

```
server/
  index.ts          — boot sequence: secret-guard → schema-migrations → schema-conformance → rls-init → registerRoutes
  routes.ts         — full API surface (~14,000 lines; CBS validation at L6824–L6989)
  storage.ts        — IStorage interface; all DB operations go through here
  db.ts             — dual-pool topology: ddlPool (superuser, for rls-init only) + appPool (aegis_app restricted role)
  lib/
    rls-init.ts     — 4-step idempotent DDL: current_tenant_id() + roles + grants + 70-table RLS loop
    tenant-middleware.ts — withTenantDbPhase GUC writer
    schema-conformance.ts — 118-column boot assertion
    pii-encryption.ts    — customer-PII AES-256-GCM + HMAC
    field-encryption.ts  — credential/integration-key encryption
    secret-boot-guard.ts — 15-secret fail-closed guard (first import in index.ts)
    audit-chain.ts       — hash-chaining logic
    core-banking-gateway.ts — CBS Finacle/Flexcube/T24/generic gateway
    dsar-workflow.ts     — DSAR/erasure engine
    ...              — other domain modules

shared/
  schema.ts         — Drizzle table definitions (imports schema-rbac.ts, schema-pii.ts etc.)
  schema-rbac.ts    — user_tenant_roles, utr_primary_per_user index

client/src/
  pages/            — 60+ React pages
  App.tsx           — route registration

scripts/            — verification scripts (re-runnable probes, test harnesses)
docs/regulatory/    — all governance documents
```

**Two connection pools — understand the boundary:**
- `appPool` (`aegis_app` role, non-bypass): used for all request-scoped queries. RLS enforced.
- `ddlPool` (superuser): used only by `rls-init.ts` for DDL and `auditDb` for audit chain writes. Never reachable from request handlers.

`withBypassRls()` helper (in `db.ts`): used for legitimate bypass surfaces only (login UTR lookup, seed functions). Every use site is registered in the LOGIN-UTR and SEED-UTR registers in `db.ts`.

---

## 7. The governance rules that will directly affect your work

Full text in `docs/regulatory/STANDING_AGENT_RULES.md`. The ones you'll hit first:

| Rule | What it means in practice |
|---|---|
| **Rule 1** | Never run any shell command or write any log that prints a secret value. Not even for debugging. Safe: existence check, length check, last-bytes-as-hex. |
| **Rule 2** | Schema changes don't auto-deploy. `db:push` = dev only. Every prod schema change needs an explicit runbook with SELECT verification before and after. |
| **Rule 5** | Realistic-not-aspirational in every artefact. Three states: implemented + measured / implemented + unmeasured / not yet implemented. "Real-time," "compliant with Y," "production-grade" all require verification before use. |
| **Rule 6** | No completion claims based on intent. Build success / test pass / probe result / direct observation only. |
| **Rule 7** | Changes must preserve all three environments (Replit dev / Docker laptop / bank prod) unless explicitly scoped to one. |
| **Rule 9** | Architect review is mandatory BEFORE committing changes to: auth, sessions, audit chain, encryption keys, multi-tenant isolation, KYT detection. Also mandatory for security-related schema changes. |
| **Rule 10** | `package.json`, `package-lock.json`, `vite.config.ts`, `drizzle.config.ts`, and all `tsconfig*` files are forbidden without explicit operator authorisation. |
| **Rule 14** | Security-control init functions must fail fast (`process.exit(1)`) before serving. A broken security control crashes the boot — it does not serve silently. |
| **Rule 16** | Idempotency must be effect-idempotent, not structure-idempotent. "Policy name exists" ≠ "policy is correct." DROP+CREATE, not "skip if exists," for security objects. |

---

## 8. Secret-handling (share this explicitly)

Secrets are managed in the platform's secret store. You get access to the store — not pasted values.

**Never** send or receive secret values over chat, email, or any uncontrolled channel. Never log them. Never echo them in a shell command. This is Rule 1 and the bank will audit for it.

The 15 boot-guarded secrets are defined in `REQUIRED` array in `server/lib/secret-boot-guard.ts`. If you add a new secret-dependent capability, add it to the guard before writing the capability code.

---

## 9. Running the CBS HTTP test (verify your environment is wired)

After your environment is running, confirm the CBS route validation is live with these three calls (requires an authenticated session cookie):

```bash
# 1. Get a CSRF token
curl -s https://<your-dev-url>/api/csrf-token

# 2. Test unknown-provider rejection (expect 400)
curl -s -X POST https://<your-dev-url>/api/cbs/transactions/flag \
  -H "Content-Type: application/json" \
  -H "x-csrf-token: <token-from-step-1>" \
  -H "Cookie: <your-session-cookie>" \
  -d '{"transactionId":"TXN-001","flag":"REVIEW","reason":"test","provider":"unknown_bank"}'
# Expected: 400 {"error":"Validation failed",...}

# 3. Test invalid enum rejection (expect 400)
curl -s -X POST https://<your-dev-url>/api/cbs/transactions/flag \
  -H "Content-Type: application/json" \
  -H "x-csrf-token: <token-from-step-1>" \
  -H "Cookie: <your-session-cookie>" \
  -d '{"transactionId":"TXN-001","flag":"INVALID_FLAG","reason":"test"}'
# Expected: 400 {"error":"Validation failed",...}
```

If either returns 200 or 500, something is wrong — stop and surface it before continuing.

---

## 10. Known gaps / honest backlog (so you are not surprised)

These are real gaps — not things we are about to close, but things that will be on your radar:

| Gap | Status |
|---|---|
| HSM enclave | Software simulation. Real hardware hookup is a future integration item. See `docs/regulatory/AEGIS_CYBER_HSM_BOUNDARY_SPEC.md` for the substitution boundary. |
| PostgreSQL streaming replication (Kampala → Entebbe DR) | Not configured. DR exercise runbook exists at `docs/regulatory/AEGIS_CYBER_DR_EXERCISE_RUNBOOK.md`. Exercise cannot run until bank IT sets up replication. |
| Offsite backup transfer | `pg_dump` to local filesystem is real; transfer to offsite storage (S3 / SFTP) is not yet implemented. |
| Existing-row PII encryption migration (T004b) | New-row writes encrypt correctly. Existing plaintext rows in 17 PII tables are not yet migrated. T004b design brief at `docs/regulatory/T004B_DESIGN_BRIEF.md`. This is the highest-risk future operation in the arc. |
| AI scoring benchmarking | Not yet run against labelled bank data. |
| Bank-prod on-prem deployment | Not yet done. Docker packaging verified; bank-IT hookup is the pilot ask. |
| FU-015 — UBO-aware erasure | Open design surface, deferred-by-design. |
| June-15 security audit | Rule 3 cadence — next audit run on 2026-06-15, carve-outs register v1.2 by 2026-06-22. |

---

## 11. Diagnostic endpoints (permanent prod infrastructure)

These endpoints exist for verification purposes. They are admin-gated and flag-controlled — they do not auto-run.

| Endpoint | Flag required | Purpose |
|---|---|---|
| `POST /api/internal/rls-diagnostic` | `RLS_DIAGNOSTIC_ENABLED=true` in prod secrets | 17-probe in-container RLS isolation functional verification. Run after any RLS/policy/grant/`current_tenant_id()` change. 17/17 PASS required. |
| `POST /api/internal/encryption-probe` | `ENCRYPTION_PROBE_ENABLED=true` in prod secrets | 20-probe PII encryption verification across 17 tables. Run after any PII encryption change. 20/20 PASS required. |

After use, set the flag to absent (not "false" — absent). The routes stay deployed as permanent infrastructure (Rule 17). They are the only mechanisms for in-container, real-role functional verification of the security substrate.

---

## 12. Getting help

- **Engineering history and decisions:** `docs/regulatory/FOLLOW-UPS.md` (9,200+ lines; use `bash sed -n 'NNN,MMMp'` for ranges beyond ~8000 lines — the read tool silently truncates).
- **Architecture questions:** check the dossier (§8.1 for isolation, §8.2 for encryption, §7 for secrets) before asking — it will have the answer with source-code citations.
- **Standing rules questions:** `docs/regulatory/STANDING_AGENT_RULES.md` has the full text including worked examples and incident anchors.
- **Current build status:** `docs/regulatory/BUILD_PRIORITY_LIST.md` — the authoritative working order.
