blueprint chapterThe Codices

Codex 0 · Chapter 17 — Platform Architecture and Engineering

Chapter 17 of the institutional specification.

Authority rank
2
Version
v2.0
Adopted
unrecorded
Held by
Stewardship Office
System
SYS-12

Source · docs/codices/CODEX-0/17-engineering.md · registered by rule

This chapter specifies the layering, boundaries, runtime constraints, and verification discipline that every implementation of Anabasis must obey.

17.0 Purpose

17.0.1 This chapter binds Codex 7 (Engineering Doctrine) to the concrete runtime the institution builds on, so that engineering judgment has a fixed reference rather than ad hoc precedent.

17.0.2 It exists because the platform is expected to be replaced, rewritten, and re-hosted multiple times across a hundred-year horizon (Codex 1, Article VII), while the boundaries and obligations named here must survive each replacement unchanged.

17.0.3 Where this chapter and Codex 7 differ in phrasing, Codex 7 governs; this chapter elaborates Codex 7 for the runtime of record and does not narrow it.

17.1 Scope and non-scope

17.1.1 In scope: layering rules, module boundaries, the runtime constraints of the edge worker environment, the server function and public route distinction, data access and row-level policy obligations, edge validation, secrets handling, observability, auditing implementation, error handling and degradation, performance and data loading, localization readiness, testing and verification, and the technical-debt register.

17.1.2 Out of scope: the choice of any specific hosting vendor, framework, or library. This chapter names capabilities and constraints, not products. Where the current implementation uses a specific framework or managed backend, this chapter describes the capability class it belongs to and reserves the institution's right to replace it without amending doctrine.

17.1.3 This chapter does not restate the design or writing rules of Codex 6; it defers to Chapter 6 and Codex 6 for register, accessibility, and interaction rules, and confines itself to structure and mechanism.

17.2 Layering

17.2.1 Every implemented system separates into four layers: presentation, application, domain, and data.

17.2.2 Presentation renders state and captures intent. It contains no business rule, no authorization decision, and no direct data access. A component may format a date; it may not decide whether a person is allowed to see it.

17.2.3 Application orchestrates use cases: it receives intent from presentation, calls domain logic and data access in sequence, and returns a result or an error. It contains no rendering concerns and no raw SQL or storage-specific logic.

17.2.4 Domain holds business rules: what a credential means, when an enrolment is complete, what a role permits. Domain logic is testable without a network, a database, or a rendered page.

17.2.5 Data is the only layer that reads or writes storage. It enforces the schema, the row-level policy, and the grants named in Codex 5 and Chapter 5. No other layer opens a connection or issues a query directly.

17.2.6 A component (in the presentation layer) must never: query the data layer directly, embed authorization logic, hold secrets, perform validation that is the sole gate against invalid state, or implement a business rule that is not also enforced server-side. UI concealment is not a permission (Codex 1, Article VI.5; Codex 0 §4).

17.2.7 A change confined to one layer must not require a change to another. If it does, the boundary was drawn in the wrong place and is corrected, not worked around.

17.3 Module boundaries and replaceability

17.3.1 Every capability — an engine (ENG-), an API boundary (API-), an internal tool (TOOL-) — is a module with a declared interface (Codex 7, Principle 3).

17.3.2 A module's interface is its contract: the shapes it accepts, the shapes it returns, and the errors it can produce. Consumers depend on the contract, never on the module's internal representation or storage layout.

17.3.3 A module is replaceable in isolation if its contract holds. Replacing an engine's internal implementation must not require a change to any consumer that only uses the declared interface.

17.3.4 No module reaches into another module's storage. An engine that needs another engine's data calls that engine's interface (Codex 0 §5). A registry entry that needs data owned by another entry names the dependency by ID (Codex 0-REGISTRY, rule 3) rather than reading the table directly.

17.3.5 A new module is created only when no existing module can absorb the responsibility (Codex 0 §5; Codex 0-REGISTRY rule 2, "rule against duplication," Codex 0 §2).

17.4 Runtime constraints of record

17.4.1 Server code executes in an edge worker runtime. This runtime constrains what "server code" is permitted to assume, independent of which vendor supplies the runtime.

17.4.2 No native binaries. A capability that requires shelling out to a compiled tool is not implementable as edge server code; it is either reimplemented in the request-time language or moved to an out-of-band job outside the request path, named as such in the registry.

17.4.3 No subprocesses. Server handlers do not spawn child processes. Work that would require a subprocess is restructured as a library call, a queued job, or a call to an external service through a declared API boundary.

17.4.4 No reliance on an OS filesystem. Server handlers do not read or write local disk as a means of persistence or interchange. Persistent state lives in the managed backend of record; transient in-memory state does not survive or coordinate across invocations and is not used as if it could.

17.4.5 Environment values are read inside handlers, never at module scope (Codex 7). A module-scope read executes once at cold start under runtime conditions the handler cannot control, and produces requests served with stale or wrong configuration; a handler-scope read is bound to the request it serves.

17.4.6 These constraints apply regardless of local convenience. A pattern that works in a developer's own machine but violates 17.4.2–17.4.4 is not shipped; it is redesigned before merge.

17.5 Server boundaries: server functions and public routes

17.5.1 Two distinct mechanisms exist for server-side logic, and they are not interchangeable.

17.5.2 App-internal server functions serve the application's own presentation layer. They are called only from within the same application, are not addressable as a general-purpose API, and may assume the calling context the application itself establishes (an authenticated session, a loaded route).

17.5.3 Public routes are externally callable: by other services, by integrations named in Codex 0 §11, or by any caller outside the application's own presentation layer. A public route verifies its caller on every invocation. It does not assume a session established elsewhere and does not trust a header, referer, or origin as proof of identity.

17.5.4 A server function is not made externally callable by giving it a public route without adding the caller-verification obligation of 17.5.3. Promoting an internal function to a public route is a boundary change, not a refactor, and is reviewed as one.

17.5.5 Only published API boundaries (API-, Codex 0 §11) are integrated against by third parties. No third-party integration receives direct database access, and none receives a private path that bypasses a declared boundary (Codex 0 §15.6).

17.5.6 A public route's contract is versioned. A breaking change to a public route requires a version, a migration window, and a decision record (Codex 0 §11; Codex 0-REGISTRY §3).

17.6 Data access and row-level policy

17.6.1 Every table holding member data ships with explicit grants and row-level policy in the same migration that creates it (Codex 1, Article VI.5; Codex 0 §7; Codex 7). A table without a policy is not deployed, regardless of how the application layer intends to guard it.

17.6.2 Row-level policy is the enforcement point, not a convenience layered on top of application checks. An application-layer check that is not backed by an equivalent database-layer policy is treated as absent: an attacker or a bug that bypasses the application still meets the policy at the data layer.

17.6.3 New surfaces start closed (Codex 0 §8). A table or policy that has not yet had its access pattern specified defaults to denying all access rather than allowing it pending review.

17.6.4 Elevated reads of member content are logged with a stated reason (Codex 0 §8) and produce an ENT-19 AuditRecord (§17.9).

17.6.5 Delegated access expires. A grant that does not carry an expiry is a defect, not an oversight to be caught later.

17.6.6 Authority to define a credential standard is kept separate, at the policy level, from authority to issue against it (Codex 0 §8). This separation is enforced in the schema and the policy, not only in the tool's interface.

17.7 Validation at the edge

17.7.1 Every request entering the application from outside its own trusted process — a public route call, a form submission, a webhook — is validated against a declared shape before any handler logic runs.

17.7.2 Validation is the same code path in every environment; it is not relaxed for internal callers, staging, or development convenience. A payload that would be rejected in production is rejected everywhere.

17.7.3 Validation failures return a structured, typed error. They do not silently coerce, truncate, or guess at intended values.

17.7.4 Validation at the edge is a complement to row-level policy (§17.6), not a substitute for it. A well-formed but unauthorized request is still rejected by policy.

17.8 Secrets handling

17.8.1 Secrets are never present in client-delivered code, in a component, or in any artifact served to a browser.

17.8.2 Secrets are read from the runtime's environment inside a handler at request time (§17.4.5), never hardcoded, never committed to version control, and never logged (§17.9).

17.8.3 A secret's presence is checked before use (does the value exist), never echoed in error messages, diagnostics, or support tooling output.

17.8.4 Rotation of a secret must not require a code change; secrets are configuration, named in Codex 7 Principle 6 ("configuration over custom code").

17.9 Observability, structured logging, and auditing

17.9.1 Logs are structured (machine-parseable fields, not free text concatenation), so failures are traceable across the layers of §17.2 without manual correlation.

17.9.2 No secret, credential, password, token, or full identity document ever appears in a log line, an error message surfaced to a user, or a diagnostic export. Logging a masked or truncated reference is acceptable; logging the value is not.

17.9.3 Every consequential action — one that changes a person's standing, grants or revokes access, issues or revokes a credential, or alters a financial record — produces an immutable ENT-19 AuditRecord carrying actor, subject, timestamp, and reason (Codex 1, Article VI.6; Codex 0 §7; Codex 7).

17.9.4 An AuditRecord is additive only. It is never edited or deleted after creation; a correction is a new record referencing the one it corrects.

17.9.5 Audit records are queried through API-11 (Audit) and surfaced through TOOL-11 and DASH-08/10; no tool reads the audit table directly outside that boundary.

17.10 Error handling and graceful degradation

17.10.1 A peripheral engine's failure never takes down the core (Codex 7). "Core" means identity, authentication, and the minimum path a person needs to reach their own record; "peripheral" means any engine or integration whose absence degrades a feature without blocking that path.

17.10.2 Every call to a peripheral system is wrapped so that its failure produces a visible, honest degraded state in the interface — never a blank screen, never a silent fabrication of data, and never a crash of the surrounding page.

17.10.3 A degraded state names what could not be loaded and, where possible, offers a retry. It never claims success it did not achieve (Codex 6, "Confidence is the product").

17.10.4 Errors returned to a caller distinguish between a caller error (invalid input, insufficient permission) and a system error (something failed on the server). The distinction determines what is retried and what is not.

17.10.5 An error is never swallowed silently. If a failure is not surfaced to the person affected, it is surfaced to the structured log (§17.9) with enough context to diagnose it.

17.11 Performance and data loading

17.11.1 A view loads only the data it needs (Codex 7). Loading an entire entity to render a summary is a defect.

17.11.2 Server-side data loading happens through route loaders and cached queries. A route's data dependency is declared at the route level so it can be fetched, cached, and invalidated predictably, rather than fetched ad hoc inside a component after render.

17.11.3 Caching is applied at the query level with an explicit invalidation rule. A cache without a stated invalidation condition is not shipped.

17.11.4 Pagination, not unbounded fetches, is the default for any list that can grow with institutional scale (Chapter 18).

17.12 Localization readiness

17.12.1 Content and layout are localization-ready from the start (Codex 0 §15.3; Codex 6; Codex 7): no string concatenation that assumes English word order, no text baked into images, and layouts that tolerate longer strings in other languages without breaking.

17.12.2 User-facing strings are held in a form that can be extracted and translated without a code change, even where only one language is implemented today.

17.12.3 Region-scoped data and residency requirements are treated as configuration on the Organization and Person records (Codex 0 §15.3), not as a fork of the codebase.

17.13 Testing and verification

17.13.1 Every structural change is typechecked before it is called done (Codex 7).

17.13.2 Verification output is read in full, by a person, not sampled or assumed passing because a command returned. An exit code of zero accompanied by error text in the output is a failure, not a pass, and is treated as one (Codex 7).

17.13.3 A test that is disabled, skipped, or marked flaky without a decision record is treated as a failing test for the purpose of this clause.

17.13.4 Verification covers all four layers of §17.2 where applicable: domain logic is unit-tested without network or storage; data-layer policy is tested against the policy itself, not only against the application's intended use of it; application and presentation are tested for the behaviors a person actually depends on.

17.14 Technical debt

17.14.1 Debt is permitted only when named: what was traded, why, and what would repay it (Codex 1, Article VII; Codex 7). Unnamed debt is a defect, not a shortcut.

17.14.2 A named debt entry is recorded where the next engineer will find it — in the code adjacent to the tradeoff and in a decision record if the tradeoff is architectural — and states, at minimum: the constraint that forced the tradeoff, the capability given up, and the condition under which it must be repaid (a scale threshold, a registry status change, a date).

17.14.3 A registry entry's status (built, partial, reserved) is not moved upward on the strength of debt going unremarked. Status moves upward only through work (Codex 0-REGISTRY, rule 5).

17.15 Interfaces

17.15.1 This chapter's obligations bind every entry in the registry classes ENG-, API-, TOOL-, DASH-, AGT-, and SURF- (Codex 0-REGISTRY) at the point each is implemented, regardless of its current status.

17.15.2 A registry entry's "How it connects" field (Codex 0 §16, question 4) is the enforcement record for the module-boundary rule of §17.3.4: an undeclared dependency is a doctrine violation, not a style issue.

17.16 Invariants

17.16.1 A component never performs a business rule or authorization decision that is not also enforced server-side.

17.16.2 A public route always verifies its caller; an app-internal server function is never exposed as a public route without acquiring that obligation.

17.16.3 No member-data table exists without row-level policy in its creating migration.

17.16.4 No secret exists in client-delivered code or in a log line.

17.16.5 No consequential action exists without a corresponding ENT-19 AuditRecord.

17.16.6 No server handler depends on OS filesystem persistence, a subprocess, or a native binary.

17.16.7 No verification is called complete while its output contains unread error text.

17.17 Prohibitions

17.17.1 No direct database access from the presentation layer.

17.17.2 No third-party integration granted access outside a published API boundary.

17.17.3 No environment value read at module scope.

17.17.4 No table shipped without its row-level policy.

17.17.5 No test disabled to make a build pass without a decision record.

17.17.6 No unnamed technical debt.

17.17.7 No fabricated success state shown to a person when a peripheral system has failed.

17.18 Open questions

17.18.1 The permanent location and retention period of structured logs, distinct from audit records, is not yet fixed and is deferred to a decision record when observability tooling is selected.

17.18.2 The mechanism for out-of-band jobs that cannot run inside the edge worker's request lifecycle (§17.4.2) is reserved; no such job exists yet, and its owner and boundary will be named when the first case arises.

17.18.3 The threshold at which cached-query invalidation (§17.11.3) must move from time-based to event-based is deferred to Chapter 18.

17.19 Governing Codices

17.19.1 Codex 1 (Constitution), Articles VI and VII.

17.19.2 Codex 0 §§4, 5, 7, 8, 11, 15, and the Registry.

17.19.3 Codex 5 (Data and APIs).

17.19.4 Codex 6 (Experience Doctrine), for the interface consequences of degradation and confidence.

17.19.5 Codex 7 (Engineering Doctrine), which this chapter elaborates and does not supersede.