> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parmanasystems.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Chapter 23: History and Open Questions

## What this chapter is

Every other chapter in this handbook describes what Parmana does today. This one describes
how it got there: the real incidents, the corrections, the things that were tried and
reversed, and the questions that remain genuinely open rather than quietly resolved. The
two files this chapter draws from most, and which a reader should treat as the primary
sources rather than this summary, are `docs/VERIFICATION-GAPS.md` (a dated incident and gap
log going back to the original external audit) and `docs/CLAIMS.md` (the audit ledger, one
entry per claim with cited evidence). This chapter is the narrative connecting them, written
by reading both directly rather than trusting either blindly, and by direct, firsthand
knowledge of the two most recent sessions, both from 2026-09-15/16.

## Why a history chapter exists at all

A codebase that has been audited, found wanting, fixed, and re-audited multiple times has a
choice about how to present that history: quietly rewrite the record so it looks like
everything was always correct, or keep the record honest, including the mistakes. This
codebase has consistently chosen the second option. `docs/VERIFICATION-GAPS.md`'s own
structure, gaps organized by the session that found and closed them, with a dedicated
"Decision required" section for things nobody has decided yet, exists specifically so a
reader can tell the difference between "this was always solid" and "this broke once, here
is exactly how, and here is what changed." Chapter 17 of the older `docs/book/` calls this
citation integrity; whatever it is called, the discipline is the same: a claim without a
file and line citation is not trusted, in this document or in the ones it draws from.

## The broad shape of the project's history

Rather than repeating every entry in `docs/VERIFICATION-GAPS.md` (over 2,900 lines as of
this writing, covering audits from an original external review through at least seven
distinct closure sessions), this section names the eras and points at where to read more:

* **The original external audit (dated July 2026 and earlier).** The root-level
  `docs/000-CONSTITUTION.md` through `docs/017-CONFORMANCE.md`, plus `ARCHITECTURE.md`,
  `SPECIFICATION.md`, `TRUST_MODEL.md`, `GUARANTEES.md`, and `PROOFS.md` date from this
  period. They are frozen, not deleted, and should not be read as current, per `docs/book/`'s
  own README.
* **2026-07-17 audit closeout session.** Nine tasks closing findings from a July 16 external
  audit. See `docs/VERIFICATION-GAPS.md`'s "Gaps closed in the 2026-07-17 audit closeout
  session" section.
* **Phase 3D certification session.** A further, larger closure pass; see that session's own
  heading in `docs/VERIFICATION-GAPS.md`.
* **2026-09-07 through 2026-09-14: a run of focused sessions** covering production
  readiness, real-deployment verification, PQC production-readiness remediation, and
  execution-audit-trail hardening, each with its own dated section in
  `docs/VERIFICATION-GAPS.md`.
* **Gaps 35 through 40 (audit-artifact-driven, same day as the gaps-24-34 pass).** These
  closed detection-then-prevention gaps in Policy Governance specifically: a five-minute
  periodic integrity re-check (gap 36), a legacy-policy backfill script (gap 39), and
  execution-time prevention itself (gap 40, `PolicyExecutionVerifier`, feature-flagged off
  by design at the time it was built, since every real production policy was still
  `PENDING_APPROVAL`). Chapter 7 of this handbook covers what changed about that precondition
  on 2026-09-16.
* **2026-09-15/16: the AWS KMS migration and Policy Governance completion.** The two most
  recent sessions, covered in detail below, since they are the freshest and least likely to
  already be reflected accurately anywhere else.

## The 2026-09-15 AWS KMS gateway signing migration

The gateway's signing key moved from a local file-based key to AWS KMS, authenticated via
Vercel OIDC rather than static AWS credentials. Six real bugs were found and fixed in the
course of this migration; `docs/operations/2026-09-15-kms-migration-troubleshooting-guide.md`
is the detailed account. The one worth naming specifically here, because of how it was
found: `SignerKeyProviderAdapter` (packages/crypto) had a divergence between the key used to
*sign* and the key used to *verify*, a signing/verification key mismatch that would have
silently produced signatures nothing could verify, had it reached production unnoticed. It
is documented as G-48/G-49 in `docs/VERIFICATION-GAPS.md`, and Chapter 3 of this handbook
covers the cryptography layer this fix lives in.

Two other findings from the same session are directly relevant to chapters elsewhere in
this handbook and are documented as their own tutorials rather than just prose:
`examples/tutorials/113-kms-key-id-resolution` (AWS KMS rejects a bare logical key ID like
`"default"`; a resolver maps it to the alias/ARN/key-ID shape KMS actually accepts) and
`examples/tutorials/115-per-limiter-rate-limit-stores` (a shared rate-limit `Store` instance
reused across two limiters, which `express-rate-limit`'s own contract disallows, including a
documented correction to an initially wrong diagnosis: the observed 500 error was blamed on
the store-reuse warning by proximity in a log, when the real cause was the separate
signing/verification key divergence above; the correction is kept visible rather than
silently rewritten, matching this codebase's own stated discipline).

## The night of 2026-09-16: closing the Policy Governance backfill

All ten real production policies had sat `PENDING_APPROVAL` since 2026-08-19, waiting on a
genuinely distinct second human checker (`SameActorCannotApproveOwnChangeError` meant the
original proposer could never approve their own proposals). This session provisioned that
checker identity (`policy-reviewer-1`) and approved all ten, plus four more pre-existing
policies that had never been proposed through the governance system at all. Chapter 7
covers the mechanism; this section covers what went wrong along the way, since every one of
these was a genuine, previously-unexercised bug, not a repeat of something already known.

1. **`EROFS` on the very first live approval.** `PolicyChangeApprovalService.approve()`
   writes the newly-approved policy content via `PolicyRepository.save()`.
   `FilePolicyRepository` does that with a local filesystem write. Vercel's serverless
   Functions run on a read-only filesystem. Because no real approval had ever been attempted
   against a live, deployed instance before this session (every prior approval attempt in
   this codebase's history was against local dev or test environments), this code path had
   simply never yet executed for real. The first time it did, in production, it failed
   immediately. Fixed with a new `SupabasePolicyRepository`
   (`packages/policy/src/SupabasePolicyRepository.ts`, migration
   `20260916060000_add_policies_table.sql`), used whenever a real database is configured.
2. **An eager-construction bug in the first version of that fix.** The first attempt at
   wiring `SupabasePolicyRepository` into `packages/api/src/application.ts` constructed it,
   and the `PostgresPoolFactory` singleton pool underneath it, at module import time rather
   than on first actual use. This violated a discipline already established elsewhere in
   this exact codebase (`packages/api/src/repositories.ts`'s `lazyRepository`, closing gap
   G-15, whose own comment states the same rule: importing a module must never itself
   construct a live database connection). The concrete symptom: constructing the pool
   eagerly meant it connected using whatever `DATABASE_URL` was live at import time, before
   `examples/tutorials/89-readiness-probe`'s third scenario (a deliberately unreachable
   database) could ever configure it differently, so that test's `NOT_READY` assertion
   silently became `READY`. Fixed by making the construction lazy, mirroring
   `repositories.ts`'s own pattern exactly.
3. **`PostgresPoolFactory` hanging indefinitely against an unreachable database**, discovered
   via the same tutorial, instead of failing fast. Fixed by adding
   `connectionTimeoutMillis: 5000` to the pool configuration.
4. **Stale content in the original 2026-08-19 proposals.** `pending_policy_changes` stores a
   one-time snapshot of proposed content, taken when the proposal is created, never
   re-checked against the live file while the proposal sits open. A month is an unusually
   long time for a proposal to remain open, and in that time the live policy files gained a
   documentation field (`unboundSignalReasons`, harmless) and, for two policies specifically
   (`connector-capability`, `customer-refund`), a functional field (`boundSignals`, which
   `SignalIntentBinder` needs to derive `paymentAmount`/`refundAmount` from a request's own
   parameters rather than treating them as needing independent verification). Approving the
   stale content as originally proposed would have quietly persisted that gap. Caught during
   review, not by any automated check, and fixed by re-proposing and re-approving all
   fourteen policies with their current, correct content, see Chapter 7 for the verification
   step (`scripts/verify-policy-changes-approved.ts --full-scan`) that confirms the fix.

None of these four were regressions of something previously working. Each was code, or a
data path, that had genuinely never been exercised against a real deployment before this
session, caught the first time it actually ran.

## Genuinely open questions

These are unresolved by design, not oversights. Each is documented in full, with real
options weighed, in `docs/VERIFICATION-GAPS.md`'s "Decision required" section; this is a
short index, not a replacement for reading the original entries.

* **D-2 (partially resolved).** Hybrid/post-quantum signatures are wired for Trust Records
  and Receipts, opt-in via `CRYPTO_MODE`, but not for `RuntimeAuthorizationSigner`, gateway
  attestation signing, or connector-signing call sites. Deliberately deferred to a
  fast-follow milestone, not a rejection.
* **D-3.** `OverrideService` exists, is presumably complete, but is not wired to any real
  HTTP route and is not exercised by tests beyond a storage-layer bypass. Undecided whether
  to wire it in or mark it explicitly future-scope.
* **D-4.** HubSpot's `TRUSTED_APPROVAL_ISSUERS` is an empty array by design (fail-closed),
  meaning every `preAuthorizedForAmountChange` claim currently fails closed since no real
  approver key has been provisioned. A proposed hardcoded dev key was explicitly rejected
  during review as inconsistent with this codebase's own never-commit-a-private-key
  convention. Status: undecided.
* **D-5.** Upstream authorization verification (`NF-001-UPSTREAM-AUTHORIZATION-VERIFICATION.md`)
  is explicit future scope: today's authorization boundary is caller identity plus
  principal/capability scoping, not an independent signature on the `Authority`/
  `Authorization` domain objects themselves. This becomes a real gap only for a delegation
  scenario (multi-party approval, an external OAuth/SAML/risk-service authorization source),
  and work has deliberately not started pending a real trigger.
* **D-6.** The CI job that would prevent an unapproved policy file from merging
  (`scripts/verify-policy-changes-approved.ts`, run by `.github/workflows/ci.yml`'s
  `verify-policy-approvals` job) is real and fail-closed, but is not configured as a
  *required* GitHub branch-protection check. Attempting to enable it during a real session
  failed with `403 Upgrade to GitHub Pro or make this repository public`, an externally
  imposed constraint (private-repository plan limits), not a gap in this codebase's own
  logic. See `docs/CLAIMS.md` §2.26's "Preventive Git-layer enforcement" entry for the full
  account.
* **The internal-vs-external policy authoring question.** Should Parmana be the system of
  record for policy approval at all, or should policies be authored and approved in an
  external system, with Parmana staying strictly read-only/enforcement-only? Nothing in the
  codebase picks a side; the maker-checker system described in Chapter 7 exists because
  policy authoring was previously outside any governance surface at all, not because
  building it internally was compared against and preferred over the external alternative.
* **`POLICY_EXECUTION_VERIFICATION_ENFORCED` remains `false`.** As of this session, every
  real production policy has a genuine, verified approval record, closing the precondition
  that originally justified leaving this flag off. The flag itself was deliberately left
  unchanged as part of closing that precondition; turning it on is reserved as its own,
  separate, later decision (`docs/operations/policy-approval-runbook.md` Part 5), not
  something to do as a side effect of finishing the backfill.

## How to keep this chapter honest going forward

The same rule that produced this chapter applies to updating it: a new incident gets added
here (or to `docs/VERIFICATION-GAPS.md`, whichever is the more precise home for it) with a
real file citation and an honest account of what broke and why, not a summary that makes the
codebase look more finished than it is. If a claim in this chapter is ever found to be wrong
against the actual current source, the correction belongs here, visible, the same way the
rate-limiter/signing-key misdiagnosis in the 2026-09-15 session is kept visible in
`examples/tutorials/115-per-limiter-rate-limit-stores/README.md` rather than quietly
rewritten.
