# Phase 2 Adjacent-Gap Audit — Durable Database and Domain State **Audit date (UTC):** 2026-07-23 **Scope:** relational backends, migrations, identity/account/analysis entities, financial lifecycle entities, transaction boundaries, restart behavior, idempotency, execution locking, legacy state, browser/process authority, and multi-worker failure behavior. **Release posture:** Paper-only; `HERMES_EXECUTION_ENABLED=false` remains the default; Testnet/Live mutation remains disabled. ## Architecture reviewed - SQLite is restricted to isolated local Paper operation. Production-shaped configuration requires PostgreSQL and rejects dialect mismatches or in-memory SQLite. - PostgreSQL has explicit ordered DDL, checksums, transactional forward migration, and advisory-lock serialization. The driver is lazy and injectable; DSNs are never emitted in connection failures. - The lifecycle schema includes users, sessions, roles, exchange accounts, trading-mode policy, analysis requests, market snapshots, plans, approvals, risk decisions, executions/events, orders/events, fills, positions/events, protective orders, audit events, idempotency evidence, and fenced execution locks. - Financial records are owner/account/mode/environment scoped and versioned where required. Order/fill/protection scope is inherited and query isolation is enforced. - Position mutations and position-event insertion share one transaction. Fill insertion and order aggregate updates share one transaction. Realized PnL ledger updates occur in the same transaction as close fills. - Idempotency is persisted before adapter communication, request-content and operation-scope bound, retained after active TTL expiry, and restart safe. Execution locks are database-backed, scoped, leased, and fenced. - The historical direct Paper API now delegates to the relational execution service. The former module singleton, in-memory duplicate map, and `paper_positions.json` authority were removed. - The legacy `hermes_durable.sqlite3` facade is not imported by runtime code. A separate one-way operator tool validates legacy records, imports positions as `manual_review`, imports plans as invalidated, and cannot authorize execution. - Browser `localStorage` is limited to presentation preferences; approval, account, mode, leverage, position, and execution controls are not accepted as authority. ## Failure and concurrency evidence - Fresh and previous-schema migration paths are tested for SQLite and an injected PostgreSQL driver. - Invalid/unknown/checksum-tampered migration histories fail startup. - PostgreSQL migration rollback preserves the previous applied version in the injected-driver contract test. - Failure injection proves fill/order aggregates and position/event pairs roll back atomically. - A fresh Python process observes persisted plans, approvals, orders, fills, positions, protection, PnL, position events, and idempotency evidence. - Concurrent idempotency claims produce one winner. Duplicate client-order creation produces one committed order/event pair. Scoped lock contention and stale fencing-token release fail safely. - Database startup failure raises a diagnostic server-side error and does not fall back to memory or an alternate database. ## Adjacent findings and dispositions 1. **Position events were missing.** Closed with SQLite migration `012_position_events.sql`, PostgreSQL migration `004_position_events.sql`, transactional repository writes, and lifecycle tests. 2. **Legacy direct Paper execution retained module/JSON authority.** Closed by routing the compatibility API through relational repositories and removing the singleton/JSON book. 3. **Realized PnL was not atomically coupled to close fills.** Closed by updating the daily risk ledger inside the close-fill transaction. 4. **Protective orders remained active after a confirmed full close.** Closed by cancelling matching active/submitted/ambiguous protection after durable close confirmation. 5. **The authority audit only detected obvious container literals and missed class-instance singletons.** Closed with AST-based module-state checks and negative fixtures for a position-book singleton, legacy financial JSON path, runtime legacy-store import, and browser approval storage. ## Remaining external-only verification A real disposable PostgreSQL instance is not available in this workspace. The backend, migrations, advisory-lock protocol, connector injection, SQL compatibility, failure rollback, and operator commands are implemented and tested locally; an actual `psycopg` migration/backup/restore smoke run remains a Desktop/CI verification item. This does not enable Testnet or Live execution. ## Audit conclusion No known critical process-local, browser-local, flat-file, transaction-integrity, restart, or multi-worker authority gap remains in the implemented Paper path. Phase 2 file implementation is complete except for the named disposable-PostgreSQL smoke verification. **Note (2026-07-27):** LLM-facing mutation tools were re-verified under plugin-based registration; the three mutation handlers remain hard-reject stubs and are not registered in the runtime toolset.