# AEGIS — Secure Coding Standard - **Document ID:** ARCH-19 - **Phase:** C — Standards & Operations - **Status:** Draft for review (post four-reviewer discipline) - **Version:** 0.1 - **Date:** 2026-07-10 - **Owner:** Chief Security Architect - **Depends on:** ARCH-06 through ARCH-18 - **Consumed by:** ARCH-20 through ARCH-24, and every implementation-phase document. --- ## 1. Purpose Codify the rules under which AEGIS source code is written, reviewed, tested, and shipped. This standard is prescriptive: it turns the architectural intent from Phases A/B into MUST-rules that a well-trained security engineer can apply without hidden knowledge (mandate #32 Operational Simplicity). ## 2. Requirements - **REQ-1.** Every AEGIS-produced binary is built from source that complies with this standard, verified by CI. - **REQ-2.** Deviations require an explicit `# ARCH-19-EXCEPTION` marker with Owner + Auditor sign-off recorded in the exception register. - **REQ-3.** Every rule below has automated enforcement where possible; where not, a review checklist item. - **REQ-4.** The standard evolves with the code (mandate #30 Docs-as-Code). Rule changes ship as PRs; drift between doc and enforcement is CI-detected. ## 3. Languages ### 3.1 Primary — TypeScript - **TS strict mode** always on: `strict: true`, `noImplicitAny`, `strictNullChecks`, `strictFunctionTypes`, `strictBindCallApply`, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`. - **Target:** Node.js current LTS (24 at time of writing). `tsc` target `es2023` minimum. - **Package manager:** pnpm with lockfile committed. `pnpm install --frozen-lockfile` in CI. ### 3.2 Security-Critical — Rust Rust is used for: Kernel core hot paths (signing, capability directory), verifier CLI, Runtime Integrity Verification, high-perf parsing (Normalization Engine hot path), and future endpoint components. - Edition 2024 or latest stable. - `#![deny(unsafe_code)]` at crate root; any `unsafe` block requires justification comment + review approval. - `#![deny(clippy::all)]` with `#![deny(clippy::pedantic)]` on new crates. - No `unwrap()` / `expect()` in non-test code without justification. ### 3.3 Prohibited - No C/C++ in the AEGIS codebase for v0. - No dynamic module load, `eval()`, `Function(...)` in any language. - No shell-out from Kernel, Storage Engine, Normalization Engine, or Audit Engine (higher-risk paths). ## 4. Mandatory Rules ### 4.1 Input Validation - **M-1.** Every external input (HTTP body, message from bus, event from source) MUST be validated against a schema (zod for TS, `serde` + validators for Rust) before use. - **M-2.** Reject on validation failure — never coerce. Fail-secure default is deny. - **M-3.** Size limits enforced at deserialization boundary (not after). - **M-4.** All parsed timestamps validated for reasonableness (§ Time integrity). ### 4.2 Output Encoding and Data Boundaries - **M-5.** All UI output goes through a framework-level escaping path (Next.js React by default). No `dangerouslySetInnerHTML` without ARCH-19-EXCEPTION. - **M-6.** Structured data crossing an engine boundary is a signed protobuf/CBOR envelope (per ARCH-09 §6.2). No ad-hoc JSON strings. - **M-7.** Any content going to an LLM is wrapped by the Redaction pipeline (ARCH-15 §7). Direct string interpolation into prompts is forbidden. ### 4.3 Error Handling - **M-8.** No swallowed exceptions. Every `catch` either handles or re-throws with context. - **M-9.** Errors returned to callers do not leak internal state (stack traces, filesystem paths, keys). External error surfaces are deliberately structured. - **M-10.** Security failures produce audit records (ARCH-20) at the boundary. - **M-11.** Never fail-open on authorization, capability verification, classification checks, or policy consultation. Timeouts = deny. ### 4.4 Secrets and Keys - **M-12.** Secrets NEVER in code, config, logs, metrics, traces, error messages, or LLM prompts. - **M-13.** Secrets retrieved via Kernel-mediated `Read-Secret` at use time; never long-cached in-process except within the documented request scope. - **M-14.** Keys used via HSM/KMS interfaces; never exported. - **M-15.** SAST rule bank forbidden-log-patterns catches: `api_key`, `password`, `token`, `secret`, `bearer`, `private_key`, `cookie`, and per-provider patterns. - **M-16.** Pre-commit hook + CI: git-secrets/trufflehog run on every commit; blocks push on find. ### 4.5 Authorization and Capabilities - **M-17.** No engine bypasses Kernel-mediated capability checks (ARCH-05 boundary contract). - **M-18.** Capability tokens verified with Kernel public key on every use; caching per ARCH-08 §7. - **M-19.** Broker ACLs are updated in the same code path as the capability grant they enforce. No orphan ACLs. - **M-20.** Every operation names its capability. Type system enforces (branded types). ### 4.6 Classification Propagation - **M-21.** Classification is a required field on every cross-boundary payload. Missing classification = refuse. - **M-22.** Downgrade requires an explicit Policy Engine decision. No implicit downgrade in code. - **M-23.** Classification is signed as part of the payload envelope (ARCH-09 §6.2). ### 4.7 Cryptography - **M-24.** Only vendored, audited libraries: `libsodium` bindings, Node built-in `crypto`, and Rust `ring` / `rustls`. No hand-rolled crypto. - **M-25.** Every signature site carries an `alg` field (Cryptographic Agility, mandate #29). - **M-26.** Ed25519 baseline; hybrid PQC pilot begins when libraries mature (per Q-09-2 resolution). - **M-27.** Random from OS CSPRNG; never from `Math.random()`, `rand::thread_rng()` for security-critical uses (`OsRng` in Rust). - **M-28.** Constant-time comparison for all secret-comparison ops. ### 4.8 Concurrency and Async - **M-29.** No shared mutable state across request scopes without explicit synchronization; type system enforces where possible. - **M-30.** Timeouts on every external I/O (`AbortController` in TS; `tokio::time::timeout` in Rust). - **M-31.** Cancel propagation: cancelled contexts release resources. ### 4.9 Time - **M-32.** Use monotonic clocks for internal comparisons (`process.hrtime.bigint()` in Node; `Instant` in Rust). - **M-33.** Wall-clock times are annotated with source (NTP-anchored or source-supplied); provenance carried per ARCH-15 §9. - **M-34.** Never use wall-clock diffs for security-relevant TTL enforcement. ### 4.10 Determinism and Reproducibility - **M-35.** Security-decision code paths are deterministic given signed inputs. No random branching. - **M-36.** Deterministic ordering: sort collections by stable key before serialization for signing. - **M-37.** No hidden global state affecting security decisions. ### 4.11 Dependency Governance - **M-38.** Allow-list of dependencies at repo root. New dep requires review and license/security check. - **M-39.** Hash-pinned versions in lockfile. No floating versions. - **M-40.** SBOM generated per build; ARCH-14 supply chain rules apply. - **M-41.** Continuous SCA. Vulnerabilities triaged within SLO (§7). ### 4.12 Testing - **M-42.** Unit tests for every non-trivial function; branch coverage ≥ 80% for security-critical crates/packages. - **M-43.** Property tests for parsers, serializers, capability verification, classification propagation, and hash-chain operations. - **M-44.** Integration tests for every Kernel-mediated boundary crossing. - **M-45.** Fuzz tests for parsers on the ingest path (Normalization). - **M-46.** Security-focused mutation testing on hot paths (annual cadence in v0; per-release in v1). ### 4.13 Observability Hooks - **M-47.** Every function emits a trace span if callable from a boundary crossing. - **M-48.** Metrics use bounded label sets (no unbounded cardinality). - **M-49.** Logs are structured JSON with the fields required by ARCH-20. ## 5. Recommended Practices - **R-1.** Prefer composition over inheritance. - **R-2.** Prefer pure functions where practical; enable easier property testing. - **R-3.** Prefer branded types (e.g., `TenantId`, `CapabilityId`) to raw strings. - **R-4.** Prefer `Result` return over throwing across module boundaries (Rust culture; TS via a `Result` shim library). - **R-5.** Prefer explicit imports over wildcard. - **R-6.** Prefer smaller files with clear ownership over "one big module." - **R-7.** Prefer functional tests that describe scenarios over unit tests that duplicate types. - **R-8.** Code comments describe **why**, not **what**. Reserve for non-obvious constraints. ## 6. Verification Process ### 6.1 Pre-commit - Format check (`prettier`, `rustfmt`). - Lint (`eslint`, `clippy`) — errors block commit. - Secret scanning. - Unit tests for the modified package. ### 6.2 CI (per PR) - Full type check (`tsc --noEmit`), full lint, full unit + property tests. - Integration tests for touched engines. - SAST (semgrep/CodeQL rules including the forbidden-log-patterns). - SCA (SBOM diff + vulnerability check). - Boundary contract tests (ensure engine A → engine B call still goes through Kernel). - Coverage report; regressions gate. ### 6.3 CI (per merge to main) - Full test suite including fuzzers (time-boxed). - Two-CI reproducibility check (ARCH-14 D-14-1). - Provenance attestation generated. - SBOM published. ### 6.4 Code Review - **Two-approver rule for security-critical paths** (Kernel, Cryptographic Identity, Audit, Evidence, Watchdogs, Signing). - Reviewer checklist auto-loaded per touched path. - Every PR includes a "threat delta" if the touched area appears in ARCH-03. ## 7. Operational Guidance ### 7.1 Working with the standard - New engineers: 1-day onboarding pass through this doc + a hands-on exercise adding a capability check. - Every engineering role has assigned areas of ownership; owners are on the reviewer roster for their areas. - Exception register lives in `docs/exceptions/`; each exception expires and requires renewal. ### 7.2 Vulnerability SLOs - **Critical (CVSS 9-10):** Patch or mitigate within 24 h. - **High (7-8.9):** Within 7 days. - **Medium (4-6.9):** Within 30 days. - **Low:** Within release cycle. ### 7.3 Handling third-party bugs - Open a security advisory tracking ticket. - Assess: is AEGIS reachable? is it exploitable? is a fix available? - Coordinate disclosure with upstream. ## 8. Future Evolution - **PQC migration.** Rules M-25/M-26 accommodate hybrid signatures; migration is a versioned rule bump. - **Rust expansion.** As security-critical paths grow, Rust footprint grows; TS remains orchestration. Both language footprints are covered by the standard. - **Formal methods.** For Kernel and Capability directory, consider TLA+ / Alloy models by v1; standard adds a "modelled" tier. ## 9. Independent Architecture Review (Reviewer 1) - **F-1.** *Type system enforcement of capability names is language-boundary-limited.* Handled by branded types + runtime schema validation at boundaries. - **F-2.** *SAST rules drift as new patterns appear.* Rule bank versioned and reviewed on release cadence; test corpus verifies rules still fire. - **F-3.** *Exception register grows without discipline.* Every exception has an expiry; expired exceptions block CI unless renewed. - **F-4.** *Property tests are only as good as their properties.* Reviewed for coverage of the security invariants named in each ARCH doc; gap-analysis annually. ## 10. Adversarial Architect Review (Reviewer 2) - **A-1.** *Insider commits a `# ARCH-19-EXCEPTION` marker to bypass a rule.* Two-approver on security-critical paths; auditor visibility on exception register; drift monitor. - **A-2.** *Novel package with legitimate-seeming behavior added to allow-list.* Two-approver + provenance check + reputation check + observation period for high-trust categories. - **A-3.** *Prompt-inject a code review AI tool to approve a bad PR.* AI code review is advisory; human approvers make the call; two-approver requirement remains. - **A-4.** *Supply-chain compromise of a dev tool (linter, SAST) to hide a bad pattern.* Tool binaries hash-pinned; RIV monitors builder toolchain; two-CI reproducibility catches divergence. - **A-5.** *Credential theft grants push access.* Signed commits required; identity binding at push time; anomaly detection on unusual commit patterns. ## 11. Operational Reliability Review (Reviewer 3) - **O-1. Onboarding cost.** 1-day guided onboarding + progressive-disclosure docs; ownership matrix keeps areas humane. - **O-2. Rule updates.** Documented deprecation cycle; rule versioning; CI enforcement gap-free. - **O-3. Legacy code migration.** Migration checklist per rule; batches per subsystem; measured progress. - **O-4. Third-party library churn.** Documented process; ARCH-14 tie-in. - **O-5. Reviewer scaling.** Ownership rotation; two-approver rules kept selective; not every path is security-critical. - **O-6. Debug ergonomics.** Structured errors + structured logs make root cause locatable. - **O-7. Toolchain sustainability.** Language + tool versions pinned; upgrade drills scheduled; ARCH-22 config management. ## 12. Self-Critique (Reviewer 4) Things I'd change with more time or more evidence: - **S-1.** *TS coverage 80% is an ok floor but not a ceiling.* Consider raising to 90% for Kernel/Audit/Evidence packages once the codebase exists; deferred to actual measurement. - **S-2.** *"Two-approver on security-critical paths" is enforced by CODEOWNERS.* Depends on Git host's honesty. Complement with post-merge audit that verifies signer identity; not yet detailed. - **S-3.** *"No swallowed exceptions" is culturally hard to enforce.* Rely on lint + custom `no-empty-catch` rule; acknowledge culture will drift; monitor rate of `catch (_)` patterns as a proxy. - **S-4.** *Property test discipline* is easy to under-invest in when features press. Standard says "reviewed for coverage" but doesn't set a hard property/coverage minimum. Consider making some property invariants (capability attenuation, classification propagation, hash-chain monotonicity) *mandatory-covered* at CI-fail level. Roadmap. - **S-5.** *Rust footprint could accidentally grow into all engines.* This standard is silent on the rate. Add a policy: Rust expansions require an architectural note explaining why TypeScript is insufficient for that area. Prevents "rewrite-it-in-Rust" drift. - **S-6.** *Formal methods deferred to v1.* This might be too late for the capability directory. Reconsider adding TLA+ modeling to v0 for the Kernel's capability graph. Revising in place: added S-4 as a hardened requirement — mandatory property tests for capability attenuation, classification propagation, hash-chain monotonicity, revocation propagation, and time monotonicity (**M-43a**). Added S-5 as a governance rule for new Rust expansions. Applied: - **M-43a.** Property tests for the following invariants are **mandatory** and CI-blocking: capability attenuation (delegation never broadens), classification propagation (never silently downgrades), hash-chain monotonicity (Layer-A ring), revocation propagation (revoked tokens never verify), time monotonicity (monotonic seq strictly increases). - **New governance rule (M-38a).** Expanding Rust usage into a new engine or module requires an architectural note approved by the Owner explaining why TypeScript is insufficient. ## 13. Attacker's First-Target Analysis and Redesign **"If I were an experienced attacker, what part of this standard would I target first?"** **The exception register.** Reason: exceptions are how legitimate deviations are allowed; if an attacker can quietly add an exception (via a subtle PR), that deviation stays, and every follow-on can layer on top. Exceptions are where the standard meets its own edge cases and where audit fatigue is likeliest. **Redesign response.** 1. **Every exception has an expiry.** Default: 90 days. Renewal requires the same approval as creation. 2. **Exception register is signed.** Modifications go through Multi-Stage Decision Pipeline (Config Management standard, ARCH-22 will govern this). 3. **Drift monitor.** Weekly job compares live enforcement configuration against the exception register; unlisted exceptions in code = alarm. 4. **Auditor visibility.** Exception register is exported to auditor dashboards on every change; monthly summary reviewed. 5. **Exception count is a security metric** (ARCH-24). Trend up = signal. **Second target after redesign.** SAST rule bank drift. Response: rules versioned, deprecation cycle, test corpus (positive + negative) required for each rule; rules dropped are auditor-visible. **Third target.** Package allow-list — a legitimate-seeming package that later turns malicious. Response: not fully addressable at the coding-standard layer; ARCH-14 supply chain governance is the primary defense; standard enforces the allow-list and provenance. ## 14. Decisions ### D-19-1. TS primary + Rust for security-critical - **Advantages.** Fast iteration in TS for orchestration; memory-safe hot paths in Rust; Q-06-1 resolution. - **Disadvantages.** Two toolchains. - **Security Impact.** *Strongly positive.* - **Performance Impact.** *Positive.* - **Operational Complexity.** *Moderate.* - **Maintainability.** *Positive.* - **Scalability.** *Positive.* - **Alternatives.** *All TS.* Rejected — some paths need Rust guarantees. *All Rust.* Rejected — velocity cost. - **Reason.** Q-06-1. ### D-19-2. Mandatory property tests for security invariants (M-43a) - **Advantages.** Structural enforcement of the most critical invariants; adversarial-review defense. - **Disadvantages.** Property test authorship overhead. - **Security Impact.** *Strongly positive.* - **Performance Impact.** N/A. - **Operational Complexity.** *Moderate.* - **Maintainability.** *Positive.* - **Scalability.** *Positive.* - **Alternatives.** *Sample tests only.* Rejected. - **Reason.** Self-critique output S-4. ### D-19-3. Exception register versioned + expiring + drift-monitored - **Advantages.** Structural resistance to the primary attack target. - **Disadvantages.** Governance overhead. - **Security Impact.** *Strongly positive.* - **Performance Impact.** N/A. - **Operational Complexity.** *Moderate.* - **Maintainability.** *Positive.* - **Scalability.** *Positive.* - **Alternatives.** *Perpetual exceptions.* Rejected. - **Reason.** §13 first-target analysis. ## 15. Open Questions - Q-19-1. Whether to require TLA+ modeling of the capability directory in v0 (S-6). Recommendation: v0 pilot; commit in ARCH-22 or later. - Q-19-2. Property-test framework choice for TS. Recommendation: `fast-check`. - Q-19-3. Semgrep vs. CodeQL for SAST. Both; overlap acceptable. ## 16. Change Log - **0.1 (2026-07-10)** — Initial draft after four-reviewer discipline.