From e724e0cae06b04f1225fdcab5f97346728c4771e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 20:10:56 +0900 Subject: [PATCH 01/58] docs: establish protected-main product requirements --- docs/product/PRD.md | 126 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 docs/product/PRD.md diff --git a/docs/product/PRD.md b/docs/product/PRD.md new file mode 100644 index 000000000..905a3906c --- /dev/null +++ b/docs/product/PRD.md @@ -0,0 +1,126 @@ +# Product Requirements Document + +## Document authority + +This PRD defines the product contract for `pg-llm-batch`. Repository behavior is authoritative only after it is integrated into the protected default branch. Pull requests, issue plans, historical branches, generated merge commits, workflow artifacts, and review commentary are evidence or work-in-progress, not shipped product truth. + +Use these status terms consistently: + +- **IMPLEMENTED-ON-PROTECTED-MAIN** — present in the protected default-branch tree and covered by its repository contract. +- **ACTIVE-PR** — implemented or being repaired in an open pull request; not shipped. +- **PARTIAL** — a protected-main primitive exists, but an end-to-end product capability still has an explicit gap. +- **PLANNED** — accepted requirement without an integrated implementation. +- **SUPERSEDED** — historical implementation or proposal that is not current product authority. + +## Product purpose + +`pg-llm-batch` is a standalone and embeddable PostgreSQL-centered engine for preparing, submitting, observing, and retrieving bounded LLM Batch API workloads. It is intended for operators and host applications that need durable batch state, deterministic token/resource accounting, explicit tenant boundaries, bounded provider I/O, and acquisition-grade operational evidence without coupling the package to one gateway, scheduler, web application, or ContextualWisdomLab host service. + +## Primary users + +1. **Platform operators** running the package as an independently deployable service or Compose component. +2. **Application/platform engineers** embedding the Python package and PostgreSQL schema in a larger product. +3. **Multi-tenant host services** that authenticate and authorize callers before supplying a trusted `tenant_scope`. +4. **Reliability and security reviewers** who need deterministic failure boundaries, migrations, rollback, audit evidence, security gates, SBOM/provenance evidence, and bounded diagnostics. + +## Product outcomes + +The product must let a qualified host: + +- count model tokens through the reviewed PostgreSQL tokenizer boundary; +- prepare JSONL batch payloads under finite token, byte, and record limits; +- preserve package-owned payloads and lifecycle state durably in PostgreSQL; +- submit, poll, wait, cancel, and retrieve through validated OpenAI-compatible Batch API clients; +- operate in exact `standalone` mode or with a trusted tenant-qualified lifecycle identity; +- recover or reconcile provider lifecycle state without introducing a second database-side networking authority; +- prove package quality, security, reproducibility, release-artifact identity, and rollback assumptions through repository evidence. + +## Protected-main capability contract + +| Capability | Status | Product requirement | +| --- | --- | --- | +| PostgreSQL token counting and bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | Token/resource accounting and batch partitioning remain deterministic and finite. | +| Disk-free package payload persistence | IMPLEMENTED-ON-PROTECTED-MAIN | Package-owned JSONL payloads persist in PostgreSQL and are validated before credential/provider effects. | +| OpenAI-compatible upload/create/poll/wait/cancel/retrieve | IMPLEMENTED-ON-PROTECTED-MAIN | Provider destinations, resource identifiers, control responses, downloads, retries, and timeouts remain bounded and validated. | +| Standalone durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | Existing standalone users retain source-compatible durable lifecycle behavior. | +| Tenant-qualified durable lifecycle with forced RLS | IMPLEMENTED-ON-PROTECTED-MAIN | Tenant scope comes only from a trusted host authorization boundary; direct arbitrary SQL remains outside the isolation guarantee. | +| Durable resumable result checkpoint/CAS storage | IMPLEMENTED-ON-PROTECTED-MAIN | PostgreSQL supplies tenant-qualified durable checkpoint authority and conflict detection; this is not a distributed exactly-once claim. | +| Redacted readiness reporting | IMPLEMENTED-ON-PROTECTED-MAIN | Public readiness evidence does not disclose arbitrary lower-layer diagnostic content. | +| Scheduler-independent bounded provider reconciliation primitive | IMPLEMENTED-ON-PROTECTED-MAIN | A host can submit a finite, validated candidate set for polling/retrieval through the existing bounded provider client; candidate discovery, scheduling, and cross-process lease ownership remain outside this primitive. | +| Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative before it can become product truth. | +| Cross-process reconciliation single-flight | ACTIVE-PR | Concurrent workers must not race the same tenant/provider identity; merge eligibility remains governed by live repository policy. | +| Existing-volume legacy `http` / `pg_cron` retirement | ACTIVE-PR | Existing deployments need fail-closed, reversible migration evidence before compatibility packages can be removed. | +| First-class OpenTelemetry installation extra | ACTIVE-PR | Ordinary installs must remain telemetry-dependency-free; the optional package graph must be locked and reproducible. | +| Autonomous package-owned reconciliation worker with crash/restart completion semantics | PARTIAL | Protected main has reconciliation and durable state primitives, but does not yet claim a complete package scheduler/worker control plane. | +| Durable result application coupled to checkpoint advancement | PARTIAL | Existing checkpoint and retrieval primitives must not be described as end-to-end exactly-once result application until a reviewed coupling contract is integrated. | + +## Functional requirements + +### FR-1: Batch preparation + +The engine shall resolve an existing batch identity, select eligible requests, count tokens through the package tokenizer boundary, partition work under explicit provider/resource limits, and persist payload/file/line/request assignment state atomically for one preparation operation. Re-running a supported preparation path must not silently duplicate assignment or corrupt package-owned state. + +### FR-2: Provider interaction + +All provider operations shall use validated endpoint configuration and finite response/download budgets. Automatic retries are restricted to reviewed idempotent GET behavior. Side-effecting provider POST operations shall not gain implicit retry authority. Credentials and provider content shall not be copied into ordinary diagnostics. + +### FR-3: Durable lifecycle and tenancy + +The durable business identity is tenant-qualified where tenancy is enabled. The package shall validate tenant scope before persistence/provider effects that rely on it, bind scope through parameterized transaction-local PostgreSQL context, and keep forced row-level security enabled for application roles. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access are administrative escape hatches and are not part of the tenant isolation guarantee. + +### FR-4: Reconciliation and recovery + +Reconciliation shall be finite, deterministic, payload-free in its operational evidence, and use the same validated provider client boundary as normal operations. Candidate discovery, concurrency control, scheduling, and result-application semantics must be explicit capabilities rather than inferred from polling code. Provider-success/database-failure cases must remain observable recovery states rather than being rewritten as if the provider effect never occurred. + +### FR-5: Persistence integrity + +Package-owned database rows shall use descriptive two-or-more-word `snake_case` object names where applicable, explicit durable identities, parameterized SQL, and migrations that are idempotent or have a documented one-way boundary. Schema copies maintained for package and Docker initialization shall remain synchronized where the repository contract requires it. Malformed durable payload/state shall fail closed before downstream credential or provider effects when correctness depends on that state. + +### FR-6: Configuration and secrets + +PostgreSQL-backed configuration and encrypted-secret support remain available for standalone use. Environment variables are bootstrap transport only where explicitly documented. Embedding hosts may inject credential providers without changing provider protocol semantics. The package shall not invent an external secret-management product dependency. + +### FR-7: Observability and diagnostics + +Operational telemetry is opt-in. Bounded operation/outcome vocabularies may be emitted; prompts, provider response bodies, credentials, arbitrary endpoint aliases, resource IDs, and arbitrary exception text are not telemetry attributes. Public readiness and ordinary errors shall use bounded categories when lower-layer text could contain sensitive data. + +### FR-8: Standalone and modular deployment + +The package shall remain usable without `contextual-orchestrator`, `naruon`, or another CWL repository. Host services may provide authentication, tenant routing, secret resolution, gateway/model routing, OpenTelemetry export, or scheduling, but those integrations shall not become hidden standalone requirements. + +## Non-functional requirements + +### Quality + +Owned production Python must maintain exact 100% statement and branch coverage and complete public docstrings under the repository's configured gates. Supported validation includes Python 3.10, 3.12, and 3.14 plus realistic PostgreSQL/container integration where behavior depends on PostgreSQL. + +### Security and privacy + +Security-sensitive validation fails closed. Secrets, DSNs, prompt/provider content, unvalidated identifiers, and arbitrary lower-layer exception text must not be retained in logs or review evidence merely for debugging. Repository controls should support SOC 2 / CSAP evidence preparation without claiming certification. + +### Reliability + +Network, response, retry, wait, candidate-scan, payload, and release-evidence operations must be explicitly bounded. Recovery and rollback must be documented before migrations or release changes are considered complete. Queued, skipped, cancelled, absent, stale, predecessor-head, synthetic-merge-only, or infrastructure-failed evidence is not success for an exact source head. + +### Interoperability + +Provider interaction stays OpenAI-Batch-compatible behind a validated Python client seam. Embedding hosts can provide credentials and control-plane context without changing the package's durable/provider semantics. + +### Packaging and release + +Dependencies must be locked/reproducible according to repository policy. Release acceptance must include required quality, security, package/container, SBOM, provenance, artifact-identity, rollback/recovery, and governance evidence on the exact integrated protected head. A release is not implied by a version string or a successful pull request. + +## Explicit non-goals + +- Replacing host authentication or authorization. +- Treating PostgreSQL RLS as a credential or as SQL-injection prevention. +- Making provider payload/model output an authority for tenant or endpoint selection. +- Providing an unbounded general-purpose HTTP proxy. +- Reintroducing provider networking or independent scheduling inside PostgreSQL. +- Claiming distributed exactly-once processing without an integrated transaction/recovery contract spanning every external effect. +- Requiring a specific ContextualWisdomLab host service for standalone operation. +- Claiming SOC 2, CSAP, or other certification solely from repository controls. + +## Product acceptance boundary + +A product capability moves to **IMPLEMENTED-ON-PROTECTED-MAIN** only after its unchanged source has satisfied the live ruleset, required exact-head CI/security/coverage/package/provenance/release checks, valid review findings are resolved, and the resulting tree is integrated into the protected default branch. Documentation must then be updated to move the capability out of `ACTIVE-PR`, `PARTIAL`, or `PLANNED`; historical evidence must not be transferred as if it were proof for a different head. \ No newline at end of file From 25d7eacf4c40e3390c5f6223e223daed60e1ec25 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 20:12:38 +0900 Subject: [PATCH 02/58] docs: establish protected-main technical requirements --- docs/product/TRD.md | 148 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 docs/product/TRD.md diff --git a/docs/product/TRD.md b/docs/product/TRD.md new file mode 100644 index 000000000..4a4249ab0 --- /dev/null +++ b/docs/product/TRD.md @@ -0,0 +1,148 @@ +# Technical Requirements Document + +## Document authority + +This TRD defines technical invariants for `pg-llm-batch`. It distinguishes protected-main behavior from work that is only present in an active pull request. The repository's live code, schema, tests, ruleset, and exact-head evidence remain stronger authority than historical branches, stale PR prose, predecessor checks, or generated merge commits. + +Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. + +## System boundary + +`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It may run standalone or be embedded by another service. The package owns batch preparation, package persistence, validated provider Batch API access, durable lifecycle projection, resumable checkpoint storage, and bounded reconciliation primitives. It does not own host authentication, business authorization, ingress/WAF, infrastructure TLS policy, external secret-manager choice, global OpenTelemetry configuration, or a cross-system distributed transaction. + +## Component contract + +| Component | Protected-main responsibility | Prohibited authority | +| --- | --- | --- | +| `token_counter.py` | resolve reviewed tokenizer metadata and call `pg_tiktoken` for token accounting | provider credentials, tenant authorization, provider I/O | +| `orchestrator.py` | select queued requests, partition under limits, persist package payload/file/line/request assignments | provider protocol and retry policy | +| `batch_api_client.py` | validate provider destination and remote identifiers; upload/create/poll/wait/cancel/retrieve under finite budgets | tenant authentication, scheduler ownership | +| `durable_client.py` | compose provider operations with durable lifecycle ordering/persistence | authenticating or authorizing host tenants | +| `db.py` | schema application and parameterized persistence/read helpers | database-side provider networking | +| `checkpoint_store.py` | tenant-qualified PostgreSQL checkpoint/CAS operations and conflict semantics | distributed exactly-once claims | +| `reconciliation.py` | finite host-selected polling/retrieval pass using the existing validated client surface | candidate discovery, scheduling, cross-process leasing | +| `config.py` | PostgreSQL-backed configuration and encrypted secret storage for standalone composition | prescribing an embedding host's external secret manager | +| `observability.py` | opt-in bounded traces/metrics around reviewed operations | configuring global SDK/exporter/resource policy | +| `health.py` | readiness aggregation and redacted public health response | general-purpose web serving or arbitrary diagnostic reflection | +| `cli.py` | standalone operator composition and bounded input surfaces | higher-level workflow orchestration | + +## Runtime architecture + +### Batch preparation + +1. Resolve a supported package batch identity. +2. Read eligible unassigned requests from PostgreSQL. +3. Count model tokens through the reviewed PostgreSQL tokenizer boundary. +4. Partition requests in memory under explicit batch token, byte, record, and provider limits. +5. Under one package preparation transaction, persist virtual payloads, batch-file rows, JSONL line rows, request assignments, and aggregate totals in deterministic order. +6. On failure before commit, roll back the package preparation transaction rather than exposing a partially committed preparation from that invocation. + +Package-generated provider payloads are represented by `memory://` references and are reconstructed from PostgreSQL rather than written to a package-owned local payload file. + +### Provider I/O + +Provider gateway URLs and endpoint aliases are configuration inputs but are untrusted until validated by the applicable package boundary. Production gateway destinations require HTTPS; only explicitly reviewed loopback development HTTP destinations are accepted. Userinfo, query, fragment, whitespace, malformed port, or other forbidden URL forms must fail before credentials are used. + +Control-plane responses are consumed through a finite decoded-byte budget and strict UTF-8/JSON parsing. Provider output/error files are streamed in finite chunks with an independent decoded-byte ceiling before JSONL parsing. The client must fail closed when an adapter cannot provide the bounded streaming interface required by the operation. + +Automatic provider retry is limited to reviewed idempotent GET operations and the exact default status set `{408, 425, 429, 502, 503, 504}`. TLS handshake, certificate, and fingerprint failures are not automatically retried. Upload/create/cancel POST operations remain single-attempt unless a separately reviewed provider-specific contract is introduced. + +### Durable lifecycle tenancy + +Standalone lifecycle data uses the exact `standalone` tenant scope. Tenant-aware hosts use a trusted host-selected scope after authentication and authorization. Provider metadata, request payloads, model output, transport headers, endpoint aliases, and provider resource identifiers never choose tenant authority. + +The durable lifecycle identity is: + +```text +(tenant_scope, endpoint_alias, remote_batch_id) +``` + +Package reads/writes bind tenant scope with parameterized transaction-local `set_config`. The schema enables and forces PostgreSQL row-level security for tenant-qualified lifecycle state. Production application roles must be `NOSUPERUSER NOBYPASSRLS`. A role that can execute arbitrary SQL can choose arbitrary custom setting values; therefore generic arbitrary SQL access is explicitly outside the package isolation guarantee. + +### Durable result checkpoints + +Protected main contains tenant-qualified durable result checkpoint storage with compare-and-swap/conflict semantics. The checkpoint store can participate in a caller-owned PostgreSQL transaction where the caller's durable result application is in the same database transaction. The mere existence of this store does not prove exactly-once application across provider/network/database boundaries. + +Checkpoint counters, offsets, and identities must validate before mutation. Conflicting writes fail explicitly rather than silently overwriting a newer checkpoint. Rollback/recovery tests and schema parity are part of the storage contract. + +### Reconciliation + +Protected main supplies a scheduler-independent `reconcile_batch_candidates(...)` primitive. A host supplies candidate identities and a finite `max_jobs` budget. The primitive validates candidates, bounds scanning/work, polls through the validated provider client, retrieves completed jobs through that same client, and returns payload-free finite outcome/error categories. + +The host still owns candidate discovery, tenant authorization, scheduling, and cross-process concurrency. Durable candidate discovery and tenant-qualified advisory single-flight are **ACTIVE-PR** surfaces; neither is treated as shipped until protected-main integration. Package-owned autonomous scheduling, crash/restart completion semantics, terminal-work retirement after durable result application, and an end-to-end exactly-once worker remain **PARTIAL** or **PLANNED** capabilities. + +## Persistence requirements + +### Naming and schema ownership + +New package-owned database objects use descriptive two-or-more-word `snake_case` names where applicable. SQL is parameterized; identifiers are not constructed from unvalidated user/provider text. Packaged schema and Docker initialization copies that represent the same contract must remain synchronized by regression tests. + +### Migration behavior + +Migrations must have an explicit compatibility and rollback boundary. Tenant migrations preserve legacy data under `standalone`, avoid a committed intermediate RLS-bypass state, restore forced RLS atomically, and remain idempotent where documented. Existing-volume retirement of legacy `http` / `pg_cron` authority is **ACTIVE-PR** and may not be described as shipped merely because fresh initialization no longer depends on SQL-side provider networking. + +### Data integrity + +Package-owned persisted virtual JSONL is canonical state, not a best-effort cache. Malformed shape, line count, framing, duplicate JSON members, non-finite numeric forms, or invalid record type fail closed through bounded package errors. Local payload integrity validation occurs before provider credentials/provider I/O where the provider effect relies on that payload. + +Durable provider/resource identifiers and tenant identities are validated before they become persistence or authorization inputs. Database/query failures must not be silently reclassified as an authoritative no-row result when correctness depends on distinguishing those cases. + +## Security and privacy requirements + +### Secrets + +Standalone provider configuration and encrypted secrets are PostgreSQL-backed. Environment variables are limited to explicitly documented bootstrap transport such as the database DSN and optional encryption key. CLI secret entry uses no-echo prompting or bounded standard input rather than plaintext process arguments. Embedding hosts may supply another credential provider through the supported seam. + +### Diagnostic confidentiality + +Errors, logs, telemetry, check evidence, and public readiness must avoid DSNs, credentials, prompts, provider bodies, arbitrary SQL/provider exception text, unvalidated identifiers, and dynamic exception-class names where those values are not required for operation. Failure categories intended for public/operational evidence use bounded vocabularies. + +### Tenant boundary + +RLS augments a trusted host authorization boundary; it is not itself authentication, a credential, or SQL-injection prevention. Administrative database identities are outside the ordinary tenant guarantee. Pooling code must not leak transaction-local tenant context between logical operations. + +### Provider boundary + +Provider URLs, statuses, IDs, headers, JSON, JSONL, retry guidance, and metadata are untrusted external input. Validation occurs before the downstream effect that relies on that value. Model/provider output never grants tenant, endpoint, credential, or filesystem authority. + +## Observability requirements + +OpenTelemetry support is opt-in. Base installations must not require OpenTelemetry packages solely to use normal batch functionality. Operation names, outcomes, and error categories are finite. Telemetry attributes exclude endpoint aliases, provider URLs, resource identifiers, credentials, metadata, prompts, and provider response bodies. + +A first-class packaging extra for OpenTelemetry is **ACTIVE-PR** until its exact generated dependency lock is committed normally, temporary materialization machinery is removed, and final package/install/release gates succeed. + +## Health and operability + +Readiness covers the required PostgreSQL/tokenizer/configuration boundary and returns redacted public evidence. A failing dependency must not cause arbitrary lower-layer text to be reflected to a caller. Docker/container health and package health semantics must remain aligned. + +Operational migrations require backup/preflight/acceptance/recovery documentation before release. A recovery instruction must preserve package and operator-owned state; destructive `CASCADE`, hidden history rewrite, or deletion of unknown operator objects is not an acceptable shortcut. + +## Concurrency requirements + +Batch preparation uses database coordination/transactionality appropriate to its package-owned state. Durable lifecycle writes use explicit ordering/conflict semantics. Any cross-process reconciliation exclusion must be tenant-qualified, non-blocking or finitely bounded, exception-safe, and clear about whether it is transient session state or durable lease state. Session advisory locking must never be promoted into a durable lease or distributed exactly-once claim. + +## Testing requirements + +Every source defect follows realistic RED → narrow fix → GREEN → focused/full validation. Required repository evidence includes: + +- Python 3.10, 3.12, and 3.14 where configured; +- exact 100% owned production statement and branch coverage; +- public docstring coverage; +- lint/static checks; +- realistic PostgreSQL integration for SQL/RLS/migration/concurrency behavior; +- package and container installation/health validation; +- migration idempotency and rollback/recovery coverage where applicable; +- confidentiality regressions that inspect full exception/traceback surfaces when relevant; +- security scanning and SAST; +- dependency-lock and packaging reproducibility; +- release acceptance, artifact identity, SBOM, and provenance evidence required by the live repository contract. + +Queued, pending, skipped, cancelled, absent, neutral, stale, predecessor-head, synthetic-merge-only, status-only, infrastructure-failed, or rate-limited evidence is not exact-head success. + +## Release requirements + +A release may originate only from the exact integrated protected head after all live required quality, security, review, migration, rollback/recovery, operational, packaging, provenance, and release-acceptance gates are terminal-success. Versioning and CHANGELOG updates are followed by publication and artifact verification. Repository control evidence may support SOC 2 / CSAP readiness but must not be represented as certification. + +## Documentation requirements + +Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. \ No newline at end of file From 6f8e6c951b81694bd2bec8048897489943c5ae53 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 20:38:13 +0900 Subject: [PATCH 03/58] docs: add canonical documentation fitness inventory --- docs/DOCUMENTATION_FITNESS.md | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 docs/DOCUMENTATION_FITNESS.md diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md new file mode 100644 index 000000000..c7306649d --- /dev/null +++ b/docs/DOCUMENTATION_FITNESS.md @@ -0,0 +1,48 @@ +# Documentation Fitness + +## Authority and status model + +This inventory evaluates the documentation graph against the exact protected-main tree `d0a4b30be1f46536e352443309f3a35533156767`. It does not promote pull-request content into shipped truth. The canonical status vocabulary is shared with `docs/product/PRD.md` and `docs/product/TRD.md`: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. + +A document is *fit* only when it states the correct authority boundary, is consistent with the protected-main code/schema/tests it describes, avoids transferring predecessor or active-branch evidence into shipped claims, and gives an operator or reviewer enough information to use, verify, recover, or reject the relevant behavior safely. + +## Current fitness matrix + +| Documentation surface | Status | Fitness assessment | Required next action | +| --- | --- | --- | --- | +| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point, but it is not the sole product/architecture authority and must not absorb transient PR/check state. | Keep beginner-readable; update bounded shipped capability changes after merge. | +| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, interoperability, and verification, but does not by itself form a complete system/UML/data model. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file. | +| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states. | Validate exact-head docs gates and integrate only through normal PR governance. | +| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries and release/testing invariants are explicit. | Validate exact-head docs gates and integrate only through normal PR governance. | +| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist, but there is no canonical ADR index describing numbering gaps, status, supersession, and protected-main applicability. | Add an ADR index on this canonical branch after checking active ADR writers. | +| `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | +| `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Durable lifecycle/tenant behavior has detailed protected-main documentation. | Keep synchronized with tenant/RLS and lifecycle migrations. | +| Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | +| Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation, but it is not shipped and its exact-head acceptance remains separate. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | +| OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | +| Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | +| Atomic durable result application | ACTIVE-PR | Draft #194 is RED-only at its initial head and is not product truth. Protected main still has a PARTIAL end-to-end result-application capability. | Keep PARTIAL until test-first implementation, exact-head gates, review, and merge complete. | +| Runtime config/schema provisioning separation | ACTIVE-PR / BLOCKED | Draft #193 is RED-only and currently frozen because a source-affecting no-PR config branch remains live writer evidence. | Do not describe the least-privilege runtime-store repair as shipped or proceed through competing source ownership. | +| Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | +| Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | +| Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | +| UML/component/sequence views | PLANNED | Root architecture is prose-first; no canonical UML authority is present. | Add textual Mermaid/PlantUML-compatible component and critical sequence diagrams after active source contracts stabilize. | +| ERD / schema model | PLANNED | SQL and schema tests are authoritative, but no canonical ERD summarizes package-owned identities, tenancy, checkpoint state, and relationships. | Generate/maintain an ERD from protected-main schema; label migration-only/active-PR objects separately. | +| Standalone operator guide | PARTIAL | Operational instructions exist across README and topic docs, while #184 is adding migration-specific operability. There is no protected-main general `docs/OPERABILITY.md`. | Establish a general operator authority without racing #184's bounded migration changes. | +| Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | +| Licensing / third-party notices | PARTIAL | Apache-2.0 source headers and repository licensing exist, but acquisition diligence should explicitly trace package license, dependency/SBOM evidence, and third-party notice process. | Evaluate a concise licensing/compliance evidence index without claiming legal certification. | + +## Non-negotiable documentation invariants + +- Protected-main behavior is the shipped authority. Active PRs and historical branches are overlays, not proof of implementation. +- Exact contributor heads, generated merge commits, check IDs, and transient queue state belong in PR/review evidence, not durable architecture/product documents. +- Standalone operation and modular MSA embedding must be documented as co-equal supported boundaries; no ContextualWisdomLab host is a hidden runtime requirement. +- Tenant scope is selected only by a trusted authenticated/authorized host boundary. PostgreSQL RLS is defense in depth, not authentication or SQL-injection prevention. +- Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. +- Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. +- Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. +- Database object names, migration/rollback behavior, exact owned coverage requirements, Python-version acceptance, packaging/SBOM/provenance expectations, and bounded diagnostics must remain synchronized with repository tests and live governance. + +## Fitness gate for future canonical changes + +Before changing a canonical surface, refetch protected main, open PRs, non-default branches, the exact affected source/schema/test authorities, and any adjacent documentation writer. A documentation repair must not race a source-affecting writer whose behavior is still unsettled. After a product PR merges, update the canonical status classification from `ACTIVE-PR` or `PARTIAL` only when the protected-main tree contains the capability and the integrated evidence contract remains valid. \ No newline at end of file From 7a17e5fd61a333e7b3c18aa4602c743157952f37 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 20:38:57 +0900 Subject: [PATCH 04/58] docs: add protected-main traceability map --- docs/TRACEABILITY.md | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/TRACEABILITY.md diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md new file mode 100644 index 000000000..f8e5f3ea4 --- /dev/null +++ b/docs/TRACEABILITY.md @@ -0,0 +1,71 @@ +# Requirements Traceability + +## Purpose and authority + +This map ties the canonical PRD/TRD requirements to stable protected-main implementation, test, ADR, and operator evidence. It intentionally avoids workflow-run IDs, predecessor SHAs, generated merge commits, and review comments because those are transient verification records rather than durable requirements authority. + +The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. Rows marked **ACTIVE-PR** or **PARTIAL** are not shipped implementation claims. + +## Product-to-technical traceability + +| Requirement | Status | Primary protected-main implementation authority | Durable verification/documentation authority | Known gap or active overlay | +| --- | --- | --- | --- | --- | +| FR-1 deterministic bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/orchestrator.py`, `pg_llm_batch/token_counter.py`, package schema | preparation/token tests; `docs/idempotent-preparation.md`; `docs/schema-integrity.md` | No gap claimed by the canonical product contract. | +| FR-2 validated bounded provider interaction | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/batch_api_client.py` | provider URL/resource/retry/response-budget tests; `docs/batch-endpoints.md`; `docs/resource-identifiers.md`; ADR 0015 | Provider-specific widening requires a separately reviewed contract. | +| FR-3 standalone + tenant-qualified durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/durable_client.py`, `pg_llm_batch/db.py`, schema/RLS objects | tenant lifecycle/integration tests; `ARCHITECTURE.md`; `docs/remote-batch-lifecycle.md`; ADR 0002 | Arbitrary SQL, superuser, and BYPASSRLS remain outside the isolation guarantee. | +| FR-4 scheduler-independent bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation.py` | reconciliation tests and protected-main release gates | Discovery #190 and single-flight #191 remain ACTIVE-PR; autonomous worker semantics remain PARTIAL. | +| FR-4 durable reconciliation candidate discovery | ACTIVE-PR | none on protected main beyond existing lifecycle/read primitives | PR #190 exact-head evidence only | Not shipped; current review/infrastructure gates must not be transferred. | +| FR-4 tenant-qualified cross-process single-flight | ACTIVE-PR | none on protected main beyond existing DB primitives | PR #191 exact-head evidence only | Not shipped; qualifying independent approval remains a live-governance concern. | +| FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | Draft #194 is test-first ACTIVE-PR work; protected main does not claim end-to-end exactly-once application. | +| FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | +| FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | +| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Least-privilege separation of runtime store construction from schema provisioning is ACTIVE-PR #193 and currently writer-blocked. | +| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader `ValidationError` value-confidentiality work must not be inferred as solved from readiness alone. | +| FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | +| FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | +| Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | +| Python 3.10/3.12/3.14 validation | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | package metadata/workflow matrix | exact-head repository CI | Requires exact-head terminal success; queued/skipped/infrastructure-failed jobs are not proof. | +| Reproducible release evidence | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/release_evidence.py` and release workflows | ADR 0003; ADR 0004; release-evidence/artifact-identity tests | Release publication itself still occurs only from a fully accepted integrated protected head. | +| SBOM/provenance/artifact identity | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | release workflows/evidence helpers | release acceptance and artifact verification tests | No certification claim follows from repository evidence alone. | +| SOC 2 / CSAP evidence readiness | PARTIAL | security, tenancy, logging, release and governance controls | PRD/TRD/security tests/ADRs | Evidence readiness only; no external certification is claimed. | + +## Security and privacy traceability + +| Control objective | Protected-main authority | Verification evidence | Residual boundary | +| --- | --- | --- | --- | +| Trusted tenant selection | `AGENTS.md`, `ARCHITECTURE.md`, tenant validation in DB/durable-client paths | tenant-scope/RLS tests | Host authentication/authorization remains external. | +| RLS defense in depth | tenant-qualified schema and transaction-local scope binding | live PostgreSQL isolation/migration tests | Superuser/BYPASSRLS/arbitrary SQL are administrative bypasses. | +| Provider destination validation | `batch_api_client.py` | endpoint/URL tests | Host/network infrastructure TLS policy is external. | +| Bounded provider input | provider client + result streaming | response/download/JSONL/resource-budget tests | Provider authenticity is not established by payload validation. | +| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | External enterprise secret manager choice remains host-owned. | +| Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic validation value confidentiality remains an explicit separate gap where applicable. | +| Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | +| Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability are operational dependencies. | + +## Data and persistence traceability + +| Data family | Durable identity / authority | Principal protected-main documents | Recovery / non-guarantee | +| --- | --- | --- | --- | +| Tenant lifecycle state | `(tenant_scope, endpoint_alias, remote_batch_id)` | `ARCHITECTURE.md`, ADR 0002, `docs/remote-batch-lifecycle.md` | Tenant scope must come from trusted host authorization; direct SQL bypass is out of scope. | +| Result checkpoints | `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | ADR 0006, ADR 0007, `docs/result-streaming.md` | Prefix checkpoint is not provider authentication or whole-stream immutability; cross-system exactly-once is not claimed. | +| Package JSONL/payload state | package-owned schema identities and virtual payload references | PRD/TRD, schema-integrity and payload docs/tests | Persisted package data is canonical, not a disposable cache. | +| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Runtime/provisioning least-privilege separation is not yet shipped. | +| Release evidence | descriptor/artifact identity contracts | ADR 0003, ADR 0004 | Evidence proves the reviewed artifact path, not organizational certification. | + +## Active overlay register + +The following open pull requests are intentionally represented only as overlays on this traceability map: + +- **#175** — OpenTelemetry packaging extra; dependency-lock/materialization and final package evidence remain outside protected-main truth. +- **#184** — existing-volume legacy PostgreSQL extension retirement; migration/operator behavior remains active until merged. +- **#190** — durable reconciliation candidate discovery; not protected-main truth and currently subject to live review/tooling evidence. +- **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. +- **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. +- **#193** — runtime-store/schema-provisioning separation; RED-only and writer-blocked in the current inventory. +- **#194** — atomic local result-effect/checkpoint application; RED-only at its initial test head and not shipped. + +This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. + +## Change-control rule + +When a capability merges, update the PRD/TRD status and this traceability map in a canonical documentation change only after the new protected-main tree is read. When a capability is abandoned or superseded, mark the overlay accordingly rather than silently deleting its historical decision context. New requirements must identify at least one intended implementation authority and one deterministic verification authority before they can be called acquisition-ready. \ No newline at end of file From 1cbc9ea0ffb1eb1809be8a284b210d5eba2efb12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 20:51:47 +0900 Subject: [PATCH 05/58] docs: index protected-main architecture decisions --- docs/adr/README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 docs/adr/README.md diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 000000000..d169ab9a0 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,49 @@ +# Architecture Decision Record Index + +## Authority + +This index is a navigation and status aid for architecture decision records that exist on protected `main`. The decision record itself remains the normative source for its context, decision, consequences, security boundary, and supersession rules. + +The protected-main tree used to reconstruct this index is `d0a4b30be1f46536e352443309f3a35533156767`. A pull request, historical branch, generated merge commit, workflow run, review comment, or proposed file that is not on protected main is not silently promoted into this index. + +## Protected-main decisions + +| ADR | Decision | Document status | Protected-main applicability | +| --- | --- | --- | --- | +| [0002](0002-tenant-scoped-lifecycle.md) | Tenant-scoped durable lifecycle state | Accepted | Defines trusted host-selected `tenant_scope`, tenant-qualified durable lifecycle identity, transaction-local RLS binding, and the standalone compatibility scope. | +| [0003](0003-reproducible-release-evidence.md) | Reproducible release evidence before publication | Proposed | Documents the reproducibility/evidence design present in the repository. The ADR's own `Proposed` status is retained and must not be rewritten as architectural acceptance merely because related release-evidence code or workflows exist. | +| [0004](0004-descriptor-pinned-release-artifact-verification.md) | Descriptor-pinned release artifact verification | Proposed | Documents the descriptor-pinned TOCTOU-hardening design. Its `Proposed` decision status remains authoritative until explicitly changed through reviewed documentation governance. | +| [0006](0006-resumable-result-checkpoints.md) | Resumable provider-result checkpoints | Accepted | Defines immutable prefix checkpoint evidence and its explicit prefix-only, non-authentication, non-whole-stream assurance boundary. | +| [0007](0007-durable-result-checkpoint-store.md) | Durable tenant-isolated result checkpoint store | Accepted | Adds optional PostgreSQL persistence, tenant isolation, compare-and-swap concurrency, and a caller-owned transaction seam without claiming distributed exactly-once delivery. Depends on ADR 0006. | +| [0015](0015-http-425-too-early-retry.md) | HTTP 425 retry for bounded idempotent GETs | Accepted for the bounded retry slice | Keeps the default GET retry-status set closed, side-effecting POSTs single-attempt, and TLS/certificate/fingerprint failures outside automatic retry. | + +## Numbering and missing identifiers + +ADR numbers are stable identifiers, not a promise of contiguous numbering. The absence of `0001`, `0005`, or `0008` through `0014` from the protected-main directory does **not** mean those decisions are missing, rejected, accepted elsewhere, or safe to reconstruct from old branches. Gaps may reflect historical work, superseded proposals, unmerged branches, or reserved identifiers. Only a reviewed protected-main document may establish the status of a missing number. + +New ADRs should use the next repository-approved stable identifier rather than renumbering existing records. Renaming an integrated ADR changes external references and should be treated as an architecture-governance migration, not cleanup. + +## Decision status versus implementation status + +ADR status answers whether an architectural decision has been accepted, proposed, deprecated, or superseded. It is not interchangeable with product implementation status. + +The canonical product/technical documents use `IMPLEMENTED-ON-PROTECTED-MAIN`, `ACTIVE-PR`, `PARTIAL`, `PLANNED`, and `SUPERSEDED` for implementation truth. A `Proposed` ADR can coexist with related code on protected main, and an `Accepted` ADR can describe a bounded contract whose larger product capability is still only partial. Do not infer one status system from the other. + +When an ADR and protected-main implementation appear inconsistent, treat the inconsistency as a defect to reconcile explicitly. Do not silently edit the index to make the conflict disappear. + +## Supersession and amendments + +A decision is superseded only when a reviewed record or amendment says so explicitly. A later implementation, issue, pull request, or historical branch does not implicitly supersede an ADR. + +For a material architecture change: + +1. refetch protected main and all source/documentation writers touching the decision boundary; +2. identify the existing ADRs and product/technical requirements that constrain the change; +3. record the new decision or explicit amendment, including rejected alternatives and operational/security consequences where material; +4. keep active/unmerged behavior classified as an overlay rather than protected-main truth; +5. update traceability after the capability actually reaches protected main; and +6. preserve standalone operation and modular MSA embedding unless a separately accepted decision changes that product contract. + +## Non-guarantees that must remain visible + +The current ADR set does not establish authentication from PostgreSQL RLS alone, provider authenticity from result checkpointing, full-stream immutability from a prefix checkpoint, distributed exactly-once processing, retry permission for arbitrary HTTP failures, or organizational security/compliance certification. Those boundaries must not be weakened by summaries, operator docs, marketing material, or future ADR titles. \ No newline at end of file From 05623306c705d3e79d2127f46c3c423f953d8edb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 20:52:58 +0900 Subject: [PATCH 06/58] docs: record active ADR index reconstruction --- docs/DOCUMENTATION_FITNESS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index c7306649d..124057e89 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -14,7 +14,8 @@ A document is *fit* only when it states the correct authority boundary, is consi | `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, interoperability, and verification, but does not by itself form a complete system/UML/data model. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file. | | `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states. | Validate exact-head docs gates and integrate only through normal PR governance. | | `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries and release/testing invariants are explicit. | Validate exact-head docs gates and integrate only through normal PR governance. | -| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist, but there is no canonical ADR index describing numbering gaps, status, supersession, and protected-main applicability. | Add an ADR index on this canonical branch after checking active ADR writers. | +| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. | +| `docs/adr/README.md` | ACTIVE-PR | This canonical branch now supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Validate exact-head documentation gates and integrate only through normal PR governance. | | `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | | `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Durable lifecycle/tenant behavior has detailed protected-main documentation. | Keep synchronized with tenant/RLS and lifecycle migrations. | | Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | From b708dbbbf7af9be9c3e9add34718949bcc34099b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 21:39:23 +0900 Subject: [PATCH 07/58] docs: refresh atomic result application status --- docs/DOCUMENTATION_FITNESS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 124057e89..f0094a0e3 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -22,7 +22,7 @@ A document is *fit* only when it states the correct authority boundary, is consi | Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation, but it is not shipped and its exact-head acceptance remains separate. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | -| Atomic durable result application | ACTIVE-PR | Draft #194 is RED-only at its initial head and is not product truth. Protected main still has a PARTIAL end-to-end result-application capability. | Keep PARTIAL until test-first implementation, exact-head gates, review, and merge complete. | +| Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay and does not make end-to-end result application or distributed exactly-once behavior protected-main truth. | Keep the protected-main end-to-end capability PARTIAL until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | | Runtime config/schema provisioning separation | ACTIVE-PR / BLOCKED | Draft #193 is RED-only and currently frozen because a source-affecting no-PR config branch remains live writer evidence. | Do not describe the least-privilege runtime-store repair as shipped or proceed through competing source ownership. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | @@ -46,4 +46,4 @@ A document is *fit* only when it states the correct authority boundary, is consi ## Fitness gate for future canonical changes -Before changing a canonical surface, refetch protected main, open PRs, non-default branches, the exact affected source/schema/test authorities, and any adjacent documentation writer. A documentation repair must not race a source-affecting writer whose behavior is still unsettled. After a product PR merges, update the canonical status classification from `ACTIVE-PR` or `PARTIAL` only when the protected-main tree contains the capability and the integrated evidence contract remains valid. \ No newline at end of file +Before changing a canonical surface, refetch protected main, open PRs, non-default branches, the exact affected source/schema/test authorities, and any adjacent documentation writer. A documentation repair must not race a source-affecting writer whose behavior is still unsettled. After a product PR merges, update the canonical status classification from `ACTIVE-PR` or `PARTIAL` only when the protected-main tree contains the capability and the integrated evidence contract remains valid. From 65338dfa04ef942864bb0a250503de1344a1b996 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 21:40:16 +0900 Subject: [PATCH 08/58] docs: align traceability with active result application --- docs/TRACEABILITY.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index f8e5f3ea4..89b33c0e1 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -16,7 +16,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | FR-4 scheduler-independent bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation.py` | reconciliation tests and protected-main release gates | Discovery #190 and single-flight #191 remain ACTIVE-PR; autonomous worker semantics remain PARTIAL. | | FR-4 durable reconciliation candidate discovery | ACTIVE-PR | none on protected main beyond existing lifecycle/read primitives | PR #190 exact-head evidence only | Not shipped; current review/infrastructure gates must not be transferred. | | FR-4 tenant-qualified cross-process single-flight | ACTIVE-PR | none on protected main beyond existing DB primitives | PR #191 exact-head evidence only | Not shipped; qualifying independent approval remains a live-governance concern. | -| FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | Draft #194 is test-first ACTIVE-PR work; protected main does not claim end-to-end exactly-once application. | +| FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | PR #194 is ACTIVE-PR test-first work that adds a same-transaction local result-effect/checkpoint seam; protected main still does not claim end-to-end or distributed exactly-once application. | | FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Least-privilege separation of runtime store construction from schema provisioning is ACTIVE-PR #193 and currently writer-blocked. | @@ -62,10 +62,10 @@ The following open pull requests are intentionally represented only as overlays - **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. - **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. - **#193** — runtime-store/schema-provisioning separation; RED-only and writer-blocked in the current inventory. -- **#194** — atomic local result-effect/checkpoint application; RED-only at its initial test head and not shipped. +- **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. ## Change-control rule -When a capability merges, update the PRD/TRD status and this traceability map in a canonical documentation change only after the new protected-main tree is read. When a capability is abandoned or superseded, mark the overlay accordingly rather than silently deleting its historical decision context. New requirements must identify at least one intended implementation authority and one deterministic verification authority before they can be called acquisition-ready. \ No newline at end of file +When a capability merges, update the PRD/TRD status and this traceability map in a canonical documentation change only after the new protected-main tree is read. When a capability is abandoned or superseded, mark the overlay accordingly rather than silently deleting its historical decision context. New requirements must identify at least one intended implementation authority and one deterministic verification authority before they can be called acquisition-ready. From b6ce4d0107de9c7e867e0532de9268f937d03a0d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 01:21:07 +0900 Subject: [PATCH 09/58] docs: refresh runtime provisioning overlay status --- docs/DOCUMENTATION_FITNESS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index f0094a0e3..22b522a0c 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -23,7 +23,7 @@ A document is *fit* only when it states the correct authority boundary, is consi | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay and does not make end-to-end result application or distributed exactly-once behavior protected-main truth. | Keep the protected-main end-to-end capability PARTIAL until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | -| Runtime config/schema provisioning separation | ACTIVE-PR / BLOCKED | Draft #193 is RED-only and currently frozen because a source-affecting no-PR config branch remains live writer evidence. | Do not describe the least-privilege runtime-store repair as shipped or proceed through competing source ownership. | +| Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. It is not shipped until normal governance integrates it. | Preserve the trusted-search-path/non-ownership caveat and reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | From 7f1dbb45d3f6bf7bdeeabe9e26954e1096d6eba3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 01:21:58 +0900 Subject: [PATCH 10/58] docs: refresh active runtime-store traceability --- docs/TRACEABILITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 89b33c0e1..9e1a81411 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -19,7 +19,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | PR #194 is ACTIVE-PR test-first work that adds a same-transaction local result-effect/checkpoint seam; protected main still does not claim end-to-end or distributed exactly-once application. | | FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | -| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Least-privilege separation of runtime store construction from schema provisioning is ACTIVE-PR #193 and currently writer-blocked. | +| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Least-privilege separation of runtime store construction from schema provisioning is ACTIVE-PR #193. Its current candidate moves DDL/default seeding to explicit provisioning and adds bounded catalog relation/type/read-capability probes, but none of that is shipped until normal governance integrates it. | | FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader `ValidationError` value-confidentiality work must not be inferred as solved from readiness alone. | | FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | @@ -61,7 +61,7 @@ The following open pull requests are intentionally represented only as overlays - **#190** — durable reconciliation candidate discovery; not protected-main truth and currently subject to live review/tooling evidence. - **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. - **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. -- **#193** — runtime-store/schema-provisioning separation; RED-only and writer-blocked in the current inventory. +- **#193** — runtime-store/schema-provisioning separation; a current-main least-privilege implementation is under review, but remains an active overlay rather than shipped behavior. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. From fecc977ff9c359ab05e31b9af4decfa2cd9d9c3f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 20:10:01 +0900 Subject: [PATCH 11/58] docs: trace secret encryption policy status --- docs/TRACEABILITY.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 9e1a81411..bd24a9133 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -19,7 +19,8 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | PR #194 is ACTIVE-PR test-first work that adds a same-transaction local result-effect/checkpoint seam; protected main still does not claim end-to-end or distributed exactly-once application. | | FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | -| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Least-privilege separation of runtime store construction from schema provisioning is ACTIVE-PR #193. Its current candidate moves DDL/default seeding to explicit provisioning and adds bounded catalog relation/type/read-capability probes, but none of that is shipped until normal governance integrates it. | +| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. PR #193 proposes an encryption-required default plus explicit local/development opt-out while also separating runtime construction from provisioning. | +| FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes the selected deployment policy through redacted readiness/operator evidence. PR #193 addresses the default-policy boundary only while it remains ACTIVE-PR. | | FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader `ValidationError` value-confidentiality work must not be inferred as solved from readiness alone. | | FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | @@ -37,7 +38,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | RLS defense in depth | tenant-qualified schema and transaction-local scope binding | live PostgreSQL isolation/migration tests | Superuser/BYPASSRLS/arbitrary SQL are administrative bypasses. | | Provider destination validation | `batch_api_client.py` | endpoint/URL tests | Host/network infrastructure TLS policy is external. | | Bounded provider input | provider client + result streaming | response/download/JSONL/resource-budget tests | Provider authenticity is not established by payload validation. | -| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | External enterprise secret manager choice remains host-owned. | +| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Protected main supports Fernet but does not require it by default; the compatibility path is not a production confidentiality claim. PR #193's stricter default is ACTIVE-PR, while enterprise secret-manager choice remains host-owned. | | Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic validation value confidentiality remains an explicit separate gap where applicable. | | Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | | Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability are operational dependencies. | @@ -49,7 +50,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | Tenant lifecycle state | `(tenant_scope, endpoint_alias, remote_batch_id)` | `ARCHITECTURE.md`, ADR 0002, `docs/remote-batch-lifecycle.md` | Tenant scope must come from trusted host authorization; direct SQL bypass is out of scope. | | Result checkpoints | `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | ADR 0006, ADR 0007, `docs/result-streaming.md` | Prefix checkpoint is not provider authentication or whole-stream immutability; cross-system exactly-once is not claimed. | | Package JSONL/payload state | package-owned schema identities and virtual payload references | PRD/TRD, schema-integrity and payload docs/tests | Persisted package data is canonical, not a disposable cache. | -| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Runtime/provisioning least-privilege separation is not yet shipped. | +| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Shipped compatibility mode can still persist `is_encrypted = FALSE`; runtime/provisioning least-privilege separation, required-encryption default, legacy-row migration, key rotation/recovery, and redacted policy-readiness evidence are not all protected-main behavior. | | Release evidence | descriptor/artifact identity contracts | ADR 0003, ADR 0004 | Evidence proves the reviewed artifact path, not organizational certification. | ## Active overlay register @@ -61,7 +62,7 @@ The following open pull requests are intentionally represented only as overlays - **#190** — durable reconciliation candidate discovery; not protected-main truth and currently subject to live review/tooling evidence. - **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. - **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. -- **#193** — runtime-store/schema-provisioning separation; a current-main least-privilege implementation is under review, but remains an active overlay rather than shipped behavior. +- **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. From b2ea32278e1d4c491312117e7629bbc233785f94 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 20:18:50 +0900 Subject: [PATCH 12/58] docs: make lifecycle compatibility contract explicit --- docs/product/PRD.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 905a3906c..f2fd8e282 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -42,8 +42,8 @@ The product must let a qualified host: | PostgreSQL token counting and bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | Token/resource accounting and batch partitioning remain deterministic and finite. | | Disk-free package payload persistence | IMPLEMENTED-ON-PROTECTED-MAIN | Package-owned JSONL payloads persist in PostgreSQL and are validated before credential/provider effects. | | OpenAI-compatible upload/create/poll/wait/cancel/retrieve | IMPLEMENTED-ON-PROTECTED-MAIN | Provider destinations, resource identifiers, control responses, downloads, retries, and timeouts remain bounded and validated. | -| Standalone durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | Existing standalone users retain source-compatible durable lifecycle behavior. | -| Tenant-qualified durable lifecycle with forced RLS | IMPLEMENTED-ON-PROTECTED-MAIN | Tenant scope comes only from a trusted host authorization boundary; direct arbitrary SQL remains outside the isolation guarantee. | +| Standalone durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | `DurableBatchAPIClient` preserves the existing four-argument lifecycle-recorder seam `(postgres_dsn, endpoint_alias, provider_batch, observation_order)` and its default recorder stores lifecycle state under the exact `standalone` scope. | +| Tenant-qualified durable lifecycle with forced RLS | IMPLEMENTED-ON-PROTECTED-MAIN | Tenant scope comes only from a trusted host authorization boundary, is validated before any tenant-client observation reservation, credential resolution, provider I/O, or lifecycle database I/O, and qualifies lifecycle identities, conflict targets, reads, and operational status indexing; direct arbitrary SQL remains outside the isolation guarantee. | | Durable resumable result checkpoint/CAS storage | IMPLEMENTED-ON-PROTECTED-MAIN | PostgreSQL supplies tenant-qualified durable checkpoint authority and conflict detection; this is not a distributed exactly-once claim. | | Redacted readiness reporting | IMPLEMENTED-ON-PROTECTED-MAIN | Public readiness evidence does not disclose arbitrary lower-layer diagnostic content. | | Scheduler-independent bounded provider reconciliation primitive | IMPLEMENTED-ON-PROTECTED-MAIN | A host can submit a finite, validated candidate set for polling/retrieval through the existing bounded provider client; candidate discovery, scheduling, and cross-process lease ownership remain outside this primitive. | @@ -66,7 +66,13 @@ All provider operations shall use validated endpoint configuration and finite re ### FR-3: Durable lifecycle and tenancy -The durable business identity is tenant-qualified where tenancy is enabled. The package shall validate tenant scope before persistence/provider effects that rely on it, bind scope through parameterized transaction-local PostgreSQL context, and keep forced row-level security enabled for application roles. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access are administrative escape hatches and are not part of the tenant isolation guarantee. +The durable business identity is tenant-qualified where tenancy is enabled. `TenantDurableBatchAPIClient` shall validate its trusted host-selected `tenant_scope` synchronously at construction, before observation reservation, credential resolution, provider I/O, or lifecycle database I/O can occur. The tenant-qualified lifecycle key is `(tenant_scope, endpoint_alias, remote_batch_id)`; lifecycle persistence conflict targets, exact-row lookups, and operational status indexes shall retain `tenant_scope`, and package reads/writes shall bind that validated scope through parameterized transaction-local PostgreSQL context with forced row-level security for application roles. Provider/model content, endpoint aliases, remote identifiers, and transport data never select tenant authority. + +The deployment credential provider remains a separate host/configuration authority: validating tenant scope before credential resolution does not make credentials tenant-keyed and does not authorize a tenant to select secrets. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access are administrative escape hatches and are not part of the tenant isolation guarantee. + +Standalone source compatibility is also normative. `DurableBatchAPIClient` retains its four-argument lifecycle-recorder interface `(postgres_dsn, endpoint_alias, provider_batch, observation_order)`, and the default persistence/read helpers use the explicit `standalone` database scope rather than silently introducing a required tenant argument. + +Protected-main acceptance authority for these invariants is deterministic: `tests/test_tenant_durable_client.py` proves construction-time pre-effect tenant validation and the four-argument standalone recorder seam; `tests/test_tenant_lifecycle_persistence.py` proves explicit `standalone` delegation, tenant-qualified conflict targets and reads, malformed-scope rejection before database access, and distinct tenant identities; `pg_llm_batch/schema.sql` supplies the tenant-qualified unique key, forced RLS policy, and tenant-qualified operational status index. `docs/remote-batch-lifecycle.md`, ADR 0002, and `docs/doctoring/tenant-scoped-lifecycle.md` describe the same protected-main contract. ### FR-4: Reconciliation and recovery From f0cf1f73c9e129fa0d4edb7a604dd51e7cf2b23f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 20:19:48 +0900 Subject: [PATCH 13/58] docs: pin tenant lifecycle technical invariants --- docs/product/TRD.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/product/TRD.md b/docs/product/TRD.md index 4a4249ab0..1d0133da8 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -17,8 +17,8 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A | `token_counter.py` | resolve reviewed tokenizer metadata and call `pg_tiktoken` for token accounting | provider credentials, tenant authorization, provider I/O | | `orchestrator.py` | select queued requests, partition under limits, persist package payload/file/line/request assignments | provider protocol and retry policy | | `batch_api_client.py` | validate provider destination and remote identifiers; upload/create/poll/wait/cancel/retrieve under finite budgets | tenant authentication, scheduler ownership | -| `durable_client.py` | compose provider operations with durable lifecycle ordering/persistence | authenticating or authorizing host tenants | -| `db.py` | schema application and parameterized persistence/read helpers | database-side provider networking | +| `durable_client.py` | compose provider operations with durable lifecycle ordering/persistence; preserve `DurableBatchAPIClient` source compatibility, its four-argument `LifecycleRecorder(postgres_dsn, endpoint_alias, provider_batch, observation_order)` seam, and default `standalone` database scope; provide a distinct tenant-qualified recorder seam | authenticating or authorizing host tenants, deriving tenant authority from provider data | +| `db.py` | schema application and parameterized persistence/read helpers, including tenant-qualified lifecycle context, conflict identity, and exact-row lookup | database-side provider networking, authenticating tenant callers | | `checkpoint_store.py` | tenant-qualified PostgreSQL checkpoint/CAS operations and conflict semantics | distributed exactly-once claims | | `reconciliation.py` | finite host-selected polling/retrieval pass using the existing validated client surface | candidate discovery, scheduling, cross-process leasing | | `config.py` | PostgreSQL-backed configuration and encrypted secret storage for standalone composition | prescribing an embedding host's external secret manager | @@ -26,6 +26,8 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A | `health.py` | readiness aggregation and redacted public health response | general-purpose web serving or arbitrary diagnostic reflection | | `cli.py` | standalone operator composition and bounded input surfaces | higher-level workflow orchestration | +The protected-main validation authority for the `durable_client.py` compatibility row is `pg_llm_batch/durable_client.py`, `tests/test_tenant_durable_client.py`, and `tests/test_tenant_lifecycle_persistence.py`: the tests prove construction-time tenant rejection before downstream effects, exact four-argument standalone recorder invocation, explicit `standalone` persistence/read delegation, and tenant-qualified lifecycle persistence/read identities. + ## Runtime architecture ### Batch preparation @@ -49,7 +51,9 @@ Automatic provider retry is limited to reviewed idempotent GET operations and th ### Durable lifecycle tenancy -Standalone lifecycle data uses the exact `standalone` tenant scope. Tenant-aware hosts use a trusted host-selected scope after authentication and authorization. Provider metadata, request payloads, model output, transport headers, endpoint aliases, and provider resource identifiers never choose tenant authority. +Standalone lifecycle data uses the exact `standalone` tenant scope. `DurableBatchAPIClient` preserves its original four-argument lifecycle-recorder interface `(postgres_dsn, endpoint_alias, provider_batch, observation_order)`; its default persistence path and `get_remote_batch_state(...)` compatibility helper resolve through the explicit `standalone` scope. Tenant-aware hosts instead use `TenantDurableBatchAPIClient` with a distinct tenant-qualified recorder seam so tenant identity cannot be silently dropped. + +A tenant-aware client validates the trusted host-selected `tenant_scope` synchronously during construction, before any observation reservation, credential-provider lookup, provider I/O, or lifecycle database I/O can occur. Provider metadata, request payloads, model output, transport headers, endpoint aliases, provider resource identifiers, and credential data never choose tenant authority. Credential resolution remains a separate deployment/host concern: ordering tenant validation before it does not make the credential store tenant-keyed. The durable lifecycle identity is: @@ -57,7 +61,9 @@ The durable lifecycle identity is: (tenant_scope, endpoint_alias, remote_batch_id) ``` -Package reads/writes bind tenant scope with parameterized transaction-local `set_config`. The schema enables and forces PostgreSQL row-level security for tenant-qualified lifecycle state. Production application roles must be `NOSUPERUSER NOBYPASSRLS`. A role that can execute arbitrary SQL can choose arbitrary custom setting values; therefore generic arbitrary SQL access is explicitly outside the package isolation guarantee. +Every tenant-aware lifecycle persistence conflict target and exact-row lookup includes the full identity. The protected schema's lifecycle operational status index begins with `tenant_scope`, and package reads/writes bind the validated scope with parameterized transaction-local `set_config`. The schema enables and forces PostgreSQL row-level security for tenant-qualified lifecycle state. Production application roles must be `NOSUPERUSER NOBYPASSRLS`. A role that can execute arbitrary SQL can choose arbitrary custom setting values; therefore generic arbitrary SQL access is explicitly outside the package isolation guarantee. + +These invariants are deterministically verified on protected main: `tests/test_tenant_durable_client.py` proves malformed scope fails before reservation or credentials and proves the unchanged four-argument standalone recorder seam; `tests/test_tenant_lifecycle_persistence.py` proves malformed scope fails before database access, the upsert conflict target is `(tenant_scope, endpoint_alias, remote_batch_id)`, exact reads bind the same full identity, and standalone helpers delegate to `standalone`; `pg_llm_batch/schema.sql` supplies the tenant-qualified unique constraint, forced RLS policy, and `idx_llm_remote_batch_jobs_tenant_status_observed` index. `docs/remote-batch-lifecycle.md`, ADR 0002, and `docs/doctoring/tenant-scoped-lifecycle.md` document the same migration, direct-SQL/RLS, role, and rollback boundaries. ### Durable result checkpoints From b9f15c0ed62dbd35d2ef971d4885aefd770125bc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 20:20:59 +0900 Subject: [PATCH 14/58] docs: verify tenant lifecycle companion authority --- docs/DOCUMENTATION_FITNESS.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 22b522a0c..f62c180e8 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -6,20 +6,24 @@ This inventory evaluates the documentation graph against the exact protected-mai A document is *fit* only when it states the correct authority boundary, is consistent with the protected-main code/schema/tests it describes, avoids transferring predecessor or active-branch evidence into shipped claims, and gives an operator or reviewer enough information to use, verify, recover, or reject the relevant behavior safely. +The tenant lifecycle material in this canonical cohort is a reconstruction of already integrated protected-main behavior, not a new runtime tenant/RLS/migration contract. Companion-document verification against protected main confirms the same contract is already present in the public `README.md`, root `ARCHITECTURE.md`, topic operator guide `docs/remote-batch-lifecycle.md`, accepted ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md`. Those authorities already cover trusted tenant identity, `NOSUPERUSER NOBYPASSRLS`, transaction-local/forced RLS, direct-SQL limits, legacy-to-`standalone` migration, and rollback constraints. The canonical PRD/TRD therefore may cite that existing evidence without rewriting those protected-main files or racing PR #184's separate legacy-extension-retirement documentation lane. + ## Current fitness matrix | Documentation surface | Status | Fitness assessment | Required next action | | --- | --- | --- | --- | -| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point, but it is not the sole product/architecture authority and must not absorb transient PR/check state. | Keep beginner-readable; update bounded shipped capability changes after merge. | -| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, interoperability, and verification, but does not by itself form a complete system/UML/data model. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file. | -| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states. | Validate exact-head docs gates and integrate only through normal PR governance. | -| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries and release/testing invariants are explicit. | Validate exact-head docs gates and integrate only through normal PR governance. | -| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. | +| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. | Keep beginner-readable; update only when a bounded shipped capability actually changes after merge. | +| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file. | +| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states and cites deterministic protected-main tenant/standalone acceptance authority. | Validate exact-head docs gates and integrate only through normal PR governance. | +| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, and release/testing invariants are explicit. | Validate exact-head docs gates and integrate only through normal PR governance. | +| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. | | `docs/adr/README.md` | ACTIVE-PR | This canonical branch now supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Validate exact-head documentation gates and integrate only through normal PR governance. | | `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | -| `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Durable lifecycle/tenant behavior has detailed protected-main documentation. | Keep synchronized with tenant/RLS and lifecycle migrations. | +| `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Serves as the topic-specific operator authority for durable lifecycle tenancy. It already specifies trusted scope selection, pre-effect validation, four-argument standalone recorder compatibility, tenant-qualified identity/conflict/read behavior, forced RLS/application-role limits, migration, direct-SQL impact, rollback, recovery, and deterministic verification. | Keep synchronized with tenant/RLS and lifecycle migrations; do not duplicate this contract into a competing operator file. | +| `docs/doctoring/tenant-scoped-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Supporting evidence independently records pre-effect validation, explicit standalone compatibility, database role/RLS limits, migration and rollback, plus current primary references. | Keep supporting references current; do not promote doctoring into the sole product authority. | +| `CHANGELOG.md` tenant lifecycle entry | IMPLEMENTED-ON-PROTECTED-MAIN | The protected-main Unreleased section already records tenant-scoped durable lifecycle, forced default-deny RLS, standalone compatibility, and the atomic tenant migration fix. | Change only when integrated shipped behavior changes; do not log active-PR claims as shipped. | | Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | -| Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation, but it is not shipped and its exact-head acceptance remains separate. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | +| Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation for retiring legacy `http` / `pg_cron`; it is a different contract from the already-shipped tenant lifecycle migration and is not protected-main truth. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay and does not make end-to-end result application or distributed exactly-once behavior protected-main truth. | Keep the protected-main end-to-end capability PARTIAL until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | @@ -29,7 +33,7 @@ A document is *fit* only when it states the correct authority boundary, is consi | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | | UML/component/sequence views | PLANNED | Root architecture is prose-first; no canonical UML authority is present. | Add textual Mermaid/PlantUML-compatible component and critical sequence diagrams after active source contracts stabilize. | | ERD / schema model | PLANNED | SQL and schema tests are authoritative, but no canonical ERD summarizes package-owned identities, tenancy, checkpoint state, and relationships. | Generate/maintain an ERD from protected-main schema; label migration-only/active-PR objects separately. | -| Standalone operator guide | PARTIAL | Operational instructions exist across README and topic docs, while #184 is adding migration-specific operability. There is no protected-main general `docs/OPERABILITY.md`. | Establish a general operator authority without racing #184's bounded migration changes. | +| General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184's active migration-specific operability work. | | Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | | Licensing / third-party notices | PARTIAL | Apache-2.0 source headers and repository licensing exist, but acquisition diligence should explicitly trace package license, dependency/SBOM evidence, and third-party notice process. | Evaluate a concise licensing/compliance evidence index without claiming legal certification. | @@ -38,7 +42,9 @@ A document is *fit* only when it states the correct authority boundary, is consi - Protected-main behavior is the shipped authority. Active PRs and historical branches are overlays, not proof of implementation. - Exact contributor heads, generated merge commits, check IDs, and transient queue state belong in PR/review evidence, not durable architecture/product documents. - Standalone operation and modular MSA embedding must be documented as co-equal supported boundaries; no ContextualWisdomLab host is a hidden runtime requirement. -- Tenant scope is selected only by a trusted authenticated/authorized host boundary. PostgreSQL RLS is defense in depth, not authentication or SQL-injection prevention. +- Tenant scope is selected only by a trusted authenticated/authorized host boundary and, for the tenant durable client, validates before observation reservation, credential lookup, provider I/O, or lifecycle database I/O. Lifecycle identities, conflict targets, exact reads, and operational status indexes remain tenant-qualified where tenancy is enabled. +- The standalone `DurableBatchAPIClient` retains its four-argument lifecycle-recorder seam and explicit `standalone` persistence/read scope unless a separately reviewed compatibility change is integrated. +- PostgreSQL RLS is defense in depth, not authentication or SQL-injection prevention; production application roles for the tenant lifecycle boundary are `NOSUPERUSER NOBYPASSRLS`. - Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. - Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. - Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. @@ -46,4 +52,4 @@ A document is *fit* only when it states the correct authority boundary, is consi ## Fitness gate for future canonical changes -Before changing a canonical surface, refetch protected main, open PRs, non-default branches, the exact affected source/schema/test authorities, and any adjacent documentation writer. A documentation repair must not race a source-affecting writer whose behavior is still unsettled. After a product PR merges, update the canonical status classification from `ACTIVE-PR` or `PARTIAL` only when the protected-main tree contains the capability and the integrated evidence contract remains valid. +Before changing a canonical surface, refetch protected main, open PRs, non-default branches, the exact affected source/schema/test authorities, and any adjacent documentation writer. A documentation repair must not race a source-affecting writer whose behavior is still unsettled. When a canonical change merely reconstructs an already integrated contract, verify the existing permanent companion set before widening the change; when runtime behavior actually changes, update the required permanent companion surfaces in that same governed change or explicitly coordinate their writer ownership. After a product PR merges, update the canonical status classification from `ACTIVE-PR` or `PARTIAL` only when the protected-main tree contains the capability and the integrated evidence contract remains valid. From 2a540ba812a36c0b1bbd30a308d4a537b18b9735 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 21:10:09 +0900 Subject: [PATCH 15/58] docs: define utility-preserving PII controls --- docs/product/PRD.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/product/PRD.md b/docs/product/PRD.md index f2fd8e282..0e9ca63fa 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -104,6 +104,8 @@ Owned production Python must maintain exact 100% statement and branch coverage a Security-sensitive validation fails closed. Secrets, DSNs, prompt/provider content, unvalidated identifiers, and arbitrary lower-layer exception text must not be retained in logs or review evidence merely for debugging. Repository controls should support SOC 2 / CSAP evidence preparation without claiming certification. +The package must not apply blanket masking or lossy transformation to authorized business payloads merely because they contain PII: changing prompt, request, or result content can invalidate business meaning, token accounting, provider behavior, auditability, or downstream decisions. Authorized content fidelity is therefore a product requirement. Confidentiality controls belong at explicit boundaries instead: trusted host authentication/authorization and tenant selection, least-privilege database/service access, transport protection, deployment/storage protection where provided, purpose-limited retention and deletion, and package-owned logs/telemetry/errors that omit content-bearing values. Any content transformation must be an explicit host/business policy with provenance and acceptance evidence, not a hidden package default or a claim that redacted diagnostics mean persisted business data was masked. + ### Reliability Network, response, retry, wait, candidate-scan, payload, and release-evidence operations must be explicitly bounded. Recovery and rollback must be documented before migrations or release changes are considered complete. Queued, skipped, cancelled, absent, stale, predecessor-head, synthetic-merge-only, or infrastructure-failed evidence is not success for an exact source head. From 6279c63b5e85900de3227b9231029f9d4e1d0219 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 21:11:01 +0900 Subject: [PATCH 16/58] docs: specify content-fidelity privacy boundary --- docs/product/TRD.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/product/TRD.md b/docs/product/TRD.md index 1d0133da8..c689e6b93 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -99,6 +99,12 @@ Durable provider/resource identifiers and tenant identities are validated before Standalone provider configuration and encrypted secrets are PostgreSQL-backed. Environment variables are limited to explicitly documented bootstrap transport such as the database DSN and optional encryption key. CLI secret entry uses no-echo prompting or bounded standard input rather than plaintext process arguments. Embedding hosts may supply another credential provider through the supported seam. +### Authorized content fidelity + +The package does not gain authority to mask, tokenize away, truncate for privacy, or otherwise alter an authorized prompt, request, JSONL record, or provider result merely because the content may contain PII. Silent transformation would change token counts, provider semantics, persisted evidence, replay behavior, and downstream business meaning. Package serialization, token accounting, persistence, upload, retrieval, and result application therefore preserve authorized business content unless an explicit reviewed feature contract says otherwise. + +Confidentiality for content-bearing data is enforced through boundary controls rather than a blanket masking default: the embedding host authenticates and authorizes the caller and selects tenant scope; package/database/service identities remain least-privilege; transport uses the reviewed secure destination policy; deployment/storage protections are owned and evidenced at the applicable layer; retention and deletion are purpose-limited and explicit; and package-owned errors, logs, telemetry, readiness, CI/review evidence, and other operational surfaces omit content-bearing values. A host that intentionally transforms content must do so through an explicit business-policy boundary with provenance and acceptance tests. Redacted operational evidence must never be represented as proof that persisted or provider-bound business content was masked. + ### Diagnostic confidentiality Errors, logs, telemetry, check evidence, and public readiness must avoid DSNs, credentials, prompts, provider bodies, arbitrary SQL/provider exception text, unvalidated identifiers, and dynamic exception-class names where those values are not required for operation. Failure categories intended for public/operational evidence use bounded vocabularies. From 8c01d37a452369774964a03f8aff45a620368c33 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 21:45:23 +0900 Subject: [PATCH 17/58] docs(security): clarify tenant setting trust boundary --- docs/product/PRD.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 0e9ca63fa..5fac473bb 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -68,7 +68,9 @@ All provider operations shall use validated endpoint configuration and finite re The durable business identity is tenant-qualified where tenancy is enabled. `TenantDurableBatchAPIClient` shall validate its trusted host-selected `tenant_scope` synchronously at construction, before observation reservation, credential resolution, provider I/O, or lifecycle database I/O can occur. The tenant-qualified lifecycle key is `(tenant_scope, endpoint_alias, remote_batch_id)`; lifecycle persistence conflict targets, exact-row lookups, and operational status indexes shall retain `tenant_scope`, and package reads/writes shall bind that validated scope through parameterized transaction-local PostgreSQL context with forced row-level security for application roles. Provider/model content, endpoint aliases, remote identifiers, and transport data never select tenant authority. -The deployment credential provider remains a separate host/configuration authority: validating tenant scope before credential resolution does not make credentials tenant-keyed and does not authorize a tenant to select secrets. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access are administrative escape hatches and are not part of the tenant isolation guarantee. +The transaction-local `pg_llm_batch.tenant_scope` custom setting is routing context, not a credential or authenticated identity. Only package code acting on a trusted authenticated/authorized host selection may set it for tenant-owned operations; arbitrary SQL must not select or override tenant authority by calling `set_config`. PostgreSQL RLS is defense in depth and does not replace host authentication/authorization, SQL-injection prevention, or correct identity mapping. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access remain administrative escape hatches outside the tenant isolation guarantee. + +The deployment credential provider remains a separate host/configuration authority: validating tenant scope before credential resolution does not make credentials tenant-keyed and does not authorize a tenant to select secrets. Standalone source compatibility is also normative. `DurableBatchAPIClient` retains its four-argument lifecycle-recorder interface `(postgres_dsn, endpoint_alias, provider_batch, observation_order)`, and the default persistence/read helpers use the explicit `standalone` database scope rather than silently introducing a required tenant argument. From d55b21efd08b800441537c762b646af4c1a39aa3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 21:46:28 +0900 Subject: [PATCH 18/58] docs(security): mirror tenant setting authority invariant --- docs/DOCUMENTATION_FITNESS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index f62c180e8..d67ab301e 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -43,8 +43,9 @@ The tenant lifecycle material in this canonical cohort is a reconstruction of al - Exact contributor heads, generated merge commits, check IDs, and transient queue state belong in PR/review evidence, not durable architecture/product documents. - Standalone operation and modular MSA embedding must be documented as co-equal supported boundaries; no ContextualWisdomLab host is a hidden runtime requirement. - Tenant scope is selected only by a trusted authenticated/authorized host boundary and, for the tenant durable client, validates before observation reservation, credential lookup, provider I/O, or lifecycle database I/O. Lifecycle identities, conflict targets, exact reads, and operational status indexes remain tenant-qualified where tenancy is enabled. +- `pg_llm_batch.tenant_scope` is transaction-local routing context, not a credential or authenticated identity. Only package code acting on trusted host selection may set it for tenant-owned operations; arbitrary SQL must not select or override tenant authority through `set_config`. - The standalone `DurableBatchAPIClient` retains its four-argument lifecycle-recorder seam and explicit `standalone` persistence/read scope unless a separately reviewed compatibility change is integrated. -- PostgreSQL RLS is defense in depth, not authentication or SQL-injection prevention; production application roles for the tenant lifecycle boundary are `NOSUPERUSER NOBYPASSRLS`. +- PostgreSQL RLS is defense in depth, not host authentication/authorization, SQL-injection prevention, or correct identity mapping; production application roles for the tenant lifecycle boundary are `NOSUPERUSER NOBYPASSRLS`. - Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. - Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. - Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. From 6b363857c49f0cc1cadf2eec359135fcbf697c0c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 16 Aug 2026 07:12:43 +0900 Subject: [PATCH 19/58] docs(traceability): register active validation privacy repair --- docs/TRACEABILITY.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index bd24a9133..8b3d140a0 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -21,7 +21,8 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. PR #193 proposes an encryption-required default plus explicit local/development opt-out while also separating runtime construction from provisioning. | | FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes the selected deployment policy through redacted readiness/operator evidence. PR #193 addresses the default-policy boundary only while it remains ACTIVE-PR. | -| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader `ValidationError` value-confidentiality work must not be inferred as solved from readiness alone. | +| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic validation rejected-value confidentiality is not protected-main truth; PR #202 is the ACTIVE-PR compatibility-aware repair and must not be inferred as shipped before integration. | +| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 exact-head privacy/compatibility tests and review evidence only | The candidate safe default uses fixed redaction unless a reviewed call site explicitly opts into bounded non-sensitive `safe_value` evidence; this remains unshipped until normal governance integrates it. | | FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | | Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | @@ -39,7 +40,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | Provider destination validation | `batch_api_client.py` | endpoint/URL tests | Host/network infrastructure TLS policy is external. | | Bounded provider input | provider client + result streaming | response/download/JSONL/resource-budget tests | Provider authenticity is not established by payload validation. | | Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Protected main supports Fernet but does not require it by default; the compatibility path is not a production confidentiality claim. PR #193's stricter default is ACTIVE-PR, while enterprise secret-manager choice remains host-owned. | -| Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic validation value confidentiality remains an explicit separate gap where applicable. | +| Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic `ValidationError` rejected-value confidentiality remains incomplete on protected main; PR #202 is ACTIVE-PR and its evidence does not transfer until merge. | | Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | | Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability are operational dependencies. | @@ -64,6 +65,7 @@ The following open pull requests are intentionally represented only as overlays - **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. - **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. +- **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening; protected main still discloses arbitrary rejected values by default, so the candidate safe-default redaction and bounded `safe_value` opt-in remain ACTIVE-PR until integrated. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. From 3d5f79fef04f034f5e930717758992bfa173e86b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 16 Aug 2026 13:11:15 +0900 Subject: [PATCH 20/58] docs(traceability): record current PR 202 blocker --- docs/TRACEABILITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 8b3d140a0..49409b9f0 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -22,7 +22,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. PR #193 proposes an encryption-required default plus explicit local/development opt-out while also separating runtime construction from provisioning. | | FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes the selected deployment policy through redacted readiness/operator evidence. PR #193 addresses the default-policy boundary only while it remains ACTIVE-PR. | | FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic validation rejected-value confidentiality is not protected-main truth; PR #202 is the ACTIVE-PR compatibility-aware repair and must not be inferred as shipped before integration. | -| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 exact-head privacy/compatibility tests and review evidence only | The candidate safe default uses fixed redaction unless a reviewed call site explicitly opts into bounded non-sensitive `safe_value` evidence; this remains unshipped until normal governance integrates it. | +| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 candidate privacy/compatibility tests and review evidence only | PR #202 is Draft because its current `safe_value` guard accepts `str` subclasses via `isinstance`, which can execute caller-controlled special methods while validation or rendering handles supposedly safe evidence. The candidate must require an exact built-in `str` and prove a hostile-subclass regression before it can become Ready; the intended fixed-redaction default and bounded `safe_value` opt-in remain unshipped. | | FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | | Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | @@ -65,7 +65,7 @@ The following open pull requests are intentionally represented only as overlays - **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. - **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. -- **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening; protected main still discloses arbitrary rejected values by default, so the candidate safe-default redaction and bounded `safe_value` opt-in remain ACTIVE-PR until integrated. +- **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening. It is Draft because the current `safe_value` guard accepts `str` subclasses via `isinstance`; the branch must first require an exact built-in `str` and pass a hostile-subclass regression. Protected main still discloses arbitrary rejected values by default, and the intended safe-default redaction/bounded `safe_value` contract remains ACTIVE-PR until integrated. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. From 3525ab6b5e7f6d98001b2284ed76d6deb300ec62 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 16 Aug 2026 14:05:58 +0900 Subject: [PATCH 21/58] docs(security): clarify tenant and result authority --- docs/DOCUMENTATION_FITNESS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index d67ab301e..94e538004 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -26,7 +26,7 @@ The tenant lifecycle material in this canonical cohort is a reconstruction of al | Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation for retiring legacy `http` / `pg_cron`; it is a different contract from the already-shipped tenant lifecycle migration and is not protected-main truth. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | -| Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay and does not make end-to-end result application or distributed exactly-once behavior protected-main truth. | Keep the protected-main end-to-end capability PARTIAL until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | +| Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | | Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. It is not shipped until normal governance integrates it. | Preserve the trusted-search-path/non-ownership caveat and reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | @@ -43,10 +43,11 @@ The tenant lifecycle material in this canonical cohort is a reconstruction of al - Exact contributor heads, generated merge commits, check IDs, and transient queue state belong in PR/review evidence, not durable architecture/product documents. - Standalone operation and modular MSA embedding must be documented as co-equal supported boundaries; no ContextualWisdomLab host is a hidden runtime requirement. - Tenant scope is selected only by a trusted authenticated/authorized host boundary and, for the tenant durable client, validates before observation reservation, credential lookup, provider I/O, or lifecycle database I/O. Lifecycle identities, conflict targets, exact reads, and operational status indexes remain tenant-qualified where tenancy is enabled. -- `pg_llm_batch.tenant_scope` is transaction-local routing context, not a credential or authenticated identity. Only package code acting on trusted host selection may set it for tenant-owned operations; arbitrary SQL must not select or override tenant authority through `set_config`. +- `pg_llm_batch.tenant_scope` is transaction-local routing context, not a credential or authenticated identity. Any database role capable of arbitrary SQL can call `set_config` with an arbitrary tenant scope; the trusted application boundary must therefore prevent generic tenant-controlled SQL, SQL injection, and incorrect identity mapping from selecting tenant authority. RLS does not provide those guarantees. - The standalone `DurableBatchAPIClient` retains its four-argument lifecycle-recorder seam and explicit `standalone` persistence/read scope unless a separately reviewed compatibility change is integrated. - PostgreSQL RLS is defense in depth, not host authentication/authorization, SQL-injection prevention, or correct identity mapping; production application roles for the tenant lifecycle boundary are `NOSUPERUSER NOBYPASSRLS`. - Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. +- Content-fidelity invariants constrain any result-application path that exists, but they do not prove that end-to-end result application is shipped; FR-4 and `docs/TRACEABILITY.md` remain the capability-status authority while protected main is `PARTIAL`. - Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. - Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. - Database object names, migration/rollback behavior, exact owned coverage requirements, Python-version acceptance, packaging/SBOM/provenance expectations, and bounded diagnostics must remain synchronized with repository tests and live governance. From 20b5362fbfdf1036ec891bfcf202865dd7000636 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 16 Aug 2026 14:06:55 +0900 Subject: [PATCH 22/58] docs(privacy): bound result and retention contracts --- docs/product/TRD.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/product/TRD.md b/docs/product/TRD.md index c689e6b93..918ec518a 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -101,9 +101,9 @@ Standalone provider configuration and encrypted secrets are PostgreSQL-backed. E ### Authorized content fidelity -The package does not gain authority to mask, tokenize away, truncate for privacy, or otherwise alter an authorized prompt, request, JSONL record, or provider result merely because the content may contain PII. Silent transformation would change token counts, provider semantics, persisted evidence, replay behavior, and downstream business meaning. Package serialization, token accounting, persistence, upload, retrieval, and result application therefore preserve authorized business content unless an explicit reviewed feature contract says otherwise. +The package does not gain authority to mask, tokenize away, truncate for privacy, or otherwise alter an authorized prompt, request, JSONL record, or provider result merely because the content may contain PII. Silent transformation would change token counts, provider semantics, persisted evidence, replay behavior, and downstream business meaning. Serialization, token accounting, persistence, upload, and retrieval paths implemented on protected main therefore preserve authorized business content unless an explicit reviewed feature contract says otherwise. The same content-fidelity invariant constrains any result-application path that exists, but end-to-end result application remains **PARTIAL** under FR-4 and `docs/TRACEABILITY.md`; PR #194 is an **ACTIVE-PR** transaction-seam candidate, not protected-main proof of a completed result-application capability. -Confidentiality for content-bearing data is enforced through boundary controls rather than a blanket masking default: the embedding host authenticates and authorizes the caller and selects tenant scope; package/database/service identities remain least-privilege; transport uses the reviewed secure destination policy; deployment/storage protections are owned and evidenced at the applicable layer; retention and deletion are purpose-limited and explicit; and package-owned errors, logs, telemetry, readiness, CI/review evidence, and other operational surfaces omit content-bearing values. A host that intentionally transforms content must do so through an explicit business-policy boundary with provenance and acceptance tests. Redacted operational evidence must never be represented as proof that persisted or provider-bound business content was masked. +Confidentiality for content-bearing data is enforced through boundary controls rather than a blanket masking default: the embedding host authenticates and authorizes the caller and selects tenant scope; package/database/service identities remain least-privilege; and transport uses the reviewed secure destination policy. Protected main does not define a universal business-data retention duration or a general destructive deletion workflow. The embedding host owns business purpose, retention period, deletion authorization/trigger, and evidence that its policy was executed; the deployment owner separately owns PostgreSQL backup/replica, log/telemetry, and infrastructure retention/deletion controls; provider-side retention/deletion remains a provider/account-policy responsibility unless an explicit reviewed package adapter contract implements and verifies it. Package-owned errors, logs, telemetry, readiness, CI/review evidence, and other operational surfaces omit content-bearing values. A host that intentionally transforms content must do so through an explicit business-policy boundary with provenance and acceptance tests. Redacted operational evidence must never be represented as proof that persisted or provider-bound business content was masked or deleted. ### Diagnostic confidentiality @@ -157,4 +157,4 @@ A release may originate only from the exact integrated protected head after all ## Documentation requirements -Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. \ No newline at end of file +Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. From 008aa9868602f5e0a886f2ddc537c312db70d184 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:02:06 +0900 Subject: [PATCH 23/58] docs(recovery): trace integrated evidence and active executors --- docs/TRACEABILITY.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 49409b9f0..36df331a9 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -4,7 +4,7 @@ This map ties the canonical PRD/TRD requirements to stable protected-main implementation, test, ADR, and operator evidence. It intentionally avoids workflow-run IDs, predecessor SHAs, generated merge commits, and review comments because those are transient verification records rather than durable requirements authority. -The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. Rows marked **ACTIVE-PR** or **PARTIAL** are not shipped implementation claims. +The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. Rows marked **ACTIVE-PR** or **PARTIAL** are not shipped implementation claims. ## Product-to-technical traceability @@ -18,6 +18,10 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | FR-4 tenant-qualified cross-process single-flight | ACTIVE-PR | none on protected main beyond existing DB primitives | PR #191 exact-head evidence only | Not shipped; qualifying independent approval remains a live-governance concern. | | FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | PR #194 is ACTIVE-PR test-first work that adds a same-transaction local result-effect/checkpoint seam; protected main still does not claim end-to-end or distributed exactly-once application. | | FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | +| FR-5 bounded PostgreSQL recovery evidence primitives | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/postgres_recovery_receipt.py`, `pg_llm_batch/postgres_backup_evidence.py`, `pg_llm_batch/postgres_schema_evidence.py` | focused receipt/artifact/schema evidence tests; merged PRs #205, #206, #207 are historical integration evidence | Protected main can derive bounded content-free receipt, backup-artifact hash/size, and packaged-schema hash/size evidence. These primitives do not prove that a backup command ran successfully, that an artifact is restorable, that a live cluster matches packaged schema, or that PITR/RPO/RTO/HA/DR objectives are satisfied. | +| FR-5 executable PostgreSQL logical backup | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #208 exact-head evidence only | The `pg_dump` execution candidate is not shipped. Its service selector is not tenant authorization, and current exact-head review/check evidence must be reacquired before integration. | +| FR-5 executable PostgreSQL logical restore | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #209 exact-head evidence only | The direct `pg_restore` candidate is not shipped. Its caller-owned source-superuser trust assertion, target-isolation responsibility, libpq allowlist, single-transaction failure boundary, and archive-integrity checks remain active-PR contracts until integration. | +| FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded receipt/artifact/schema evidence primitives are integrated | Issue #204 acceptance authority plus protected-main recovery evidence tests | No protected-main end-to-end isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. PR #193 proposes an encryption-required default plus explicit local/development opt-out while also separating runtime construction from provisioning. | | FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes the selected deployment policy through redacted readiness/operator evidence. PR #193 addresses the default-policy boundary only while it remains ACTIVE-PR. | @@ -42,6 +46,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Protected main supports Fernet but does not require it by default; the compatibility path is not a production confidentiality claim. PR #193's stricter default is ACTIVE-PR, while enterprise secret-manager choice remains host-owned. | | Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic `ValidationError` rejected-value confidentiality remains incomplete on protected main; PR #202 is ACTIVE-PR and its evidence does not transfer until merge. | | Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | +| Recovery evidence confidentiality/integrity | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | recovery receipt/artifact/schema evidence regressions | Evidence is bounded and content-free but does not authenticate an operator, prove backup provenance beyond caller-supplied receipt inputs, or prove restore semantics. | | Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability are operational dependencies. | ## Data and persistence traceability @@ -52,6 +57,7 @@ The reference protected-main tree is `d0a4b30be1f46536e352443309f3a35533156767`. | Result checkpoints | `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | ADR 0006, ADR 0007, `docs/result-streaming.md` | Prefix checkpoint is not provider authentication or whole-stream immutability; cross-system exactly-once is not claimed. | | Package JSONL/payload state | package-owned schema identities and virtual payload references | PRD/TRD, schema-integrity and payload docs/tests | Persisted package data is canonical, not a disposable cache. | | Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Shipped compatibility mode can still persist `is_encrypted = FALSE`; runtime/provisioning least-privilege separation, required-encryption default, legacy-row migration, key rotation/recovery, and redacted policy-readiness evidence are not all protected-main behavior. | +| PostgreSQL recovery evidence | bounded receipt metadata plus backup/schema SHA-256 and byte-size evidence | protected-main recovery evidence modules/tests; canonical PRD/TRD/this traceability map once integrated | The evidence does not itself persist a backup, execute backup/restore, prove isolated target parity, or establish PITR/RPO/RTO/HA/DR. Backup storage, encryption, retention, key custody, and external copies remain deployment/operator responsibilities unless a separately integrated contract says otherwise. | | Release evidence | descriptor/artifact identity contracts | ADR 0003, ADR 0004 | Evidence proves the reviewed artifact path, not organizational certification. | ## Active overlay register @@ -66,6 +72,10 @@ The following open pull requests are intentionally represented only as overlays - **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. - **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening. It is Draft because the current `safe_value` guard accepts `str` subclasses via `isinstance`; the branch must first require an exact built-in `str` and pass a hostile-subclass regression. Protected main still discloses arbitrary rejected values by default, and the intended safe-default redaction/bounded `safe_value` contract remains ACTIVE-PR until integrated. +- **#208** — bounded logical PostgreSQL backup executor candidate using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. +- **#209** — bounded direct logical PostgreSQL restore executor candidate using `pg_restore`; active source only and not evidence of isolated restore acceptance or end-to-end recovery readiness. + +Merged recovery PRs #205, #206, and #207 are no longer active overlays; their bounded receipt, backup-artifact, and packaged-schema evidence primitives are present on the referenced protected-main tree. Their historical PR descriptions remain integration evidence, not durable runtime authority. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. From e2076821bf944ad4c16b44d1d2266455f06e68ff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:03:10 +0900 Subject: [PATCH 24/58] docs(recovery): refresh documentation fitness at protected main --- docs/DOCUMENTATION_FITNESS.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 94e538004..083d1bd5b 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -2,38 +2,42 @@ ## Authority and status model -This inventory evaluates the documentation graph against the exact protected-main tree `d0a4b30be1f46536e352443309f3a35533156767`. It does not promote pull-request content into shipped truth. The canonical status vocabulary is shared with `docs/product/PRD.md` and `docs/product/TRD.md`: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. +This inventory evaluates the documentation graph against the exact protected-main tree `d2f1e32271910a6db98a0757d67194ddadca4566`. It does not promote pull-request content into shipped truth. The canonical status vocabulary is shared with `docs/product/PRD.md` and `docs/product/TRD.md`: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. A document is *fit* only when it states the correct authority boundary, is consistent with the protected-main code/schema/tests it describes, avoids transferring predecessor or active-branch evidence into shipped claims, and gives an operator or reviewer enough information to use, verify, recover, or reject the relevant behavior safely. The tenant lifecycle material in this canonical cohort is a reconstruction of already integrated protected-main behavior, not a new runtime tenant/RLS/migration contract. Companion-document verification against protected main confirms the same contract is already present in the public `README.md`, root `ARCHITECTURE.md`, topic operator guide `docs/remote-batch-lifecycle.md`, accepted ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md`. Those authorities already cover trusted tenant identity, `NOSUPERUSER NOBYPASSRLS`, transaction-local/forced RLS, direct-SQL limits, legacy-to-`standalone` migration, and rollback constraints. The canonical PRD/TRD therefore may cite that existing evidence without rewriting those protected-main files or racing PR #184's separate legacy-extension-retirement documentation lane. +Protected main now also contains the bounded recovery-evidence primitives integrated by #205, #206, and #207: content-free PostgreSQL recovery receipts, descriptor-pinned backup-artifact hash/size evidence, and packaged-schema hash/size evidence. These are evidence primitives only. They do not make executable logical backup/restore, isolated restore acceptance, WAL/PITR, key/config custody, or any RPO/RTO/HA/DR objective shipped; #208 and #209 remain active source candidates and Issue #204 remains the end-to-end recovery authority. + ## Current fitness matrix | Documentation surface | Status | Fitness assessment | Required next action | | --- | --- | --- | --- | -| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. | Keep beginner-readable; update only when a bounded shipped capability actually changes after merge. | -| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file. | -| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states and cites deterministic protected-main tenant/standalone acceptance authority. | Validate exact-head docs gates and integrate only through normal PR governance. | -| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, and release/testing invariants are explicit. | Validate exact-head docs gates and integrate only through normal PR governance. | -| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. | -| `docs/adr/README.md` | ACTIVE-PR | This canonical branch now supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Validate exact-head documentation gates and integrate only through normal PR governance. | +| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. The newly integrated recovery-evidence primitives are not yet a complete operator recovery procedure. | Keep beginner-readable; add shipped recovery semantics only when adjacent writer ownership permits and do not present evidence primitives as a restorable-backup guarantee. | +| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. Recovery evidence has advanced on protected main without establishing end-to-end recovery semantics. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file, and update recovery architecture only through a non-conflicting governed documentation lane. | +| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states and cites deterministic protected-main tenant/standalone acceptance authority. | Reflect the integrated recovery-evidence primitives while keeping executable backup/restore and end-to-end recovery PARTIAL/ACTIVE-PR; validate exact-head docs gates and integrate only through normal PR governance. | +| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, and release/testing invariants are explicit. | Add the bounded recovery-evidence technical boundary without promoting #208/#209; validate exact-head docs gates and integrate only through normal PR governance. | +| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. Add or amend an ADR only if the recovery execution/rollback architecture becomes a durable decision requiring one. | +| `docs/adr/README.md` | ACTIVE-PR | This canonical branch supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Keep the referenced protected-main tree current; do not invent a recovery ADR that is not integrated. | | `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | | `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Serves as the topic-specific operator authority for durable lifecycle tenancy. It already specifies trusted scope selection, pre-effect validation, four-argument standalone recorder compatibility, tenant-qualified identity/conflict/read behavior, forced RLS/application-role limits, migration, direct-SQL impact, rollback, recovery, and deterministic verification. | Keep synchronized with tenant/RLS and lifecycle migrations; do not duplicate this contract into a competing operator file. | | `docs/doctoring/tenant-scoped-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Supporting evidence independently records pre-effect validation, explicit standalone compatibility, database role/RLS limits, migration and rollback, plus current primary references. | Keep supporting references current; do not promote doctoring into the sole product authority. | | `CHANGELOG.md` tenant lifecycle entry | IMPLEMENTED-ON-PROTECTED-MAIN | The protected-main Unreleased section already records tenant-scoped durable lifecycle, forced default-deny RLS, standalone compatibility, and the atomic tenant migration fix. | Change only when integrated shipped behavior changes; do not log active-PR claims as shipped. | | Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | +| PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py` are integrated protected-main primitives with focused tests. They produce bounded content-free metadata/hash/size evidence without executing SQL or claiming cluster parity. | Keep the evidence/guarantee distinction explicit. Do not claim restorable backup, isolated restore, PITR, RPO/RTO/HA/DR, or compliance readiness from these primitives alone. | +| PostgreSQL logical backup/restore execution | ACTIVE-PR | #208 proposes bounded `pg_dump` execution and #209 proposes bounded direct `pg_restore` execution. Neither is protected-main truth. #209 also introduces a direct-SQL/rollback contract that requires permanent operator/architecture/ADR/doctoring/CHANGELOG documentation once writer ownership is coordinated. | Do not race those source branches or adjacent documentation writers. Promote only after exact-head gates, valid findings, required documentation, qualifying approval, and protected-main integration. | | Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation for retiring legacy `http` / `pg_cron`; it is a different contract from the already-shipped tenant lifecycle migration and is not protected-main truth. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | | Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. It is not shipped until normal governance integrates it. | Preserve the trusted-search-path/non-ownership caveat and reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | -| Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | +| Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and now distinguishes integrated recovery evidence from active executable recovery candidates. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | | UML/component/sequence views | PLANNED | Root architecture is prose-first; no canonical UML authority is present. | Add textual Mermaid/PlantUML-compatible component and critical sequence diagrams after active source contracts stabilize. | | ERD / schema model | PLANNED | SQL and schema tests are authoritative, but no canonical ERD summarizes package-owned identities, tenancy, checkpoint state, and relationships. | Generate/maintain an ERD from protected-main schema; label migration-only/active-PR objects separately. | -| General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184's active migration-specific operability work. | +| General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184 or #209 documentation surfaces. | | Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | | Licensing / third-party notices | PARTIAL | Apache-2.0 source headers and repository licensing exist, but acquisition diligence should explicitly trace package license, dependency/SBOM evidence, and third-party notice process. | Evaluate a concise licensing/compliance evidence index without claiming legal certification. | @@ -48,6 +52,8 @@ The tenant lifecycle material in this canonical cohort is a reconstruction of al - PostgreSQL RLS is defense in depth, not host authentication/authorization, SQL-injection prevention, or correct identity mapping; production application roles for the tenant lifecycle boundary are `NOSUPERUSER NOBYPASSRLS`. - Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. - Content-fidelity invariants constrain any result-application path that exists, but they do not prove that end-to-end result application is shipped; FR-4 and `docs/TRACEABILITY.md` remain the capability-status authority while protected main is `PARTIAL`. +- Bounded recovery receipts, artifact hashes, and packaged-schema hashes are evidence primitives, not proof that a backup is restorable or that a stated recovery objective is met. +- A future direct logical restore contract must keep caller-owned source trust, target isolation, allowed libpq environment, transaction rollback behavior, and post-restore acceptance explicit; those active-PR semantics are not shipped until integrated. - Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. - Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. - Database object names, migration/rollback behavior, exact owned coverage requirements, Python-version acceptance, packaging/SBOM/provenance expectations, and bounded diagnostics must remain synchronized with repository tests and live governance. From e5901d177e345601a93ca1a86dd3e7cea41ea7b4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:05:06 +0900 Subject: [PATCH 25/58] docs(recovery): align product contract with protected main --- docs/product/PRD.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 5fac473bb..47ef86feb 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -33,6 +33,7 @@ The product must let a qualified host: - submit, poll, wait, cancel, and retrieve through validated OpenAI-compatible Batch API clients; - operate in exact `standalone` mode or with a trusted tenant-qualified lifecycle identity; - recover or reconcile provider lifecycle state without introducing a second database-side networking authority; +- derive bounded content-free PostgreSQL recovery evidence for backup artifacts and the packaged schema without treating evidence as proof of restorability; and - prove package quality, security, reproducibility, release-artifact identity, and rollback assumptions through repository evidence. ## Protected-main capability contract @@ -47,6 +48,12 @@ The product must let a qualified host: | Durable resumable result checkpoint/CAS storage | IMPLEMENTED-ON-PROTECTED-MAIN | PostgreSQL supplies tenant-qualified durable checkpoint authority and conflict detection; this is not a distributed exactly-once claim. | | Redacted readiness reporting | IMPLEMENTED-ON-PROTECTED-MAIN | Public readiness evidence does not disclose arbitrary lower-layer diagnostic content. | | Scheduler-independent bounded provider reconciliation primitive | IMPLEMENTED-ON-PROTECTED-MAIN | A host can submit a finite, validated candidate set for polling/retrieval through the existing bounded provider client; candidate discovery, scheduling, and cross-process lease ownership remain outside this primitive. | +| Bounded PostgreSQL recovery receipt | IMPLEMENTED-ON-PROTECTED-MAIN | The package can encode/decode deterministic bounded content-free metadata that identifies package/source/PostgreSQL/schema/backup evidence without carrying credentials, DSNs, SQL, business payloads, or arbitrary diagnostics. | +| Bounded PostgreSQL backup-artifact integrity evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from one private regular backup artifact under descriptor-pinned, no-follow, finite-work constraints without executing backup or restore. | +| Bounded packaged PostgreSQL schema evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from the exact distributed `schema.sql` resource under a finite package-owned work budget without executing SQL or asserting live-cluster parity. | +| PostgreSQL logical backup execution | ACTIVE-PR | A `pg_dump` candidate exists in #208 but is not shipped; protected main must not be described as creating a restorable backup from the evidence primitives alone. | +| PostgreSQL logical restore execution | ACTIVE-PR | A direct `pg_restore` candidate exists in #209 but is not shipped; its caller-owned source trust, target-isolation responsibility, libpq allowlist, transactional failure boundary, and archive-integrity contract remain active-PR semantics. | +| End-to-end PostgreSQL recovery readiness | PARTIAL | Integrated evidence primitives do not yet prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative before it can become product truth. | | Cross-process reconciliation single-flight | ACTIVE-PR | Concurrent workers must not race the same tenant/provider identity; merge eligibility remains governed by live repository policy. | | Existing-volume legacy `http` / `pg_cron` retirement | ACTIVE-PR | Existing deployments need fail-closed, reversible migration evidence before compatibility packages can be removed. | @@ -76,14 +83,18 @@ Standalone source compatibility is also normative. `DurableBatchAPIClient` retai Protected-main acceptance authority for these invariants is deterministic: `tests/test_tenant_durable_client.py` proves construction-time pre-effect tenant validation and the four-argument standalone recorder seam; `tests/test_tenant_lifecycle_persistence.py` proves explicit `standalone` delegation, tenant-qualified conflict targets and reads, malformed-scope rejection before database access, and distinct tenant identities; `pg_llm_batch/schema.sql` supplies the tenant-qualified unique key, forced RLS policy, and tenant-qualified operational status index. `docs/remote-batch-lifecycle.md`, ADR 0002, and `docs/doctoring/tenant-scoped-lifecycle.md` describe the same protected-main contract. -### FR-4: Reconciliation and recovery +### FR-4: Reconciliation and provider-effect recovery Reconciliation shall be finite, deterministic, payload-free in its operational evidence, and use the same validated provider client boundary as normal operations. Candidate discovery, concurrency control, scheduling, and result-application semantics must be explicit capabilities rather than inferred from polling code. Provider-success/database-failure cases must remain observable recovery states rather than being rewritten as if the provider effect never occurred. -### FR-5: Persistence integrity +### FR-5: Persistence integrity and PostgreSQL recovery evidence Package-owned database rows shall use descriptive two-or-more-word `snake_case` object names where applicable, explicit durable identities, parameterized SQL, and migrations that are idempotent or have a documented one-way boundary. Schema copies maintained for package and Docker initialization shall remain synchronized where the repository contract requires it. Malformed durable payload/state shall fail closed before downstream credential or provider effects when correctness depends on that state. +Protected main shall provide bounded, content-free recovery evidence without overstating its guarantee. `PostgresRecoveryReceipt` identifies one evidence set using package version, exact source commit, PostgreSQL major version, schema SHA-256, a reviewed backup-method vocabulary, backup-artifact SHA-256 and size, and bounded start/completion epochs. Backup-artifact inspection shall pin directory/file identity, reject symlink traversal and unsafe file shapes, remain within a caller-visible finite hashing budget, and return only hash/size evidence. Packaged-schema inspection shall stream the exact distributed `schema.sql` under a finite package-owned budget and return only hash/size evidence. Malformed, ambiguous, duplicate-member, hostile-subclass, oversized, mutating, unreadable, or cleanup-failing evidence shall fail closed through fixed package diagnostics. + +These primitives do not execute `pg_dump` or `pg_restore`, persist backup bytes, prove backup provenance or restorability, prove a live-cluster schema matches the package, authorize a tenant/operator, manage encryption keys, manage WAL, establish PITR, or prove RPO/RTO/HA/DR/compliance. Executable logical backup/restore and isolated-restore acceptance remain separate governed capabilities. A future direct restore must make caller-owned source-superuser trust, target isolation, allowed libpq credential/service environment, transaction rollback behavior, and post-restore acceptance explicit before it can become protected-main truth. + ### FR-6: Configuration and secrets PostgreSQL-backed configuration and encrypted-secret support remain available for standalone use. Environment variables are bootstrap transport only where explicitly documented. Embedding hosts may inject credential providers without changing provider protocol semantics. The package shall not invent an external secret-management product dependency. @@ -110,11 +121,11 @@ The package must not apply blanket masking or lossy transformation to authorized ### Reliability -Network, response, retry, wait, candidate-scan, payload, and release-evidence operations must be explicitly bounded. Recovery and rollback must be documented before migrations or release changes are considered complete. Queued, skipped, cancelled, absent, stale, predecessor-head, synthetic-merge-only, or infrastructure-failed evidence is not success for an exact source head. +Network, response, retry, wait, candidate-scan, payload, recovery-evidence, and release-evidence operations must be explicitly bounded. Recovery receipts and hashes are integrity/identity evidence, not restoration success. Recovery and rollback must be documented before migrations or release changes are considered complete. Queued, skipped, cancelled, absent, stale, predecessor-head, synthetic-merge-only, or infrastructure-failed evidence is not success for an exact source head. ### Interoperability -Provider interaction stays OpenAI-Batch-compatible behind a validated Python client seam. Embedding hosts can provide credentials and control-plane context without changing the package's durable/provider semantics. +Provider interaction stays OpenAI-Batch-compatible behind a validated Python client seam. Embedding hosts can provide credentials and control-plane context without changing the package's durable/provider semantics. PostgreSQL backup/restore executors, when integrated, must remain caller-targeted infrastructure seams rather than hidden dependencies on a specific ContextualWisdomLab host. ### Packaging and release @@ -127,10 +138,11 @@ Dependencies must be locked/reproducible according to repository policy. Release - Making provider payload/model output an authority for tenant or endpoint selection. - Providing an unbounded general-purpose HTTP proxy. - Reintroducing provider networking or independent scheduling inside PostgreSQL. +- Claiming a backup is restorable, a live cluster matches packaged schema, or a recovery objective is met from receipt/hash evidence alone. - Claiming distributed exactly-once processing without an integrated transaction/recovery contract spanning every external effect. - Requiring a specific ContextualWisdomLab host service for standalone operation. - Claiming SOC 2, CSAP, or other certification solely from repository controls. ## Product acceptance boundary -A product capability moves to **IMPLEMENTED-ON-PROTECTED-MAIN** only after its unchanged source has satisfied the live ruleset, required exact-head CI/security/coverage/package/provenance/release checks, valid review findings are resolved, and the resulting tree is integrated into the protected default branch. Documentation must then be updated to move the capability out of `ACTIVE-PR`, `PARTIAL`, or `PLANNED`; historical evidence must not be transferred as if it were proof for a different head. \ No newline at end of file +A product capability moves to **IMPLEMENTED-ON-PROTECTED-MAIN** only after its unchanged source has satisfied the live ruleset, required exact-head CI/security/coverage/package/provenance/release checks, valid review findings are resolved, and the resulting tree is integrated into the protected default branch. Documentation must then be updated to move the capability out of `ACTIVE-PR`, `PARTIAL`, or `PLANNED`; historical evidence must not be transferred as if it were proof for a different head. From ad761d336f113b2ac8eb879e9402975ac6af2623 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:06:31 +0900 Subject: [PATCH 26/58] docs(recovery): align technical contract with protected main --- docs/product/TRD.md | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/product/TRD.md b/docs/product/TRD.md index 918ec518a..3449661f1 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -8,7 +8,7 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A ## System boundary -`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It may run standalone or be embedded by another service. The package owns batch preparation, package persistence, validated provider Batch API access, durable lifecycle projection, resumable checkpoint storage, and bounded reconciliation primitives. It does not own host authentication, business authorization, ingress/WAF, infrastructure TLS policy, external secret-manager choice, global OpenTelemetry configuration, or a cross-system distributed transaction. +`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It may run standalone or be embedded by another service. The package owns batch preparation, package persistence, validated provider Batch API access, durable lifecycle projection, resumable checkpoint storage, bounded reconciliation primitives, and bounded content-free PostgreSQL recovery-evidence primitives. It does not own host authentication, business authorization, ingress/WAF, infrastructure TLS policy, external secret-manager choice, global OpenTelemetry configuration, backup-storage infrastructure, WAL/archive infrastructure, or a cross-system distributed transaction. ## Component contract @@ -21,6 +21,9 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A | `db.py` | schema application and parameterized persistence/read helpers, including tenant-qualified lifecycle context, conflict identity, and exact-row lookup | database-side provider networking, authenticating tenant callers | | `checkpoint_store.py` | tenant-qualified PostgreSQL checkpoint/CAS operations and conflict semantics | distributed exactly-once claims | | `reconciliation.py` | finite host-selected polling/retrieval pass using the existing validated client surface | candidate discovery, scheduling, cross-process leasing | +| `postgres_recovery_receipt.py` | encode/decode one deterministic bounded content-free PostgreSQL recovery evidence receipt | proving backup success/restorability, authenticating operators, carrying DSNs/credentials/business content | +| `postgres_backup_evidence.py` | derive SHA-256 and byte-size evidence from one private regular backup artifact through descriptor-pinned no-follow traversal and finite work | executing `pg_dump`/`pg_restore`, persisting backup bytes, proving restore semantics | +| `postgres_schema_evidence.py` | derive SHA-256 and byte-size evidence from the exact distributed `pg_llm_batch/schema.sql` resource under a finite package-owned budget | executing SQL, proving live-cluster parity or migration currency | | `config.py` | PostgreSQL-backed configuration and encrypted secret storage for standalone composition | prescribing an embedding host's external secret manager | | `observability.py` | opt-in bounded traces/metrics around reviewed operations | configuring global SDK/exporter/resource policy | | `health.py` | readiness aggregation and redacted public health response | general-purpose web serving or arbitrary diagnostic reflection | @@ -28,6 +31,8 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A The protected-main validation authority for the `durable_client.py` compatibility row is `pg_llm_batch/durable_client.py`, `tests/test_tenant_durable_client.py`, and `tests/test_tenant_lifecycle_persistence.py`: the tests prove construction-time tenant rejection before downstream effects, exact four-argument standalone recorder invocation, explicit `standalone` persistence/read delegation, and tenant-qualified lifecycle persistence/read identities. +The protected-main validation authority for recovery evidence is the three recovery modules plus their focused test suites. Historical merged PRs #205, #206, and #207 are integration evidence, not runtime authority. `docs/TRACEABILITY.md` remains the canonical status map for the distinction between integrated evidence primitives and active backup/restore execution candidates. + ## Runtime architecture ### Batch preparation @@ -77,6 +82,18 @@ Protected main supplies a scheduler-independent `reconcile_batch_candidates(...) The host still owns candidate discovery, tenant authorization, scheduling, and cross-process concurrency. Durable candidate discovery and tenant-qualified advisory single-flight are **ACTIVE-PR** surfaces; neither is treated as shipped until protected-main integration. Package-owned autonomous scheduling, crash/restart completion semantics, terminal-work retirement after durable result application, and an end-to-end exactly-once worker remain **PARTIAL** or **PLANNED** capabilities. +### PostgreSQL recovery evidence + +Protected main supplies three deliberately non-executing recovery-evidence primitives. + +1. `PostgresRecoveryReceipt` binds exact built-in primitive metadata for package version, source commit, PostgreSQL major, packaged-schema SHA-256, reviewed backup-method vocabulary (`logical`, `physical`, or `pitr`), backup artifact SHA-256/size, and bounded timestamps. Its JSON representation is deterministic and size-bounded, rejects duplicate/unknown fields and hostile subclasses, and maps ordinary malformed input/decoder failures to fixed content-free diagnostics. +2. `inspect_postgres_backup_artifact(...)` traverses path components through pinned directory descriptors with no-follow semantics, rejects `..`, symlinked parents/final components, non-regular/empty/oversized files and unsafe link counts/permissions as defined by the implementation contract, hashes under an explicit finite maximum-size work budget, bounds each read request by remaining budget, compares descriptor identity/metadata before and after hashing, and treats cleanup failures as bounded evidence without masking an already-selected primary error. +3. `inspect_postgres_schema()` streams the exact distributed `pg_llm_batch/schema.sql` resource through SHA-256 under a finite package-owned work budget and returns only SHA-256 plus byte size. Missing, unreadable, empty, oversized, malformed-chunk, hostile-subclass, or cleanup-failing resources fail closed through fixed content-free diagnostics. + +These primitives do not execute SQL or database mutation. They do not prove the backup command succeeded, prove backup provenance beyond caller-controlled receipt fields, prove restorability, prove a live database matches the packaged schema, provide target isolation, manage keys/secrets, manage physical/WAL/PITR infrastructure, or establish RPO/RTO/HA/DR/compliance. Those are separate acceptance domains. + +Logical `pg_dump` execution in #208 and direct `pg_restore` execution in #209 remain **ACTIVE-PR**. Until integration, no protected-main technical contract may rely on those executors. The direct-restore candidate additionally requires permanent operator/architecture/ADR/doctoring/CHANGELOG coverage for caller-owned source-superuser trust, the non-authorizing service selector, permitted inherited libpq variables, single-transaction rollback behavior, target isolation, and post-restore acceptance before it may be represented as shipped. + ## Persistence requirements ### Naming and schema ownership @@ -93,12 +110,16 @@ Package-owned persisted virtual JSONL is canonical state, not a best-effort cach Durable provider/resource identifiers and tenant identities are validated before they become persistence or authorization inputs. Database/query failures must not be silently reclassified as an authoritative no-row result when correctness depends on distinguishing those cases. +Recovery evidence is identity/integrity metadata, not a second persistence authority. The package does not own backup storage, replica lifecycle, object-store retention, WAL archives, encryption-at-rest infrastructure, or backup deletion merely because it can hash an operator-selected artifact. Operators/deployments must keep those responsibilities explicit. + ## Security and privacy requirements ### Secrets Standalone provider configuration and encrypted secrets are PostgreSQL-backed. Environment variables are limited to explicitly documented bootstrap transport such as the database DSN and optional encryption key. CLI secret entry uses no-echo prompting or bounded standard input rather than plaintext process arguments. Embedding hosts may supply another credential provider through the supported seam. +Recovery evidence must not carry DSNs, passwords, Fernet keys, prompts/results, ciphertext, arbitrary SQL, provider payloads, paths where not required by the callable interface, dynamic exception names, or reflected lower-layer diagnostics. A future backup/restore executor must isolate credentials from process arguments and ambient environment according to its separately reviewed contract. + ### Authorized content fidelity The package does not gain authority to mask, tokenize away, truncate for privacy, or otherwise alter an authorized prompt, request, JSONL record, or provider result merely because the content may contain PII. Silent transformation would change token counts, provider semantics, persisted evidence, replay behavior, and downstream business meaning. Serialization, token accounting, persistence, upload, and retrieval paths implemented on protected main therefore preserve authorized business content unless an explicit reviewed feature contract says otherwise. The same content-fidelity invariant constrains any result-application path that exists, but end-to-end result application remains **PARTIAL** under FR-4 and `docs/TRACEABILITY.md`; PR #194 is an **ACTIVE-PR** transaction-seam candidate, not protected-main proof of a completed result-application capability. @@ -117,6 +138,10 @@ RLS augments a trusted host authorization boundary; it is not itself authenticat Provider URLs, statuses, IDs, headers, JSON, JSONL, retry guidance, and metadata are untrusted external input. Validation occurs before the downstream effect that relies on that value. Model/provider output never grants tenant, endpoint, credential, or filesystem authority. +### Recovery authority boundary + +A backup artifact, receipt, service selector, schema hash, or backup method string is not authorization to read, write, restore, or replace a database. Authentication, authorization, target isolation, backup custody, key custody, destructive-operation approval, and recovery-objective ownership remain external until a separately integrated contract explicitly supplies and verifies them. Recovery evidence must never be used to infer those authorities. + ## Observability requirements OpenTelemetry support is opt-in. Base installations must not require OpenTelemetry packages solely to use normal batch functionality. Operation names, outcomes, and error categories are finite. Telemetry attributes exclude endpoint aliases, provider URLs, resource identifiers, credentials, metadata, prompts, and provider response bodies. @@ -129,10 +154,14 @@ Readiness covers the required PostgreSQL/tokenizer/configuration boundary and re Operational migrations require backup/preflight/acceptance/recovery documentation before release. A recovery instruction must preserve package and operator-owned state; destructive `CASCADE`, hidden history rewrite, or deletion of unknown operator objects is not an acceptable shortcut. +A recovery drill must distinguish artifact identity from restore acceptance. At minimum, acceptance criteria for a future end-to-end logical restore must address exact schema/package identity, required schema/RLS/constraint/extension behavior, migration compatibility, intended target isolation, credential/key availability, and rollback/recovery behavior. Physical/WAL/PITR drills additionally require their own timeline/target and infrastructure acceptance criteria. No repository evidence should claim universal RPO/RTO/HA/DR without an explicit measured deployment objective. + ## Concurrency requirements Batch preparation uses database coordination/transactionality appropriate to its package-owned state. Durable lifecycle writes use explicit ordering/conflict semantics. Any cross-process reconciliation exclusion must be tenant-qualified, non-blocking or finitely bounded, exception-safe, and clear about whether it is transient session state or durable lease state. Session advisory locking must never be promoted into a durable lease or distributed exactly-once claim. +Recovery-evidence file inspection must remain finite and fail closed under concurrent mutation. A successful hash/size result is valid only for the descriptor identity/metadata contract that was revalidated by the implementation; it is not a lock or lease over external backup infrastructure. + ## Testing requirements Every source defect follows realistic RED → narrow fix → GREEN → focused/full validation. Required repository evidence includes: @@ -144,6 +173,7 @@ Every source defect follows realistic RED → narrow fix → GREEN → focused/f - realistic PostgreSQL integration for SQL/RLS/migration/concurrency behavior; - package and container installation/health validation; - migration idempotency and rollback/recovery coverage where applicable; +- recovery-evidence tests for exact primitive types, duplicate/unknown metadata, finite work, descriptor/path boundaries, concurrent mutation, cleanup failure, and content-free diagnostics; - confidentiality regressions that inspect full exception/traceback surfaces when relevant; - security scanning and SAST; - dependency-lock and packaging reproducibility; @@ -155,6 +185,10 @@ Queued, pending, skipped, cancelled, absent, neutral, stale, predecessor-head, s A release may originate only from the exact integrated protected head after all live required quality, security, review, migration, rollback/recovery, operational, packaging, provenance, and release-acceptance gates are terminal-success. Versioning and CHANGELOG updates are followed by publication and artifact verification. Repository control evidence may support SOC 2 / CSAP readiness but must not be represented as certification. +The presence of recovery-evidence primitives does not make a release recovery-ready for a deployment. A release or operator contract that claims restore/PITR/RPO/RTO/HA/DR readiness must cite the exact integrated executor/drill/acceptance evidence for that deployment objective rather than extrapolating from hash/receipt modules. + ## Documentation requirements Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. + +Direct-SQL or rollback authority introduced by a future backup/restore executor requires coordinated permanent README, operator, architecture, ADR (or explicit accepted amendment/no-new-decision rationale), doctoring/reference, and CHANGELOG coverage. Active PR source may document its own callable boundary, but canonical docs must not represent it as shipped before integration. From 458a1056ac6dbaad7e5ad61e9924ec29848fb64f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:07:16 +0900 Subject: [PATCH 27/58] docs(recovery): refresh ADR index authority and recovery boundary --- docs/adr/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index d169ab9a0..d9f677522 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -4,7 +4,7 @@ This index is a navigation and status aid for architecture decision records that exist on protected `main`. The decision record itself remains the normative source for its context, decision, consequences, security boundary, and supersession rules. -The protected-main tree used to reconstruct this index is `d0a4b30be1f46536e352443309f3a35533156767`. A pull request, historical branch, generated merge commit, workflow run, review comment, or proposed file that is not on protected main is not silently promoted into this index. +The protected-main tree used to reconstruct this index is `d2f1e32271910a6db98a0757d67194ddadca4566`. A pull request, historical branch, generated merge commit, workflow run, review comment, or proposed file that is not on protected main is not silently promoted into this index. ## Protected-main decisions @@ -17,6 +17,8 @@ The protected-main tree used to reconstruct this index is `d0a4b30be1f46536e3524 | [0007](0007-durable-result-checkpoint-store.md) | Durable tenant-isolated result checkpoint store | Accepted | Adds optional PostgreSQL persistence, tenant isolation, compare-and-swap concurrency, and a caller-owned transaction seam without claiming distributed exactly-once delivery. Depends on ADR 0006. | | [0015](0015-http-425-too-early-retry.md) | HTTP 425 retry for bounded idempotent GETs | Accepted for the bounded retry slice | Keeps the default GET retry-status set closed, side-effecting POSTs single-attempt, and TLS/certificate/fingerprint failures outside automatic retry. | +Protected main also contains bounded PostgreSQL recovery-evidence primitives in `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py`. Their integration does **not** create an implicit ADR. They are implementation/evidence contracts recorded by the PRD/TRD/traceability map, while executable logical backup/restore and end-to-end recovery remain active/partial work. If a future restore executor introduces a durable architectural decision about direct SQL authority, target isolation, source-superuser trust, libpq credential/environment handling, or rollback/acceptance semantics, that decision must be added or explicitly amended through normal ADR governance rather than inferred from the implementation. + ## Numbering and missing identifiers ADR numbers are stable identifiers, not a promise of contiguous numbering. The absence of `0001`, `0005`, or `0008` through `0014` from the protected-main directory does **not** mean those decisions are missing, rejected, accepted elsewhere, or safe to reconstruct from old branches. Gaps may reflect historical work, superseded proposals, unmerged branches, or reserved identifiers. Only a reviewed protected-main document may establish the status of a missing number. @@ -46,4 +48,4 @@ For a material architecture change: ## Non-guarantees that must remain visible -The current ADR set does not establish authentication from PostgreSQL RLS alone, provider authenticity from result checkpointing, full-stream immutability from a prefix checkpoint, distributed exactly-once processing, retry permission for arbitrary HTTP failures, or organizational security/compliance certification. Those boundaries must not be weakened by summaries, operator docs, marketing material, or future ADR titles. \ No newline at end of file +The current ADR set does not establish authentication from PostgreSQL RLS alone, provider authenticity from result checkpointing, full-stream immutability from a prefix checkpoint, distributed exactly-once processing, retry permission for arbitrary HTTP failures, backup restorability or PITR/RPO/RTO/HA/DR from recovery receipts/hashes alone, or organizational security/compliance certification. Those boundaries must not be weakened by summaries, operator docs, marketing material, or future ADR titles. From 89f4e52df9e36c6e9af6576b995f00ae5ded60c6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:14:34 +0900 Subject: [PATCH 28/58] docs(recovery): mark seek-safe restore successor --- docs/DOCUMENTATION_FITNESS.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 083d1bd5b..2ef97bca1 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -8,7 +8,7 @@ A document is *fit* only when it states the correct authority boundary, is consi The tenant lifecycle material in this canonical cohort is a reconstruction of already integrated protected-main behavior, not a new runtime tenant/RLS/migration contract. Companion-document verification against protected main confirms the same contract is already present in the public `README.md`, root `ARCHITECTURE.md`, topic operator guide `docs/remote-batch-lifecycle.md`, accepted ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md`. Those authorities already cover trusted tenant identity, `NOSUPERUSER NOBYPASSRLS`, transaction-local/forced RLS, direct-SQL limits, legacy-to-`standalone` migration, and rollback constraints. The canonical PRD/TRD therefore may cite that existing evidence without rewriting those protected-main files or racing PR #184's separate legacy-extension-retirement documentation lane. -Protected main now also contains the bounded recovery-evidence primitives integrated by #205, #206, and #207: content-free PostgreSQL recovery receipts, descriptor-pinned backup-artifact hash/size evidence, and packaged-schema hash/size evidence. These are evidence primitives only. They do not make executable logical backup/restore, isolated restore acceptance, WAL/PITR, key/config custody, or any RPO/RTO/HA/DR objective shipped; #208 and #209 remain active source candidates and Issue #204 remains the end-to-end recovery authority. +Protected main now also contains the bounded recovery-evidence primitives integrated by #205, #206, and #207: content-free PostgreSQL recovery receipts, descriptor-pinned backup-artifact hash/size evidence, and packaged-schema hash/size evidence. These are evidence primitives only. They do not make executable logical backup/restore, isolated restore acceptance, WAL/PITR, key/config custody, or any RPO/RTO/HA/DR objective shipped. #208 remains the active logical-backup candidate. Direct-restore predecessor #209 is not mergeable as a product contract because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives; Draft #212 is the active successor and Issue #204 remains the end-to-end recovery authority. ## Current fitness matrix @@ -16,28 +16,28 @@ Protected main now also contains the bounded recovery-evidence primitives integr | --- | --- | --- | --- | | `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. The newly integrated recovery-evidence primitives are not yet a complete operator recovery procedure. | Keep beginner-readable; add shipped recovery semantics only when adjacent writer ownership permits and do not present evidence primitives as a restorable-backup guarantee. | | `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. Recovery evidence has advanced on protected main without establishing end-to-end recovery semantics. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file, and update recovery architecture only through a non-conflicting governed documentation lane. | -| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states and cites deterministic protected-main tenant/standalone acceptance authority. | Reflect the integrated recovery-evidence primitives while keeping executable backup/restore and end-to-end recovery PARTIAL/ACTIVE-PR; validate exact-head docs gates and integrate only through normal PR governance. | -| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, and release/testing invariants are explicit. | Add the bounded recovery-evidence technical boundary without promoting #208/#209; validate exact-head docs gates and integrate only through normal PR governance. | -| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. Add or amend an ADR only if the recovery execution/rollback architecture becomes a durable decision requiring one. | -| `docs/adr/README.md` | ACTIVE-PR | This canonical branch supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Keep the referenced protected-main tree current; do not invent a recovery ADR that is not integrated. | +| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states and cites deterministic protected-main tenant/standalone acceptance authority. | Reflect the integrated recovery-evidence primitives while keeping executable backup/restore and end-to-end recovery PARTIAL/ACTIVE-PR; treat #209 as an unsafe predecessor and #212 as the Draft direct-restore successor until protected integration. | +| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, and release/testing invariants are explicit. | Keep the bounded recovery-evidence technical boundary without promoting #208/#212; remove predecessor #209 from any implied merge path before canonical integration. | +| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. Draft #212 proposes ADR 0016 for custom-format restore seek semantics, but that record is not protected-main authority until integrated. | +| `docs/adr/README.md` | ACTIVE-PR | This canonical branch supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Keep the referenced protected-main tree current; do not list #212's proposed ADR 0016 as a protected-main decision before integration. | | `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | | `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Serves as the topic-specific operator authority for durable lifecycle tenancy. It already specifies trusted scope selection, pre-effect validation, four-argument standalone recorder compatibility, tenant-qualified identity/conflict/read behavior, forced RLS/application-role limits, migration, direct-SQL impact, rollback, recovery, and deterministic verification. | Keep synchronized with tenant/RLS and lifecycle migrations; do not duplicate this contract into a competing operator file. | | `docs/doctoring/tenant-scoped-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Supporting evidence independently records pre-effect validation, explicit standalone compatibility, database role/RLS limits, migration and rollback, plus current primary references. | Keep supporting references current; do not promote doctoring into the sole product authority. | | `CHANGELOG.md` tenant lifecycle entry | IMPLEMENTED-ON-PROTECTED-MAIN | The protected-main Unreleased section already records tenant-scoped durable lifecycle, forced default-deny RLS, standalone compatibility, and the atomic tenant migration fix. | Change only when integrated shipped behavior changes; do not log active-PR claims as shipped. | | Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | | PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py` are integrated protected-main primitives with focused tests. They produce bounded content-free metadata/hash/size evidence without executing SQL or claiming cluster parity. | Keep the evidence/guarantee distinction explicit. Do not claim restorable backup, isolated restore, PITR, RPO/RTO/HA/DR, or compliance readiness from these primitives alone. | -| PostgreSQL logical backup/restore execution | ACTIVE-PR | #208 proposes bounded `pg_dump` execution and #209 proposes bounded direct `pg_restore` execution. Neither is protected-main truth. #209 also introduces a direct-SQL/rollback contract that requires permanent operator/architecture/ADR/doctoring/CHANGELOG documentation once writer ownership is coordinated. | Do not race those source branches or adjacent documentation writers. Promote only after exact-head gates, valid findings, required documentation, qualifying approval, and protected-main integration. | +| PostgreSQL logical backup/restore execution | ACTIVE-PR | #208 proposes bounded `pg_dump` execution. #209's direct-restore predecessor has a verified false-failure defect because a seekable custom-format `pg_restore` need not leave the shared descriptor at EOF after successful transactional restore. Draft #212 is the active successor: it removes that invalid EOF postcondition while preserving metadata-fingerprint verification and owns the permanent README/architecture/ADR/doctoring/CHANGELOG restore-contract documentation. None is protected-main truth. | Freeze #209 rather than merge or patch it in parallel; do not race #208/#212 active writers. Promote only the unchanged successor after exact-head gates, valid findings, required documentation, qualifying approval, and protected-main integration. | | Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation for retiring legacy `http` / `pg_cron`; it is a different contract from the already-shipped tenant lifecycle migration and is not protected-main truth. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | | Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. It is not shipped until normal governance integrates it. | Preserve the trusted-search-path/non-ownership caveat and reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | -| Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and now distinguishes integrated recovery evidence from active executable recovery candidates. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs. | +| Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | | UML/component/sequence views | PLANNED | Root architecture is prose-first; no canonical UML authority is present. | Add textual Mermaid/PlantUML-compatible component and critical sequence diagrams after active source contracts stabilize. | | ERD / schema model | PLANNED | SQL and schema tests are authoritative, but no canonical ERD summarizes package-owned identities, tenancy, checkpoint state, and relationships. | Generate/maintain an ERD from protected-main schema; label migration-only/active-PR objects separately. | -| General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184 or #209 documentation surfaces. | +| General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184 or #212 documentation surfaces. | | Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | | Licensing / third-party notices | PARTIAL | Apache-2.0 source headers and repository licensing exist, but acquisition diligence should explicitly trace package license, dependency/SBOM evidence, and third-party notice process. | Evaluate a concise licensing/compliance evidence index without claiming legal certification. | @@ -53,7 +53,7 @@ Protected main now also contains the bounded recovery-evidence primitives integr - Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. - Content-fidelity invariants constrain any result-application path that exists, but they do not prove that end-to-end result application is shipped; FR-4 and `docs/TRACEABILITY.md` remain the capability-status authority while protected main is `PARTIAL`. - Bounded recovery receipts, artifact hashes, and packaged-schema hashes are evidence primitives, not proof that a backup is restorable or that a stated recovery objective is met. -- A future direct logical restore contract must keep caller-owned source trust, target isolation, allowed libpq environment, transaction rollback behavior, and post-restore acceptance explicit; those active-PR semantics are not shipped until integrated. +- A direct logical restore contract must keep caller-owned source trust, target isolation, allowed libpq environment, transaction rollback behavior, and post-restore acceptance explicit. Its archive-completion checks must match PostgreSQL custom-format random-access semantics: final descriptor offset is not proof of complete restore. #209 is therefore an unsafe predecessor, while #212 remains only an ACTIVE-PR successor until integrated. - Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. - Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. - Database object names, migration/rollback behavior, exact owned coverage requirements, Python-version acceptance, packaging/SBOM/provenance expectations, and bounded diagnostics must remain synchronized with repository tests and live governance. From eafbfa9b301dcd35fd49b0521abd250eb35e5815 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 00:15:46 +0900 Subject: [PATCH 29/58] docs(recovery): trace seek-safe restore successor --- docs/TRACEABILITY.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 36df331a9..1a67bb9c7 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -20,7 +20,7 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | | FR-5 bounded PostgreSQL recovery evidence primitives | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/postgres_recovery_receipt.py`, `pg_llm_batch/postgres_backup_evidence.py`, `pg_llm_batch/postgres_schema_evidence.py` | focused receipt/artifact/schema evidence tests; merged PRs #205, #206, #207 are historical integration evidence | Protected main can derive bounded content-free receipt, backup-artifact hash/size, and packaged-schema hash/size evidence. These primitives do not prove that a backup command ran successfully, that an artifact is restorable, that a live cluster matches packaged schema, or that PITR/RPO/RTO/HA/DR objectives are satisfied. | | FR-5 executable PostgreSQL logical backup | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #208 exact-head evidence only | The `pg_dump` execution candidate is not shipped. Its service selector is not tenant authorization, and current exact-head review/check evidence must be reacquired before integration. | -| FR-5 executable PostgreSQL logical restore | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #209 exact-head evidence only | The direct `pg_restore` candidate is not shipped. Its caller-owned source-superuser trust assertion, target-isolation responsibility, libpq allowlist, single-transaction failure boundary, and archive-integrity checks remain active-PR contracts until integration. | +| FR-5 executable PostgreSQL logical restore | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #212 exact-head evidence only; PR #209 is predecessor defect evidence | Draft #212 is the active direct-`pg_restore` successor. PR #209 must not merge because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after transactional restore has already succeeded. The successor's caller-owned source-superuser trust, target-isolation responsibility, libpq allowlist, single-transaction failure boundary, metadata-integrity checks, and permanent documentation remain unshipped until integration. | | FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded receipt/artifact/schema evidence primitives are integrated | Issue #204 acceptance authority plus protected-main recovery evidence tests | No protected-main end-to-end isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. PR #193 proposes an encryption-required default plus explicit local/development opt-out while also separating runtime construction from provisioning. | @@ -73,7 +73,8 @@ The following open pull requests are intentionally represented only as overlays - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. - **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening. It is Draft because the current `safe_value` guard accepts `str` subclasses via `isinstance`; the branch must first require an exact built-in `str` and pass a hostile-subclass regression. Protected main still discloses arbitrary rejected values by default, and the intended safe-default redaction/bounded `safe_value` contract remains ACTIVE-PR until integrated. - **#208** — bounded logical PostgreSQL backup executor candidate using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. -- **#209** — bounded direct logical PostgreSQL restore executor candidate using `pg_restore`; active source only and not evidence of isolated restore acceptance or end-to-end recovery readiness. +- **#209** — unsafe direct logical-restore predecessor. Its EOF-consumption postcondition is incompatible with seekable PostgreSQL custom archives and can produce a false post-commit failure. It must not merge in this state and is retained only as defect/history context while the successor is active. +- **#212** — Draft direct logical-restore successor. It replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying README/architecture/ADR/doctoring/CHANGELOG restore-contract documentation. It remains ACTIVE-PR and is not evidence of isolated restore acceptance or end-to-end recovery readiness. Merged recovery PRs #205, #206, and #207 are no longer active overlays; their bounded receipt, backup-artifact, and packaged-schema evidence primitives are present on the referenced protected-main tree. Their historical PR descriptions remain integration evidence, not durable runtime authority. From c27075a572595f7300022299091a65d7a1044867 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 15:21:55 +0000 Subject: [PATCH 30/58] docs(recovery): rebase restore overlay onto merged main Replay the #212 successor alignment onto 229f8d3 so the product and technical contracts no longer present #209 as the active pg_restore path or treat set_config as an enforcement control. Register #210 as the Fernet operator-contract overlay and freeze stale #213. Co-authored-by: Seongho Bae --- docs/DOCUMENTATION_FITNESS.md | 6 +++--- docs/TRACEABILITY.md | 4 +++- docs/product/PRD.md | 4 ++-- docs/product/TRD.md | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 2ef97bca1..f35c4272c 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -16,8 +16,8 @@ Protected main now also contains the bounded recovery-evidence primitives integr | --- | --- | --- | --- | | `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. The newly integrated recovery-evidence primitives are not yet a complete operator recovery procedure. | Keep beginner-readable; add shipped recovery semantics only when adjacent writer ownership permits and do not present evidence primitives as a restorable-backup guarantee. | | `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. Recovery evidence has advanced on protected main without establishing end-to-end recovery semantics. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file, and update recovery architecture only through a non-conflicting governed documentation lane. | -| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states and cites deterministic protected-main tenant/standalone acceptance authority. | Reflect the integrated recovery-evidence primitives while keeping executable backup/restore and end-to-end recovery PARTIAL/ACTIVE-PR; treat #209 as an unsafe predecessor and #212 as the Draft direct-restore successor until protected integration. | -| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, and release/testing invariants are explicit. | Keep the bounded recovery-evidence technical boundary without promoting #208/#212; remove predecessor #209 from any implied merge path before canonical integration. | +| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states, cites deterministic protected-main tenant/standalone acceptance authority, records the `set_config` capability/trust boundary, and treats Draft #212 as the restore successor while freezing predecessor #209. | Keep executable backup/restore and end-to-end recovery PARTIAL/ACTIVE-PR; refresh only after protected-main integration of #208 or #212. | +| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, #209/#212 restore overlay separation, and release/testing invariants are explicit. | Keep the bounded recovery-evidence technical boundary without promoting #208/#212; do not restore predecessor #209 to any implied merge path. | | ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. Draft #212 proposes ADR 0016 for custom-format restore seek semantics, but that record is not protected-main authority until integrated. | | `docs/adr/README.md` | ACTIVE-PR | This canonical branch supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Keep the referenced protected-main tree current; do not list #212's proposed ADR 0016 as a protected-main decision before integration. | | `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | @@ -31,7 +31,7 @@ Protected main now also contains the bounded recovery-evidence primitives integr | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | -| Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. It is not shipped until normal governance integrates it. | Preserve the trusted-search-path/non-ownership caveat and reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | +| Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. Draft #210 is the operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 1a67bb9c7..6720dcc39 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -68,8 +68,10 @@ The following open pull requests are intentionally represented only as overlays - **#184** — existing-volume legacy PostgreSQL extension retirement; migration/operator behavior remains active until merged. - **#190** — durable reconciliation candidate discovery; not protected-main truth and currently subject to live review/tooling evidence. - **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. -- **#192** — this canonical PRD/TRD/fitness/traceability reconstruction itself. +- **#192** — predecessor five-file canonical reconstruction. At `229f8d3` it still presents #209 as the active restore path and still reads as if arbitrary SQL cannot call `set_config`. Do not merge that head; this overlay is the current alignment. +- **#213** — stale overlay of #192 at `eafbfa9`. It predates the protected-main merge at `229f8d3` and must not land as a competing five-file rewrite. - **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. +- **#210** — Draft operator-contract successor to #193. It keeps the runtime fail-closed Fernet/provisioning seam and updates public install/README/architecture/CHANGELOG wording so first-run and embed paths match the code. Historical unencrypted-row migration, key rotation, and custody remain Issue #121 residuals and are not shipped. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. - **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening. It is Draft because the current `safe_value` guard accepts `str` subclasses via `isinstance`; the branch must first require an exact built-in `str` and pass a hostile-subclass regression. Protected main still discloses arbitrary rejected values by default, and the intended safe-default redaction/bounded `safe_value` contract remains ACTIVE-PR until integrated. - **#208** — bounded logical PostgreSQL backup executor candidate using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 47ef86feb..4454e0936 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -52,7 +52,7 @@ The product must let a qualified host: | Bounded PostgreSQL backup-artifact integrity evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from one private regular backup artifact under descriptor-pinned, no-follow, finite-work constraints without executing backup or restore. | | Bounded packaged PostgreSQL schema evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from the exact distributed `schema.sql` resource under a finite package-owned work budget without executing SQL or asserting live-cluster parity. | | PostgreSQL logical backup execution | ACTIVE-PR | A `pg_dump` candidate exists in #208 but is not shipped; protected main must not be described as creating a restorable backup from the evidence primitives alone. | -| PostgreSQL logical restore execution | ACTIVE-PR | A direct `pg_restore` candidate exists in #209 but is not shipped; its caller-owned source trust, target-isolation responsibility, libpq allowlist, transactional failure boundary, and archive-integrity contract remain active-PR semantics. | +| PostgreSQL logical restore execution | ACTIVE-PR | Draft #212 is the current direct `pg_restore` successor. Predecessor #209 must not merge: its EOF-consumption check can report failure after a seekable custom-format restore has already committed. Caller-owned source trust, target isolation, libpq allowlist, transactional failure, metadata-fingerprint integrity, and permanent documentation remain unshipped. | | End-to-end PostgreSQL recovery readiness | PARTIAL | Integrated evidence primitives do not yet prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative before it can become product truth. | | Cross-process reconciliation single-flight | ACTIVE-PR | Concurrent workers must not race the same tenant/provider identity; merge eligibility remains governed by live repository policy. | @@ -75,7 +75,7 @@ All provider operations shall use validated endpoint configuration and finite re The durable business identity is tenant-qualified where tenancy is enabled. `TenantDurableBatchAPIClient` shall validate its trusted host-selected `tenant_scope` synchronously at construction, before observation reservation, credential resolution, provider I/O, or lifecycle database I/O can occur. The tenant-qualified lifecycle key is `(tenant_scope, endpoint_alias, remote_batch_id)`; lifecycle persistence conflict targets, exact-row lookups, and operational status indexes shall retain `tenant_scope`, and package reads/writes shall bind that validated scope through parameterized transaction-local PostgreSQL context with forced row-level security for application roles. Provider/model content, endpoint aliases, remote identifiers, and transport data never select tenant authority. -The transaction-local `pg_llm_batch.tenant_scope` custom setting is routing context, not a credential or authenticated identity. Only package code acting on a trusted authenticated/authorized host selection may set it for tenant-owned operations; arbitrary SQL must not select or override tenant authority by calling `set_config`. PostgreSQL RLS is defense in depth and does not replace host authentication/authorization, SQL-injection prevention, or correct identity mapping. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access remain administrative escape hatches outside the tenant isolation guarantee. +The transaction-local `pg_llm_batch.tenant_scope` custom setting is routing context, not a credential or authenticated identity. Package code may set it only from a trusted authenticated/authorized host selection. A database role that can execute arbitrary SQL can still call `set_config` with an arbitrary tenant scope; the trusted application boundary must prevent generic tenant-controlled SQL, SQL injection, and incorrect identity mapping from selecting tenant authority. PostgreSQL RLS is defense in depth and does not replace those controls. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access remain administrative escape hatches outside the tenant isolation guarantee. The deployment credential provider remains a separate host/configuration authority: validating tenant scope before credential resolution does not make credentials tenant-keyed and does not authorize a tenant to select secrets. diff --git a/docs/product/TRD.md b/docs/product/TRD.md index 3449661f1..f95977ab8 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -92,7 +92,7 @@ Protected main supplies three deliberately non-executing recovery-evidence primi These primitives do not execute SQL or database mutation. They do not prove the backup command succeeded, prove backup provenance beyond caller-controlled receipt fields, prove restorability, prove a live database matches the packaged schema, provide target isolation, manage keys/secrets, manage physical/WAL/PITR infrastructure, or establish RPO/RTO/HA/DR/compliance. Those are separate acceptance domains. -Logical `pg_dump` execution in #208 and direct `pg_restore` execution in #209 remain **ACTIVE-PR**. Until integration, no protected-main technical contract may rely on those executors. The direct-restore candidate additionally requires permanent operator/architecture/ADR/doctoring/CHANGELOG coverage for caller-owned source-superuser trust, the non-authorizing service selector, permitted inherited libpq variables, single-transaction rollback behavior, target isolation, and post-restore acceptance before it may be represented as shipped. +Logical `pg_dump` execution in #208 remains **ACTIVE-PR**. Direct `pg_restore` execution is also **ACTIVE-PR**, but only Draft #212 is the current successor. Predecessor #209 is not a merge path: its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after `--single-transaction` has already committed. Until integration, no protected-main technical contract may rely on those executors. The #212 successor additionally requires permanent operator/architecture/ADR/doctoring/CHANGELOG coverage for caller-owned source-superuser trust, the non-authorizing service selector, permitted inherited libpq variables, single-transaction rollback behavior, target isolation, metadata-fingerprint verification, and post-restore acceptance before it may be represented as shipped. ## Persistence requirements From 85949a2243d79135c0a2ee4722b4c94fb96662bd Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 15:22:46 +0000 Subject: [PATCH 31/58] docs(recovery): name overlay #214 in the register Record the rebased successor as the current five-file alignment so operators do not land #192 or stale #213. Co-authored-by: Seongho Bae --- docs/TRACEABILITY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 6720dcc39..931230cad 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -68,8 +68,9 @@ The following open pull requests are intentionally represented only as overlays - **#184** — existing-volume legacy PostgreSQL extension retirement; migration/operator behavior remains active until merged. - **#190** — durable reconciliation candidate discovery; not protected-main truth and currently subject to live review/tooling evidence. - **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. -- **#192** — predecessor five-file canonical reconstruction. At `229f8d3` it still presents #209 as the active restore path and still reads as if arbitrary SQL cannot call `set_config`. Do not merge that head; this overlay is the current alignment. +- **#192** — predecessor five-file canonical reconstruction. At `229f8d3` it still presents #209 as the active restore path and still reads as if arbitrary SQL cannot call `set_config`. Do not merge that head; #214 is the current alignment. - **#213** — stale overlay of #192 at `eafbfa9`. It predates the protected-main merge at `229f8d3` and must not land as a competing five-file rewrite. +- **#214** — this overlay. It rebases the #212 successor alignment and the `set_config` capability wording onto `229f8d3` and is not shipped truth until protected-main integration. - **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. - **#210** — Draft operator-contract successor to #193. It keeps the runtime fail-closed Fernet/provisioning seam and updates public install/README/architecture/CHANGELOG wording so first-run and embed paths match the code. Historical unencrypted-row migration, key rotation, and custody remain Issue #121 residuals and are not shipped. - **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. From 8227e820e62edc502f7b050fb72d0a638d30d135 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 17 Aug 2026 01:45:02 +0900 Subject: [PATCH 32/58] docs: refresh canonical active-overlay truth --- docs/TRACEABILITY.md | 48 +++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 931230cad..e0bfc356b 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -20,13 +20,17 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | | FR-5 bounded PostgreSQL recovery evidence primitives | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/postgres_recovery_receipt.py`, `pg_llm_batch/postgres_backup_evidence.py`, `pg_llm_batch/postgres_schema_evidence.py` | focused receipt/artifact/schema evidence tests; merged PRs #205, #206, #207 are historical integration evidence | Protected main can derive bounded content-free receipt, backup-artifact hash/size, and packaged-schema hash/size evidence. These primitives do not prove that a backup command ran successfully, that an artifact is restorable, that a live cluster matches packaged schema, or that PITR/RPO/RTO/HA/DR objectives are satisfied. | | FR-5 executable PostgreSQL logical backup | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #208 exact-head evidence only | The `pg_dump` execution candidate is not shipped. Its service selector is not tenant authorization, and current exact-head review/check evidence must be reacquired before integration. | -| FR-5 executable PostgreSQL logical restore | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #212 exact-head evidence only; PR #209 is predecessor defect evidence | Draft #212 is the active direct-`pg_restore` successor. PR #209 must not merge because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after transactional restore has already succeeded. The successor's caller-owned source-superuser trust, target-isolation responsibility, libpq allowlist, single-transaction failure boundary, metadata-integrity checks, and permanent documentation remain unshipped until integration. | -| FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded receipt/artifact/schema evidence primitives are integrated | Issue #204 acceptance authority plus protected-main recovery evidence tests | No protected-main end-to-end isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | +| FR-5 executable PostgreSQL logical restore | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #212 exact-head evidence only; closed #209 is predecessor defect evidence | #212 is the active direct-`pg_restore` successor. Closed predecessor #209 remains historical defect evidence because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after transactional restore has already succeeded. The successor's caller-owned source-superuser trust, target-isolation responsibility, libpq allowlist, single-transaction failure boundary, metadata-integrity checks, and permanent documentation remain unshipped until integration. | +| FR-5 recovery evidence binding and live re-verification | ACTIVE-PR | protected main exposes the underlying receipt/schema/artifact evidence primitives only | PRs #215 and #221 exact-head evidence only | Bind-time composition and later re-inspection are active candidate seams, not inspection provenance or restore proof on protected main. A verifier success is integrity agreement at the inspection instant and does not remove TOCTOU or target-isolation requirements. | +| FR-5 post-restore catalog acceptance | ACTIVE-PR | protected-main schema and recovery evidence only | PR #223 exact-head catalog/unit/container evidence only; closed #216 is predecessor evidence | Catalog acceptance remains unshipped. Same-name index decoys, tenant-qualified key order, uniqueness/constraint authority, access method, readiness/validity, and live PostgreSQL query behavior must remain fail-closed before this can become protected-main truth. | +| FR-5 physical/WAL/PITR recovery profile | ACTIVE-PR | none on protected main beyond bounded recovery evidence | PR #219 exact-head evidence only | The profile records caller-owned recovery intent and objectives; it does not execute `pg_basebackup`, archive/replay WAL, prove an isolated target, or establish package RPO/RTO capability. | +| FR-5 restore-target isolation | PARTIAL | no protected-main target-isolation proof exists | active recovery acceptance work, including PR #224, is PR evidence only | Distinct configuration labels alone are insufficient to prove two service aliases resolve to different clusters. End-to-end acceptance must authenticate the actual restore target before production safety can be claimed. | +| FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded receipt/artifact/schema evidence primitives are integrated | Issue #204 acceptance authority plus protected-main recovery evidence tests | Active logical execution, evidence binding/reinspection, catalog acceptance, physical/PITR profiling, and target-isolation slices remain unshipped. No protected-main isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | -| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. PR #193 proposes an encryption-required default plus explicit local/development opt-out while also separating runtime construction from provisioning. | -| FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes the selected deployment policy through redacted readiness/operator evidence. PR #193 addresses the default-policy boundary only while it remains ACTIVE-PR. | +| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. #210 is the active operator/runtime-contract successor to the closed #193 line; neither its stricter policy nor provisioning/runtime separation is protected-main truth until integration. | +| FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes selected deployment policy through redacted readiness/operator evidence. #210 remains an ACTIVE-PR candidate rather than shipped policy. | | FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic validation rejected-value confidentiality is not protected-main truth; PR #202 is the ACTIVE-PR compatibility-aware repair and must not be inferred as shipped before integration. | -| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 candidate privacy/compatibility tests and review evidence only | PR #202 is Draft because its current `safe_value` guard accepts `str` subclasses via `isinstance`, which can execute caller-controlled special methods while validation or rendering handles supposedly safe evidence. The candidate must require an exact built-in `str` and prove a hostile-subclass regression before it can become Ready; the intended fixed-redaction default and bounded `safe_value` opt-in remain unshipped. | +| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 candidate privacy/compatibility tests and review evidence only | PR #202 remains Draft with a hostile-type boundary defect on its current lane; intended safe-default redaction/bounded `safe_value` behavior remains unshipped until the exact current source and governance evidence are repaired and integrated. | | FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | | Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | @@ -43,10 +47,10 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | RLS defense in depth | tenant-qualified schema and transaction-local scope binding | live PostgreSQL isolation/migration tests | Superuser/BYPASSRLS/arbitrary SQL are administrative bypasses. | | Provider destination validation | `batch_api_client.py` | endpoint/URL tests | Host/network infrastructure TLS policy is external. | | Bounded provider input | provider client + result streaming | response/download/JSONL/resource-budget tests | Provider authenticity is not established by payload validation. | -| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Protected main supports Fernet but does not require it by default; the compatibility path is not a production confidentiality claim. PR #193's stricter default is ACTIVE-PR, while enterprise secret-manager choice remains host-owned. | +| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Protected main supports Fernet but does not require it by default; compatibility mode is not a production confidentiality claim. #210 is ACTIVE-PR, while enterprise secret-manager choice and key custody remain host-owned. | | Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic `ValidationError` rejected-value confidentiality remains incomplete on protected main; PR #202 is ACTIVE-PR and its evidence does not transfer until merge. | | Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | -| Recovery evidence confidentiality/integrity | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | recovery receipt/artifact/schema evidence regressions | Evidence is bounded and content-free but does not authenticate an operator, prove backup provenance beyond caller-supplied receipt inputs, or prove restore semantics. | +| Recovery evidence confidentiality/integrity | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | recovery receipt/artifact/schema evidence regressions | Evidence is bounded and content-free but does not authenticate an operator, prove live inspection provenance beyond the integrated primitives, prove target isolation, or prove restore semantics. | | Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability are operational dependencies. | ## Data and persistence traceability @@ -62,24 +66,26 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. ## Active overlay register -The following open pull requests are intentionally represented only as overlays on this traceability map: +The following open pull requests are represented only as overlays. Their existence does not make their behavior protected-main truth, and this register intentionally avoids volatile Draft/Ready/check-state labels: - **#175** — OpenTelemetry packaging extra; dependency-lock/materialization and final package evidence remain outside protected-main truth. - **#184** — existing-volume legacy PostgreSQL extension retirement; migration/operator behavior remains active until merged. -- **#190** — durable reconciliation candidate discovery; not protected-main truth and currently subject to live review/tooling evidence. +- **#190** — durable reconciliation candidate discovery; not protected-main truth and subject to live review/tooling evidence. - **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. -- **#192** — predecessor five-file canonical reconstruction. At `229f8d3` it still presents #209 as the active restore path and still reads as if arbitrary SQL cannot call `set_config`. Do not merge that head; #214 is the current alignment. -- **#213** — stale overlay of #192 at `eafbfa9`. It predates the protected-main merge at `229f8d3` and must not land as a competing five-file rewrite. -- **#214** — this overlay. It rebases the #212 successor alignment and the `set_config` capability wording onto `229f8d3` and is not shipped truth until protected-main integration. -- **#193** — runtime-store/schema-provisioning separation plus an encryption-required `SecretStore` default with explicit local/development compatibility opt-out; both remain active overlays, and this PR does not by itself establish legacy-row migration, key rotation/recovery, or readiness-policy lifecycle completion. -- **#210** — Draft operator-contract successor to #193. It keeps the runtime fail-closed Fernet/provisioning seam and updates public install/README/architecture/CHANGELOG wording so first-run and embed paths match the code. Historical unencrypted-row migration, key rotation, and custody remain Issue #121 residuals and are not shipped. -- **#194** — atomic local result-effect/checkpoint application; a current-main-compatible implementation is under review but remains an active overlay and is not shipped. -- **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening. It is Draft because the current `safe_value` guard accepts `str` subclasses via `isinstance`; the branch must first require an exact built-in `str` and pass a hostile-subclass regression. Protected main still discloses arbitrary rejected values by default, and the intended safe-default redaction/bounded `safe_value` contract remains ACTIVE-PR until integrated. -- **#208** — bounded logical PostgreSQL backup executor candidate using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. -- **#209** — unsafe direct logical-restore predecessor. Its EOF-consumption postcondition is incompatible with seekable PostgreSQL custom archives and can produce a false post-commit failure. It must not merge in this state and is retained only as defect/history context while the successor is active. -- **#212** — Draft direct logical-restore successor. It replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying README/architecture/ADR/doctoring/CHANGELOG restore-contract documentation. It remains ACTIVE-PR and is not evidence of isolated restore acceptance or end-to-end recovery readiness. - -Merged recovery PRs #205, #206, and #207 are no longer active overlays; their bounded receipt, backup-artifact, and packaged-schema evidence primitives are present on the referenced protected-main tree. Their historical PR descriptions remain integration evidence, not durable runtime authority. +- **#194** — atomic local result-effect/checkpoint application; same-transaction behavior remains an active overlay and is not shipped. +- **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening; current candidate evidence does not transfer into shipped behavior. +- **#208** — bounded logical PostgreSQL backup executor using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. +- **#210** — configuration/secrets operator/runtime contract successor; encryption-required policy, least-privilege runtime readiness, and provisioning separation remain unshipped until this lane is repaired and integrated. +- **#212** — direct logical-restore successor to closed #209; it replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying restore-contract documentation. It is not evidence of isolated restore acceptance or end-to-end recovery readiness. +- **#214** — this five-file canonical overlay; protected-main status does not change until this documentation lane integrates. +- **#215** — recovery receipt evidence-binding candidate; exact-type evidence objects must not be mistaken for inspection provenance, and the active lane remains unshipped until repaired and accepted. +- **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives only and does not execute recovery or claim achieved RPO/RTO. +- **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. +- **#222** — read-only exact-SHA workflow-registry audit candidate; governance tooling remains an overlay until normal integration, and ADR identity must remain collision-free across concurrent writers. +- **#223** — live PostgreSQL restore-catalog acceptance successor to closed #216; catalog/index-semantic acceptance remains unshipped. +- **#224** — restore-target isolation candidate. A safe final contract must distinguish configuration-label separation from authenticated target/cluster separation; neither is protected-main truth today. + +Closed or superseded predecessors such as #192, #193, #209, #211, #213, and #216 remain historical evidence only. Merged recovery PRs #205, #206, and #207 are no longer active overlays; their bounded receipt, backup-artifact, and packaged-schema evidence primitives are present on the referenced protected-main tree. This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. From c76ca2988755e5fe7d7b6c02f1a5a8b899c63fad Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 16:51:36 +0000 Subject: [PATCH 33/58] docs(recovery): drop transient Draft labels from canonical status Keep #209 as the unsafe predecessor and #212 as the unshipped active successor without freezing Draft/Ready pull-request state. Name the adjacent recovery families and add a regression that rejects those labels in durable product documents. Co-authored-by: Seongho Bae --- docs/DOCUMENTATION_FITNESS.md | 14 +++-- docs/TRACEABILITY.md | 5 +- docs/product/PRD.md | 7 ++- docs/product/TRD.md | 4 +- tests/test_canonical_status_vocabulary.py | 72 +++++++++++++++++++++++ 5 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 tests/test_canonical_status_vocabulary.py diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index f35c4272c..a9939bda0 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -8,7 +8,7 @@ A document is *fit* only when it states the correct authority boundary, is consi The tenant lifecycle material in this canonical cohort is a reconstruction of already integrated protected-main behavior, not a new runtime tenant/RLS/migration contract. Companion-document verification against protected main confirms the same contract is already present in the public `README.md`, root `ARCHITECTURE.md`, topic operator guide `docs/remote-batch-lifecycle.md`, accepted ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md`. Those authorities already cover trusted tenant identity, `NOSUPERUSER NOBYPASSRLS`, transaction-local/forced RLS, direct-SQL limits, legacy-to-`standalone` migration, and rollback constraints. The canonical PRD/TRD therefore may cite that existing evidence without rewriting those protected-main files or racing PR #184's separate legacy-extension-retirement documentation lane. -Protected main now also contains the bounded recovery-evidence primitives integrated by #205, #206, and #207: content-free PostgreSQL recovery receipts, descriptor-pinned backup-artifact hash/size evidence, and packaged-schema hash/size evidence. These are evidence primitives only. They do not make executable logical backup/restore, isolated restore acceptance, WAL/PITR, key/config custody, or any RPO/RTO/HA/DR objective shipped. #208 remains the active logical-backup candidate. Direct-restore predecessor #209 is not mergeable as a product contract because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives; Draft #212 is the active successor and Issue #204 remains the end-to-end recovery authority. +Protected main now also contains the bounded recovery-evidence primitives integrated by #205, #206, and #207: content-free PostgreSQL recovery receipts, descriptor-pinned backup-artifact hash/size evidence, and packaged-schema hash/size evidence. These are evidence primitives only. They do not make executable logical backup/restore, isolated restore acceptance, WAL/PITR, key/config custody, or any RPO/RTO/HA/DR objective shipped. #208 remains the active logical-backup candidate. Direct-restore predecessor #209 is not mergeable as a product contract because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives; #212 is the unshipped active successor. Adjacent unshipped recovery families are evidence binding, live receipt re-inspection, post-restore catalog acceptance, a caller-owned physical/WAL/PITR profile, and restore-target isolation. Issue #204 remains the end-to-end recovery authority. ## Current fitness matrix @@ -16,9 +16,9 @@ Protected main now also contains the bounded recovery-evidence primitives integr | --- | --- | --- | --- | | `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. The newly integrated recovery-evidence primitives are not yet a complete operator recovery procedure. | Keep beginner-readable; add shipped recovery semantics only when adjacent writer ownership permits and do not present evidence primitives as a restorable-backup guarantee. | | `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. Recovery evidence has advanced on protected main without establishing end-to-end recovery semantics. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file, and update recovery architecture only through a non-conflicting governed documentation lane. | -| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states, cites deterministic protected-main tenant/standalone acceptance authority, records the `set_config` capability/trust boundary, and treats Draft #212 as the restore successor while freezing predecessor #209. | Keep executable backup/restore and end-to-end recovery PARTIAL/ACTIVE-PR; refresh only after protected-main integration of #208 or #212. | +| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states, cites deterministic protected-main tenant/standalone acceptance authority, records the `set_config` capability/trust boundary, and treats #212 as the unshipped active restore successor while freezing predecessor #209. | Keep executable backup/restore, evidence binding, catalog acceptance, physical/PITR profiling, restore-target isolation, and end-to-end recovery PARTIAL/ACTIVE-PR; refresh only after protected-main integration. | | `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, #209/#212 restore overlay separation, and release/testing invariants are explicit. | Keep the bounded recovery-evidence technical boundary without promoting #208/#212; do not restore predecessor #209 to any implied merge path. | -| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. Draft #212 proposes ADR 0016 for custom-format restore seek semantics, but that record is not protected-main authority until integrated. | +| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. #212 proposes ADR 0016 for custom-format restore seek semantics, but that record is not protected-main authority until integrated. | | `docs/adr/README.md` | ACTIVE-PR | This canonical branch supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Keep the referenced protected-main tree current; do not list #212's proposed ADR 0016 as a protected-main decision before integration. | | `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | | `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Serves as the topic-specific operator authority for durable lifecycle tenancy. It already specifies trusted scope selection, pre-effect validation, four-argument standalone recorder compatibility, tenant-qualified identity/conflict/read behavior, forced RLS/application-role limits, migration, direct-SQL impact, rollback, recovery, and deterministic verification. | Keep synchronized with tenant/RLS and lifecycle migrations; do not duplicate this contract into a competing operator file. | @@ -26,12 +26,16 @@ Protected main now also contains the bounded recovery-evidence primitives integr | `CHANGELOG.md` tenant lifecycle entry | IMPLEMENTED-ON-PROTECTED-MAIN | The protected-main Unreleased section already records tenant-scoped durable lifecycle, forced default-deny RLS, standalone compatibility, and the atomic tenant migration fix. | Change only when integrated shipped behavior changes; do not log active-PR claims as shipped. | | Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | | PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py` are integrated protected-main primitives with focused tests. They produce bounded content-free metadata/hash/size evidence without executing SQL or claiming cluster parity. | Keep the evidence/guarantee distinction explicit. Do not claim restorable backup, isolated restore, PITR, RPO/RTO/HA/DR, or compliance readiness from these primitives alone. | -| PostgreSQL logical backup/restore execution | ACTIVE-PR | #208 proposes bounded `pg_dump` execution. #209's direct-restore predecessor has a verified false-failure defect because a seekable custom-format `pg_restore` need not leave the shared descriptor at EOF after successful transactional restore. Draft #212 is the active successor: it removes that invalid EOF postcondition while preserving metadata-fingerprint verification and owns the permanent README/architecture/ADR/doctoring/CHANGELOG restore-contract documentation. None is protected-main truth. | Freeze #209 rather than merge or patch it in parallel; do not race #208/#212 active writers. Promote only the unchanged successor after exact-head gates, valid findings, required documentation, qualifying approval, and protected-main integration. | +| PostgreSQL logical backup/restore execution | ACTIVE-PR | #208 proposes bounded `pg_dump` execution. #209's direct-restore predecessor has a verified false-failure defect because a seekable custom-format `pg_restore` need not leave the shared descriptor at EOF after successful transactional restore. #212 is the unshipped active successor: it removes that invalid EOF postcondition while preserving metadata-fingerprint verification and owns the permanent README/architecture/ADR/doctoring/CHANGELOG restore-contract documentation. None is protected-main truth. | Freeze #209 rather than merge or patch it in parallel; do not race #208/#212 active writers. Promote only the unchanged successor after exact-head gates, valid findings, required documentation, qualifying approval, and protected-main integration. | +| Recovery evidence binding and live re-inspection | ACTIVE-PR | Adjacent overlays compose receipts from exact inspected evidence and later re-hash current bytes. Agreement is integrity at one inspection instant, not provenance, restorability, or target isolation. | Keep bind/re-inspect seams unshipped until exact-head gates and qualifying approval land; do not treat object construction as live inspection. | +| Post-restore catalog acceptance | ACTIVE-PR | Catalog acceptance must prove live PostgreSQL query behavior against same-name index decoys, tenant-qualified key order, uniqueness/constraint authority, and access method. | Do not promote catalog greps of SQL text into shipped acceptance. | +| Physical/WAL/PITR recovery profile | ACTIVE-PR | A caller-owned profile records physical recovery intent and objectives. It does not execute `pg_basebackup` or WAL replay. | Keep RPO/RTO language as caller-owned intent, not a package capability. | +| Restore-target isolation | PARTIAL | Distinct libpq service names are a configuration-label check. They do not authenticate that two aliases resolve to different clusters. | Require authenticated target proof before claiming production restore safety. | | Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation for retiring legacy `http` / `pg_cron`; it is a different contract from the already-shipped tenant lifecycle migration and is not protected-main truth. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | | OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | -| Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. Draft #210 is the operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | +| Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. #210 is the unshipped operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | | Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index e0bfc356b..5093d3edc 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -30,7 +30,7 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. #210 is the active operator/runtime-contract successor to the closed #193 line; neither its stricter policy nor provisioning/runtime separation is protected-main truth until integration. | | FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes selected deployment policy through redacted readiness/operator evidence. #210 remains an ACTIVE-PR candidate rather than shipped policy. | | FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic validation rejected-value confidentiality is not protected-main truth; PR #202 is the ACTIVE-PR compatibility-aware repair and must not be inferred as shipped before integration. | -| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 candidate privacy/compatibility tests and review evidence only | PR #202 remains Draft with a hostile-type boundary defect on its current lane; intended safe-default redaction/bounded `safe_value` behavior remains unshipped until the exact current source and governance evidence are repaired and integrated. | +| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 candidate privacy/compatibility tests and review evidence only | PR #202 remains an ACTIVE-PR candidate with a hostile-type boundary defect on its current lane; intended safe-default redaction/bounded `safe_value` behavior remains unshipped until the exact current source and governance evidence are repaired and integrated. | | FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | | Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | @@ -83,7 +83,8 @@ The following open pull requests are represented only as overlays. Their existen - **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. - **#222** — read-only exact-SHA workflow-registry audit candidate; governance tooling remains an overlay until normal integration, and ADR identity must remain collision-free across concurrent writers. - **#223** — live PostgreSQL restore-catalog acceptance successor to closed #216; catalog/index-semantic acceptance remains unshipped. -- **#224** — restore-target isolation candidate. A safe final contract must distinguish configuration-label separation from authenticated target/cluster separation; neither is protected-main truth today. +- **#224** — restore-target isolation predecessor that files ADR 0021; that number collides with the workflow-registry audit lane, so this head is not the landing vehicle. +- **#225** — collision-free restore-target isolation successor using ADR 0022. Distinct libpq service names are a configuration-label check only; they are not authenticated cluster isolation or a restore executor. Closed or superseded predecessors such as #192, #193, #209, #211, #213, and #216 remain historical evidence only. Merged recovery PRs #205, #206, and #207 are no longer active overlays; their bounded receipt, backup-artifact, and packaged-schema evidence primitives are present on the referenced protected-main tree. diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 4454e0936..458f01688 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -52,7 +52,12 @@ The product must let a qualified host: | Bounded PostgreSQL backup-artifact integrity evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from one private regular backup artifact under descriptor-pinned, no-follow, finite-work constraints without executing backup or restore. | | Bounded packaged PostgreSQL schema evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from the exact distributed `schema.sql` resource under a finite package-owned work budget without executing SQL or asserting live-cluster parity. | | PostgreSQL logical backup execution | ACTIVE-PR | A `pg_dump` candidate exists in #208 but is not shipped; protected main must not be described as creating a restorable backup from the evidence primitives alone. | -| PostgreSQL logical restore execution | ACTIVE-PR | Draft #212 is the current direct `pg_restore` successor. Predecessor #209 must not merge: its EOF-consumption check can report failure after a seekable custom-format restore has already committed. Caller-owned source trust, target isolation, libpq allowlist, transactional failure, metadata-fingerprint integrity, and permanent documentation remain unshipped. | +| PostgreSQL logical restore execution | ACTIVE-PR | #212 is the unshipped active direct `pg_restore` successor. Predecessor #209 must not merge: its EOF-consumption check can report failure after a seekable custom-format restore has already committed. Caller-owned source trust, target isolation, libpq allowlist, transactional failure, metadata-fingerprint integrity, and permanent documentation remain unshipped. | +| Recovery evidence binding | ACTIVE-PR | A host can compose one receipt from exact inspected schema and backup-artifact evidence objects. Bind-time composition is not inspection provenance, restorability, or target isolation. | +| Live receipt re-inspection | ACTIVE-PR | A later verifier can re-hash current bytes and compare them to a stored receipt. Agreement is valid only at that inspection instant and does not remove TOCTOU or prove restore success. | +| Post-restore catalog acceptance | ACTIVE-PR | Isolated restore acceptance must fail closed on same-name catalog decoys, tenant-qualified key order, uniqueness/constraint authority, access method, and live PostgreSQL query behavior. | +| Physical/WAL/PITR recovery profile | ACTIVE-PR | A caller-owned physical recovery profile records intent and objectives only. It does not execute `pg_basebackup`, archive or replay WAL, or establish a package RPO/RTO. | +| Restore-target isolation | PARTIAL | Distinct configuration labels are not authenticated cluster isolation. End-to-end acceptance must prove the restore target is a different cluster before production safety can be claimed. | | End-to-end PostgreSQL recovery readiness | PARTIAL | Integrated evidence primitives do not yet prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative before it can become product truth. | | Cross-process reconciliation single-flight | ACTIVE-PR | Concurrent workers must not race the same tenant/provider identity; merge eligibility remains governed by live repository policy. | diff --git a/docs/product/TRD.md b/docs/product/TRD.md index f95977ab8..8b82746fa 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -92,7 +92,9 @@ Protected main supplies three deliberately non-executing recovery-evidence primi These primitives do not execute SQL or database mutation. They do not prove the backup command succeeded, prove backup provenance beyond caller-controlled receipt fields, prove restorability, prove a live database matches the packaged schema, provide target isolation, manage keys/secrets, manage physical/WAL/PITR infrastructure, or establish RPO/RTO/HA/DR/compliance. Those are separate acceptance domains. -Logical `pg_dump` execution in #208 remains **ACTIVE-PR**. Direct `pg_restore` execution is also **ACTIVE-PR**, but only Draft #212 is the current successor. Predecessor #209 is not a merge path: its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after `--single-transaction` has already committed. Until integration, no protected-main technical contract may rely on those executors. The #212 successor additionally requires permanent operator/architecture/ADR/doctoring/CHANGELOG coverage for caller-owned source-superuser trust, the non-authorizing service selector, permitted inherited libpq variables, single-transaction rollback behavior, target isolation, metadata-fingerprint verification, and post-restore acceptance before it may be represented as shipped. +Logical `pg_dump` execution in #208 remains **ACTIVE-PR**. Direct `pg_restore` execution is also **ACTIVE-PR**, and #212 is the unshipped active successor. Predecessor #209 is not a merge path: its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after `--single-transaction` has already committed. Until integration, no protected-main technical contract may rely on those executors. The #212 successor additionally requires permanent operator/architecture/ADR/doctoring/CHANGELOG coverage for caller-owned source-superuser trust, the non-authorizing service selector, permitted inherited libpq variables, single-transaction rollback behavior, target isolation, metadata-fingerprint verification, and post-restore acceptance before it may be represented as shipped. + +Active recovery work also includes evidence binding, live receipt re-inspection, post-restore catalog acceptance, a caller-owned physical/WAL/PITR profile, and restore-target isolation. Those are capability families, not shipped executors. Distinct service-name labels are not authenticated cluster isolation. ## Persistence requirements diff --git a/tests/test_canonical_status_vocabulary.py b/tests/test_canonical_status_vocabulary.py new file mode 100644 index 000000000..ea39dbd0d --- /dev/null +++ b/tests/test_canonical_status_vocabulary.py @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: Apache-2.0 +"""Canonical product documents must not persist transient pull-request state.""" + +from __future__ import annotations + +import re +from pathlib import Path + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +CANONICAL_STATUS_DOCUMENTS = ( + REPOSITORY_ROOT / "docs" / "product" / "PRD.md", + REPOSITORY_ROOT / "docs" / "product" / "TRD.md", + REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md", + REPOSITORY_ROOT / "docs" / "TRACEABILITY.md", + REPOSITORY_ROOT / "docs" / "adr" / "README.md", +) +_TRANSIENT_PR_STATE = re.compile( + r"(?i)\b(?:draft|ready)\s+#\d+\b|\bpr\s+#\d+\s+remains\s+draft\b" +) +_EXACT_HEAD_SHA = re.compile(r"\b[0-9a-f]{40}\b") +_PROTECTED_MAIN_REFERENCE_TREE = "d2f1e32271910a6db98a0757d67194ddadca4566" + + +def _read(path: Path) -> str: + """Return one canonical Markdown document as UTF-8 text.""" + return path.read_text(encoding="utf-8") + + +def test_canonical_status_documents_omit_transient_pr_ready_or_draft_labels() -> None: + """Durable product/status prose must not freeze Draft/Ready pull-request labels.""" + for path in CANONICAL_STATUS_DOCUMENTS: + matches = _TRANSIENT_PR_STATE.findall(_read(path)) + assert matches == [], f"{path.name} persists transient PR state: {matches}" + + +def test_canonical_status_documents_do_not_embed_exact_contributor_heads() -> None: + """Exact SHAs belong in review evidence, not durable product-status prose.""" + for path in CANONICAL_STATUS_DOCUMENTS: + text = _read(path) + leftover = [ + match + for match in _EXACT_HEAD_SHA.findall(text) + if match != _PROTECTED_MAIN_REFERENCE_TREE + ] + assert leftover == [], f"{path.name} embeds exact heads: {leftover}" + + +def test_product_contract_names_restore_successor_without_draft_label() -> None: + """#209 is the unsafe predecessor; #212 is the unshipped active successor.""" + prd = _read(REPOSITORY_ROOT / "docs" / "product" / "PRD.md") + trd = _read(REPOSITORY_ROOT / "docs" / "product" / "TRD.md") + fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") + + for document in (prd, trd, fitness): + assert "Draft #212" not in document + assert "#212" in document + assert "#209" in document + assert "EOF-consumption" in document or "EOF" in document + + +def test_product_contract_names_active_recovery_capability_families() -> None: + """The recovery graph is more than logical dump/restore execution.""" + prd = _read(REPOSITORY_ROOT / "docs" / "product" / "PRD.md") + fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") + + for document in (prd, fitness, traceability): + assert "evidence binding" in document.lower() or "receipt" in document.lower() + assert "catalog" in document.lower() + assert "pitr" in document.lower() + assert "target isolation" in document.lower() or "restore-target" in document.lower() From ad39b4d4f0ff03fa8dfe600bc4534a866551d672 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 16:53:34 +0000 Subject: [PATCH 34/58] docs: add threat model and package-owned schema ERD Close the acquisition-facing documentation gaps that left assets, trust boundaries, and table identities only in SQL and scattered security prose. Cite NIST SP 800-30, 800-53, and 800-154 without claiming certification. Co-authored-by: Seongho Bae --- docs/DOCUMENTATION_FITNESS.md | 4 +- docs/THREAT_MODEL.md | 106 +++++++++++++++ docs/TRACEABILITY.md | 3 +- docs/erd/package-owned-schema.md | 159 +++++++++++++++++++++++ tests/test_schema_erd_documentation.py | 68 ++++++++++ tests/test_threat_model_documentation.py | 53 ++++++++ 6 files changed, 390 insertions(+), 3 deletions(-) create mode 100644 docs/THREAT_MODEL.md create mode 100644 docs/erd/package-owned-schema.md create mode 100644 tests/test_schema_erd_documentation.py create mode 100644 tests/test_threat_model_documentation.py diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index a9939bda0..8bc1a2470 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -37,10 +37,10 @@ Protected main now also contains the bounded recovery-evidence primitives integr | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | | Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. #210 is the unshipped operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | -| Threat model | PLANNED | No canonical protected-main `docs/THREAT_MODEL.md` is present. Security rules are distributed across AGENTS, architecture, ADRs, tests, and issue/PR evidence. | Add a threat model that distinguishes assets, trust boundaries, attacker capabilities, mitigations, residual risk, and non-guarantees without certification claims. | +| Threat model | ACTIVE-PR | This overlay adds `docs/THREAT_MODEL.md` with assets, trust boundaries, attacker preconditions, package mitigations, residual risk, operator next actions, and APA 7th NIST citations. It is not protected-main truth until this documentation lane integrates, and it does not claim SOC 2/CSAP certification. | Promote only after exact-head gates and merge; keep residual-risk language if a later executor or worker lands. | | Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | | UML/component/sequence views | PLANNED | Root architecture is prose-first; no canonical UML authority is present. | Add textual Mermaid/PlantUML-compatible component and critical sequence diagrams after active source contracts stabilize. | -| ERD / schema model | PLANNED | SQL and schema tests are authoritative, but no canonical ERD summarizes package-owned identities, tenancy, checkpoint state, and relationships. | Generate/maintain an ERD from protected-main schema; label migration-only/active-PR objects separately. | +| ERD / schema model | ACTIVE-PR | This overlay adds `docs/erd/package-owned-schema.md` from packaged `schema.sql` plus migration-owned `llm_result_stream_checkpoints`. SQL remains stronger authority. Active recovery/reconciliation tables stay off the diagram until they exist on protected main. | Refresh the diagram only after a packaged table or migration-owned identity actually changes. | | General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184 or #212 documentation surfaces. | | Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | | Licensing / third-party notices | PARTIAL | Apache-2.0 source headers and repository licensing exist, but acquisition diligence should explicitly trace package license, dependency/SBOM evidence, and third-party notice process. | Evaluate a concise licensing/compliance evidence index without claiming legal certification. | diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md new file mode 100644 index 000000000..c02059166 --- /dev/null +++ b/docs/THREAT_MODEL.md @@ -0,0 +1,106 @@ +# Threat model + +## Authority + +This model describes protected-main `pg-llm-batch` assets, trust boundaries, +attacker capabilities, package mitigations, and residual risk. It is evidence +readiness for SOC 2 / CSAP preparation. It is not a certification, a penetration +test, or a claim that a deployment is authorized for production. + +Use it to decide the next host control, not to infer that PostgreSQL row-level +security, recovery receipts, or redacted diagnostics have already closed a +business risk. + +The methodology follows data-centric threat modeling (Scarfone & Souppaya, +2016/2016 IPD) and the NIST risk-assessment process (Joint Task Force, 2012): +identify the data, the system where it lives, the relevant threat sources, the +preconditions those sources need, and the residual risk after package controls. +Control families are aligned to NIST SP 800-53 Revision 5 (Joint Task Force, +2020). + +## What to do next + +1. Keep tenant selection behind your authenticated and authorized host boundary. +2. Do not grant arbitrary SQL, `SUPERUSER`, or `BYPASSRLS` to the application + role that runs this package. +3. Preserve authorized business payloads. Do not add blanket PII masking on + prompts, JSONL, or provider results; that would change token counts, replay, + and downstream decisions. +4. Treat recovery receipts and artifact hashes as identity evidence only. They + do not prove a backup is restorable or that a restore target is isolated. +5. Run `standalone` when you are a single-tenant operator. Use + `TenantDurableBatchAPIClient` only after your host has already chosen + `tenant_scope`. + +## Assets + +| Asset | Where it lives | Why a buyer cares | +| --- | --- | --- | +| Authorized prompts, JSONL payloads, and provider results | `llm_requests`, `llm_batch_file_payloads`, `llm_jsonl_lines`, provider files | Business meaning. Silent masking or truncation invalidates accounting. | +| Durable remote lifecycle identity | `llm_remote_batch_jobs` keyed by `(tenant_scope, endpoint_alias, remote_batch_id)` | Prevents one tenant from observing or advancing another tenant's batch. | +| Result-stream checkpoints | `llm_result_stream_checkpoints` keyed by `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | Prefix resume only. Not provider authenticity or whole-stream immutability. | +| Standalone secrets and configuration | `com_secrets`, `com_config` | Bootstrap transport. Compatibility mode can still persist `is_encrypted = FALSE`. | +| Provider credentials | Host-injected credential provider or standalone secret store | Never a tenant-selected authority and never a telemetry attribute. | +| Recovery evidence | In-memory receipts plus caller-owned backup/schema bytes | Content-free hash/size identity. Not restorability. | + +## Trust boundaries + +```text +[Caller / operator] + | host authentication and authorization (out of package) + v +[Host control plane] -- selects tenant_scope, credentials, DSN, restore target + | package Python API / CLI only + v +[pg-llm-batch] -- validates, bounds I/O, binds transaction-local set_config + | parameterized SQL + v +[PostgreSQL] -- forced RLS for lifecycle and checkpoint tables + | + +--> [Provider Batch API] untrusted statuses, IDs, JSON, JSONL + +--> [Caller-owned backup/restore tools] untrusted until a shipped executor lands +``` + +The package does not authenticate callers. `tenant_scope` is routing context +written with parameterized `set_config('pg_llm_batch.tenant_scope', ..., true)`. +A role that can execute arbitrary SQL can choose any scope. RLS is defense in +depth after that trusted write. + +## Threat sources and package mitigations + +| Threat source | Needed precondition | Package mitigation on protected main | Residual risk | +| --- | --- | --- | --- | +| Confused-deputy tenant selection | Host accepts provider IDs, headers, or model output as tenant authority | Tenant clients reject that path; scope is validated before reservation, credentials, provider I/O, or lifecycle SQL | Host mapping bugs remain outside the package. | +| Cross-tenant lifecycle read/write | Application role plus missing or wrong transaction-local scope | Forced RLS default-deny; tenant-qualified unique key and status index | `SUPERUSER` / `BYPASSRLS` / arbitrary SQL bypass the guarantee. | +| SQL injection or generic tenant SQL | Application role exposed through a SQL console | Parameterized statements; documented prohibition on generic SQL | The custom setting is not a credential. Do not grant arbitrary SQL. | +| Provider spoofing or oversized bodies | Network path to an unvalidated URL or unbounded parser | HTTPS production destinations, finite decoded-byte budgets, closed GET retry set `{408, 425, 429, 502, 503, 504}` | Provider authenticity is not proved by payload validation. HTTP 500 and POST stay single-attempt. | +| Secret reflection | Diagnostics copy DSNs, keys, prompts, or provider bodies | Bounded error vocabularies; public readiness omits lower-layer text | Generic `ValidationError` rejected-value confidentiality is still an active overlay. | +| Backup theft or unsafe restore | Operator points restore at the live cluster or a guessed artifact | Receipts and hashes identify bytes; they do not execute dump/restore | Executable backup/restore, catalog acceptance, and authenticated target isolation remain unshipped. | +| Checkpoint fork or replay | Concurrent consumers advance the same identity | CAS `SELECT ... FOR UPDATE` with exact previous checkpoint | PostgreSQL atomicity does not extend to provider or network effects. | +| Content-fidelity sabotage | A privacy filter rewrites authorized payloads | Package paths preserve authorized content unless a reviewed host policy says otherwise | A host that transforms content must keep provenance and acceptance tests. | + +## Explicit non-guarantees + +- This document does not claim SOC 2, CSAP, ISO/IEC 27001, or any other + certification. +- RLS does not replace authentication, authorization, or SQL-injection + prevention. +- A recovery receipt, schema hash, or backup-artifact hash does not prove + restorability, live-cluster parity, PITR, RPO, RTO, HA, or DR. +- A prefix checkpoint is not a distributed exactly-once claim. +- `standalone` is an explicit single-tenant scope, not an anonymous public mode. + +## References + +Joint Task Force. (2012). *Guide for conducting risk assessments* (NIST Special +Publication 800-30, Revision 1). National Institute of Standards and Technology. +https://doi.org/10.6028/NIST.SP.800-30r1 + +Joint Task Force. (2020). *Security and privacy controls for information systems +and organizations* (NIST Special Publication 800-53, Revision 5). National +Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-53r5 + +Scarfone, K., & Souppaya, M. (2016). *Guide to data-centric system threat +modeling* (NIST Special Publication 800-154, Initial Public Draft). National +Institute of Standards and Technology. +https://csrc.nist.gov/pubs/sp/800/154/ipd diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 5093d3edc..329da642d 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -77,7 +77,8 @@ The following open pull requests are represented only as overlays. Their existen - **#208** — bounded logical PostgreSQL backup executor using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. - **#210** — configuration/secrets operator/runtime contract successor; encryption-required policy, least-privilege runtime readiness, and provisioning separation remain unshipped until this lane is repaired and integrated. - **#212** — direct logical-restore successor to closed #209; it replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying restore-contract documentation. It is not evidence of isolated restore acceptance or end-to-end recovery readiness. -- **#214** — this five-file canonical overlay; protected-main status does not change until this documentation lane integrates. +- **#214** — superseded canonical overlay that still froze transient Draft labels; keep it Draft. +- **#226** — current canonical documentation successor. It removes Draft/Ready vocabulary, names adjacent recovery families, and adds the threat-model and package ERD overlays. Protected-main status does not change until this lane integrates. - **#215** — recovery receipt evidence-binding candidate; exact-type evidence objects must not be mistaken for inspection provenance, and the active lane remains unshipped until repaired and accepted. - **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives only and does not execute recovery or claim achieved RPO/RTO. - **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. diff --git a/docs/erd/package-owned-schema.md b/docs/erd/package-owned-schema.md new file mode 100644 index 000000000..d5149aa7f --- /dev/null +++ b/docs/erd/package-owned-schema.md @@ -0,0 +1,159 @@ +# Package-owned schema ERD + +## Authority + +This diagram summarizes protected-main package tables from +`pg_llm_batch/schema.sql` plus the migration-owned checkpoint table from +`pg_llm_batch/migrations/0007_result_stream_checkpoints.sql`. SQL and schema +tests remain stronger authority than this picture. + +Use it to see identities, foreign keys, and tenant qualification before you +write a report, a restore drill, or an embedding mapping. Do not treat the +diagram as proof that backup/restore, candidate discovery, or distributed +exactly-once processing is shipped. + +## What to do next + +1. Keep new database objects as two-or-more-word `snake_case` names. +2. Bind `tenant_scope` before reading `llm_remote_batch_jobs` or + `llm_result_stream_checkpoints`. +3. Treat `llm_result_stream_checkpoints` as prefix evidence, not a distributed + exactly-once claim. +4. Leave ACTIVE-PR recovery and reconciliation tables off this diagram until + they exist on protected main. + +## Identities + +| Table | Durable identity | Notes | +| --- | --- | --- | +| `llm_remote_batch_jobs` | `tenant_scope, endpoint_alias, remote_batch_id` | Forced RLS. Provider data never selects the tenant. | +| `llm_result_stream_checkpoints` | `tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id` | Added by migration 0007. Forced RLS. | +| `llm_queues` | `queue_uuid` / unique `queue_name` | Standalone preparation owner. | +| `llm_batches` | `batch_uuid` | Child of one queue. | +| `llm_batch_file_payloads` | `file_id` | Canonical JSONL bytes in PostgreSQL. | +| `llm_batch_files` | `(batch_uuid, part_index)` | Virtual payload via `payload_file_id`. | +| `llm_requests` | `request_uuid` | Authorized prompt/result content. | +| `llm_jsonl_lines` | `(payload_file_id, sequence_no)` | JOIN-only reconstruction. | +| `llm_endpoints` | `endpoint_alias` | Configuration, not tenant authority. | +| `com_config` / `com_secrets` | `config_key` / `secret_key` | KV stores. Compatibility secrets may be plaintext. | + +## Entity-relationship diagram + +```mermaid +erDiagram + com_config { + text config_key PK + text config_value + timestamptz updated_at + } + + com_secrets { + text secret_key PK + text secret_value + boolean is_encrypted + timestamptz updated_at + } + + llm_queues { + uuid queue_uuid PK + text queue_name UK + text queue_status + timestamptz created_at + } + + llm_batches { + uuid batch_uuid PK + uuid queue_uuid FK + text batch_name + text batch_status + text model_name + timestamptz created_at + } + + llm_batch_file_payloads { + uuid file_uuid PK + text file_id UK + jsonb content + timestamptz created_at + } + + llm_batch_files { + uuid file_uuid PK + uuid batch_uuid FK + uuid queue_uuid FK + text payload_file_id FK + int part_index + } + + llm_requests { + uuid request_uuid PK + uuid batch_uuid FK + uuid batch_file_uuid FK + text user_prompt + text response_content + text request_status + } + + llm_jsonl_lines { + uuid line_uuid PK + text payload_file_id FK + uuid request_uuid FK + int sequence_no + text line_text + } + + llm_endpoints { + uuid endpoint_uuid PK + text endpoint_alias UK + text base_url + boolean active + } + + llm_endpoint_models { + uuid endpoint_uuid PK,FK + text model_id PK + text tokenizer_model + } + + llm_remote_batch_jobs { + uuid remote_job_uuid PK + text tenant_scope + text endpoint_alias + text remote_batch_id + bigint observation_order + text batch_status + } + + llm_result_stream_checkpoints { + uuid result_checkpoint_uuid PK + text tenant_scope + text checkpoint_consumer_name + text endpoint_alias + text remote_batch_id + text prefix_sha256 + } + + llm_queues ||--o{ llm_batches : contains + llm_queues ||--o{ llm_batch_files : owns + llm_batches ||--o{ llm_batch_files : partitions + llm_batch_file_payloads ||--o{ llm_batch_files : stores + llm_batches ||--o{ llm_requests : queues + llm_batch_files ||--o{ llm_requests : assigns + llm_batch_file_payloads ||--o{ llm_jsonl_lines : lines + llm_requests ||--o{ llm_jsonl_lines : reconstructs + llm_endpoints ||--o{ llm_endpoint_models : maps +``` + +`llm_remote_batch_jobs` and `llm_result_stream_checkpoints` are intentionally +unrelated to the preparation graph. Their tenant-qualified unique keys are the +lifecycle and checkpoint identities. Migration 0007 owns the checkpoint table; +the packaged `schema.sql` / Docker init mirror do not create it. + +## Third-normal-form boundary + +Preparation tables keep queue, batch, payload, request, and line facts in +separate relations with explicit keys. Endpoint/model mapping is a separate +relation from lifecycle projection. The KV tables `com_config` and `com_secrets` +are key/value stores by design: each row is one setting, not a repeating group +inside another entity. Do not add single-word table names or embed tenant +authority in provider columns. diff --git a/tests/test_schema_erd_documentation.py b/tests/test_schema_erd_documentation.py new file mode 100644 index 000000000..039c2dc3b --- /dev/null +++ b/tests/test_schema_erd_documentation.py @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: Apache-2.0 +"""The package ERD must name every protected-main table and the checkpoint overlay.""" + +from __future__ import annotations + +import re +from pathlib import Path + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +SCHEMA = REPOSITORY_ROOT / "pg_llm_batch" / "schema.sql" +CHECKPOINT_MIGRATION = ( + REPOSITORY_ROOT + / "pg_llm_batch" + / "migrations" + / "0007_result_stream_checkpoints.sql" +) +ERD = REPOSITORY_ROOT / "docs" / "erd" / "package-owned-schema.md" +FITNESS = REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md" +_TABLE_NAME = re.compile( + r"CREATE TABLE IF NOT EXISTS ([a-z][a-z0-9_]+)", + re.MULTILINE, +) + + +def _read(path: Path) -> str: + """Return one repository text file as UTF-8.""" + return path.read_text(encoding="utf-8") + + +def _table_names(sql_text: str) -> tuple[str, ...]: + """Return CREATE TABLE names in document order.""" + return tuple(_TABLE_NAME.findall(sql_text)) + + +def test_erd_names_every_packaged_schema_table() -> None: + """An acquisition reviewer can map SQL objects without reading schema.sql first.""" + erd = _read(ERD) + tables = _table_names(_read(SCHEMA)) + assert tables, "packaged schema must declare tables" + for table_name in tables: + assert table_name in erd, table_name + assert "_" in table_name + + +def test_erd_labels_checkpoint_table_as_migration_owned() -> None: + """Checkpoint storage is packaged by migration 0007, not the init schema copy.""" + erd = _read(ERD) + checkpoint_tables = _table_names(_read(CHECKPOINT_MIGRATION)) + assert checkpoint_tables == ("llm_result_stream_checkpoints",) + assert "llm_result_stream_checkpoints" in erd + assert "0007" in erd + assert "ACTIVE-PR" in erd or "not a distributed exactly-once" in erd.lower() + + +def test_erd_uses_tenant_qualified_identities() -> None: + """The diagram must show the tenant-qualified lifecycle and checkpoint keys.""" + erd = _read(ERD) + assert "tenant_scope, endpoint_alias, remote_batch_id" in erd + assert "checkpoint_consumer_name" in erd + assert "erDiagram" in erd + + +def test_fitness_inventory_tracks_the_erd_overlay() -> None: + """The fitness matrix must stop calling the ERD merely planned.""" + fitness = _read(FITNESS) + assert "docs/erd/package-owned-schema.md" in fitness + assert "| ERD / schema model | PLANNED |" not in fitness diff --git a/tests/test_threat_model_documentation.py b/tests/test_threat_model_documentation.py new file mode 100644 index 000000000..c792bd4da --- /dev/null +++ b/tests/test_threat_model_documentation.py @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: Apache-2.0 +"""Static contracts for the protected-main threat-model overlay.""" + +from __future__ import annotations + +from pathlib import Path + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +THREAT_MODEL = REPOSITORY_ROOT / "docs" / "THREAT_MODEL.md" +FITNESS = REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md" + + +def _read(path: Path) -> str: + """Return one Markdown document as UTF-8 text.""" + return path.read_text(encoding="utf-8") + + +def test_threat_model_identifies_assets_boundaries_and_residuals() -> None: + """A buyer must see assets, trust boundaries, mitigations, and residual risk.""" + text = _read(THREAT_MODEL) + assert "tenant_scope" in text + assert "llm_remote_batch_jobs" in text + assert "llm_result_stream_checkpoints" in text + assert "authorized business payloads" in text.lower() or "content fidelity" in text.lower() + assert "set_config" in text + assert "BYPASSRLS" in text + assert "Residual" in text + assert "does not claim" in text.lower() or "not a certification" in text.lower() + + +def test_threat_model_cites_current_risk_authorities() -> None: + """Doctoring must cite current NIST risk and control publications in APA 7th.""" + text = " ".join(_read(THREAT_MODEL).split()) + assert "NIST Special Publication 800-53" in text + assert "NIST Special Publication 800-30" in text + assert "800-154" in text + assert "https://doi.org/10.6028/NIST.SP.800-53r5" in text + assert "https://doi.org/10.6028/NIST.SP.800-30r1" in text + + +def test_threat_model_tells_the_operator_the_next_action() -> None: + """The document must tell a qualified host what to do next, not only what exists.""" + text = " ".join(_read(THREAT_MODEL).split()) + assert "Do not grant arbitrary SQL" in text or "do not grant arbitrary SQL" in text + assert "standalone" in text + + +def test_fitness_inventory_tracks_the_threat_model_overlay() -> None: + """The fitness matrix must stop calling the threat model merely planned.""" + fitness = _read(FITNESS) + assert "docs/THREAT_MODEL.md" in fitness + assert "| Threat model | PLANNED |" not in fitness From 65be01d69ad3192f892ebe0e9cd27356594f9458 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 16:54:39 +0000 Subject: [PATCH 35/58] docs: add data-governance and component UML overlays Map payload ownership, retention, and the no-blanket-masking privacy boundary, and show standalone versus embedded composition so a buyer can see the next host control without reading SQL first. Co-authored-by: Seongho Bae --- docs/DATA_GOVERNANCE.md | 78 +++++++++++++++++++++ docs/DOCUMENTATION_FITNESS.md | 4 +- docs/TRACEABILITY.md | 2 +- docs/uml/component-and-sequence.md | 77 ++++++++++++++++++++ tests/test_data_governance_documentation.py | 44 ++++++++++++ tests/test_uml_documentation.py | 36 ++++++++++ 6 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 docs/DATA_GOVERNANCE.md create mode 100644 docs/uml/component-and-sequence.md create mode 100644 tests/test_data_governance_documentation.py create mode 100644 tests/test_uml_documentation.py diff --git a/docs/DATA_GOVERNANCE.md b/docs/DATA_GOVERNANCE.md new file mode 100644 index 000000000..ce403c7de --- /dev/null +++ b/docs/DATA_GOVERNANCE.md @@ -0,0 +1,78 @@ +# Data governance + +## Authority + +This contract maps protected-main data classes, owners, tenant authority, +retention, deletion, and privacy boundaries. SQL, package code, and the +canonical PRD/TRD remain stronger authority. It is evidence readiness, not a +certification and not a claim that a deployment has a complete records program. + +## What to do next + +1. Decide which host identity is allowed to select `tenant_scope` before any + package call. +2. Do not mask, tokenize away, or truncate authorized business payloads inside + this package. If your policy requires transformation, do it in an explicit + host boundary with provenance and acceptance tests. +3. Keep Fernet or an external secret manager as a host/deployment choice. + Protected main can persist `com_secrets.is_encrypted = FALSE` in + compatibility mode. +4. Own backup copies, replica retention, log/telemetry retention, and + destructive deletion yourself. The package will not invent a general purge. +5. Use `standalone` for a single-tenant operator. Do not reuse that scope as an + anonymous public bucket. + +## Data classes + +| Class | Principal objects | Owner | Package duty | +| --- | --- | --- | --- | +| Authorized business payloads | `llm_requests` prompts/results, `llm_batch_file_payloads`, `llm_jsonl_lines` | Embedding host / business process | Persist and replay exactly. Do not mask. | +| Durable lifecycle projection | `llm_remote_batch_jobs` | Host-selected `tenant_scope` plus package recorder | Tenant-qualify identity, bind `set_config`, force RLS. | +| Result checkpoints | `llm_result_stream_checkpoints` | Host-selected consumer name plus tenant | Store prefix evidence only. | +| Standalone configuration | `com_config` | Operator | Key/value settings. Not tenant authorization. | +| Standalone secrets | `com_secrets` | Operator / secret-manager host | Optional Fernet. Compatibility plaintext is not a production claim. | +| Provider credentials | Host credential provider | Deployment | Resolve after tenant validation. Never tenant-keyed by this package. | +| Recovery evidence | Receipts, artifact hashes, schema hashes | Operator | Content-free identity. Not restorability. | +| Operational diagnostics | Errors, logs, readiness, telemetry | Package | Omit payloads, DSNs, credentials, and dynamic exception text. | + +## Tenant authority + +`tenant_scope` is selected only by a trusted authenticated/authorized host +boundary. Provider metadata, remote identifiers, request bodies, model output, +endpoint aliases, and transport headers are never tenant authorities. The +embedding host owns the identity-to-tenant map. + +## Retention and deletion + +Protected main does not define a universal business-data retention duration. +The embedding host owns purpose, retention period, deletion authorization, and +evidence that the policy ran. The deployment owner separately owns PostgreSQL +backup/replica, WAL, and infrastructure log retention. Provider-side retention +remains a provider/account policy unless a reviewed adapter implements it. + +The package will not silently delete unknown operator objects, rewrite history, +or `CASCADE` through unrelated schemas as a recovery shortcut. + +## Privacy without paralysis + +ISO/IEC 29100 treats purpose specification and data minimization as +organization policy, not as an excuse to destroy the meaning of a processing +record (ISO/IEC, 2024). NIST SP 800-53 Revision 5 likewise places confidentiality +controls at authorization, access, transmission, and audit boundaries (Joint +Task Force, 2020). This package therefore: + +- preserves authorized business payloads; +- redacts operational surfaces; +- fails closed on untrusted provider and path input; +- refuses to treat RLS or diagnostic redaction as proof that persisted + business content was masked. + +## References + +International Organization for Standardization. (2024). *Information +technology — Security techniques — Privacy framework* (ISO/IEC 29100:2024). +https://www.iso.org/standard/85938.html + +Joint Task Force. (2020). *Security and privacy controls for information systems +and organizations* (NIST Special Publication 800-53, Revision 5). National +Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-53r5 diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 8bc1a2470..ccab66d16 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -38,8 +38,8 @@ Protected main now also contains the bounded recovery-evidence primitives integr | Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. #210 is the unshipped operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | | Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | | Threat model | ACTIVE-PR | This overlay adds `docs/THREAT_MODEL.md` with assets, trust boundaries, attacker preconditions, package mitigations, residual risk, operator next actions, and APA 7th NIST citations. It is not protected-main truth until this documentation lane integrates, and it does not claim SOC 2/CSAP certification. | Promote only after exact-head gates and merge; keep residual-risk language if a later executor or worker lands. | -| Data governance | PLANNED | No single canonical data-governance document currently maps data classes, retention/ownership, tenant authority, privacy exposure, backup/restore, and deletion limits. | Add a protected-main-grounded data-governance contract. | -| UML/component/sequence views | PLANNED | Root architecture is prose-first; no canonical UML authority is present. | Add textual Mermaid/PlantUML-compatible component and critical sequence diagrams after active source contracts stabilize. | +| Data governance | ACTIVE-PR | This overlay adds `docs/DATA_GOVERNANCE.md` mapping data classes, owners, tenant authority, retention/deletion limits, and the no-blanket-masking privacy boundary with APA 7th citations. | Promote only after exact-head gates and merge; do not treat this file as a records-program certification. | +| UML/component/sequence views | ACTIVE-PR | This overlay adds `docs/uml/component-and-sequence.md` showing standalone/embedded composition and the tenant-validation sequence. ACTIVE-PR executors stay off the shipped component list. | Update only when a protected-main component or seam actually changes. | | ERD / schema model | ACTIVE-PR | This overlay adds `docs/erd/package-owned-schema.md` from packaged `schema.sql` plus migration-owned `llm_result_stream_checkpoints`. SQL remains stronger authority. Active recovery/reconciliation tables stay off the diagram until they exist on protected main. | Refresh the diagram only after a packaged table or migration-owned identity actually changes. | | General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184 or #212 documentation surfaces. | | Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 329da642d..3cc373226 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -78,7 +78,7 @@ The following open pull requests are represented only as overlays. Their existen - **#210** — configuration/secrets operator/runtime contract successor; encryption-required policy, least-privilege runtime readiness, and provisioning separation remain unshipped until this lane is repaired and integrated. - **#212** — direct logical-restore successor to closed #209; it replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying restore-contract documentation. It is not evidence of isolated restore acceptance or end-to-end recovery readiness. - **#214** — superseded canonical overlay that still froze transient Draft labels; keep it Draft. -- **#226** — current canonical documentation successor. It removes Draft/Ready vocabulary, names adjacent recovery families, and adds the threat-model and package ERD overlays. Protected-main status does not change until this lane integrates. +- **#226** — current canonical documentation successor. It removes Draft/Ready vocabulary, names adjacent recovery families, and adds threat-model, data-governance, UML, and package ERD overlays. Protected-main status does not change until this lane integrates. - **#215** — recovery receipt evidence-binding candidate; exact-type evidence objects must not be mistaken for inspection provenance, and the active lane remains unshipped until repaired and accepted. - **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives only and does not execute recovery or claim achieved RPO/RTO. - **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. diff --git a/docs/uml/component-and-sequence.md b/docs/uml/component-and-sequence.md new file mode 100644 index 000000000..ec37a78fe --- /dev/null +++ b/docs/uml/component-and-sequence.md @@ -0,0 +1,77 @@ +# Component and sequence views + +## Authority + +These diagrams describe protected-main composition. They do not add runtime +authority and do not promote ACTIVE-PR backup, restore, discovery, or worker +lanes into shipped components. + +## What to do next + +1. Deploy this package alone, or embed it behind `contextual-orchestrator` / + `naruon` after those hosts authenticate and authorize. +2. Inject credentials and `tenant_scope` from the host. Do not read them from + provider responses. +3. Call `DurableBatchAPIClient` for `standalone`. Call + `TenantDurableBatchAPIClient` only after the host has chosen a scope. + +## Component view + +```mermaid +flowchart LR + subgraph hosts [Optional CWL hosts] + orchestrator[contextual-orchestrator] + naruon[naruon] + end + subgraph package [pg-llm-batch standalone or embedded] + cli[cli.py] + durable[DurableBatchAPIClient] + tenant[TenantDurableBatchAPIClient] + client[batch_api_client.py] + reconcile[reconciliation.py] + db[db.py] + checkpoints[checkpoint_store.py] + evidence[recovery evidence modules] + end + postgres[(PostgreSQL)] + provider[OpenAI-compatible Batch API] + orchestrator -->|authorized tenant_scope| tenant + naruon -->|authorized tenant_scope| tenant + cli --> durable + durable -->|standalone| db + tenant -->|set_config tenant_scope| db + durable --> client + tenant --> client + reconcile --> client + db --> postgres + checkpoints --> postgres + client --> provider + evidence -.->|hash and receipt only| postgres +``` + +`contextual-orchestrator` and `naruon` are optional. The package must keep +working when they are absent. + +## Tenant lifecycle sequence + +```mermaid +sequenceDiagram + participant Host + participant TenantClient as TenantDurableBatchAPIClient + participant DB as db.py + participant PG as PostgreSQL + participant Provider as Batch API + Host->>TenantClient: construct(tenant_scope) + TenantClient->>TenantClient: validate tenant_scope + Host->>TenantClient: observe or persist remote batch + TenantClient->>DB: parameterized set_config(tenant_scope) + DB->>PG: transaction-local scope plus RLS + TenantClient->>Provider: bounded upload/create/poll/retrieve + Provider-->>TenantClient: untrusted status and files + TenantClient->>DB: tenant-qualified upsert + DB->>PG: (tenant_scope, endpoint_alias, remote_batch_id) +``` + +A missing or malformed scope fails before credential lookup, provider I/O, or +lifecycle SQL. `DurableBatchAPIClient` keeps the four-argument recorder seam +and stores under the exact `standalone` scope. diff --git a/tests/test_data_governance_documentation.py b/tests/test_data_governance_documentation.py new file mode 100644 index 000000000..cc5ab232d --- /dev/null +++ b/tests/test_data_governance_documentation.py @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: Apache-2.0 +"""Static contracts for the data-governance overlay.""" + +from __future__ import annotations + +from pathlib import Path + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +GOVERNANCE = REPOSITORY_ROOT / "docs" / "DATA_GOVERNANCE.md" +FITNESS = REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md" + + +def _read(path: Path) -> str: + """Return one Markdown document as UTF-8 text.""" + return path.read_text(encoding="utf-8") + + +def test_data_governance_maps_classes_retention_and_deletion_limits() -> None: + """A buyer must see data classes, owners, retention, and what the package will not delete.""" + text = " ".join(_read(GOVERNANCE).split()) + assert "llm_requests" in text + assert "com_secrets" in text + assert "tenant_scope" in text + assert "authorized business payloads" in text.lower() + assert "Do not mask" in text or "do not mask" in text + assert "retention" in text.lower() + assert "deletion" in text.lower() + assert "host owns" in text.lower() or "embedding host owns" in text.lower() + + +def test_data_governance_cites_privacy_and_control_authorities() -> None: + """Doctoring must cite current privacy-control publications in APA 7th.""" + text = " ".join(_read(GOVERNANCE).split()) + assert "NIST Special Publication 800-53" in text + assert "https://doi.org/10.6028/NIST.SP.800-53r5" in text + assert "ISO/IEC 27701" in text or "ISO/IEC 29100" in text + + +def test_fitness_inventory_tracks_the_data_governance_overlay() -> None: + """The fitness matrix must stop calling data governance merely planned.""" + fitness = _read(FITNESS) + assert "docs/DATA_GOVERNANCE.md" in fitness + assert "| Data governance | PLANNED |" not in fitness diff --git a/tests/test_uml_documentation.py b/tests/test_uml_documentation.py new file mode 100644 index 000000000..b839c763d --- /dev/null +++ b/tests/test_uml_documentation.py @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: Apache-2.0 +"""Static contracts for the component and sequence UML overlay.""" + +from __future__ import annotations + +from pathlib import Path + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +UML = REPOSITORY_ROOT / "docs" / "uml" / "component-and-sequence.md" +FITNESS = REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md" + + +def _read(path: Path) -> str: + """Return one Markdown document as UTF-8 text.""" + return path.read_text(encoding="utf-8") + + +def test_uml_shows_standalone_and_embedded_component_boundaries() -> None: + """A buyer must see standalone operation and MSA embedding as co-equal.""" + text = _read(UML) + assert "flowchart" in text or "C4Context" in text + assert "sequenceDiagram" in text + assert "DurableBatchAPIClient" in text + assert "TenantDurableBatchAPIClient" in text + assert "standalone" in text + assert "contextual-orchestrator" in text + assert "naruon" in text + assert "set_config" in text + + +def test_fitness_inventory_tracks_the_uml_overlay() -> None: + """The fitness matrix must stop calling UML merely planned.""" + fitness = _read(FITNESS) + assert "docs/uml/component-and-sequence.md" in fitness + assert "| UML/component/sequence views | PLANNED |" not in fitness From 93b76d2a06c4ce858738eebca278e1dbdbb5eb1d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 16:58:38 +0000 Subject: [PATCH 36/58] docs(recovery): name the live canonical overlay without Draft instructions Keep #214 and #226 as superseded predecessors, point restore-target isolation at #225, and reject leftover keep-it-Draft register wording. Co-authored-by: Seongho Bae --- docs/DOCUMENTATION_FITNESS.md | 2 +- docs/TRACEABILITY.md | 7 ++++--- tests/test_canonical_status_vocabulary.py | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index ccab66d16..08a6e2d72 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -36,7 +36,7 @@ Protected main now also contains the bounded recovery-evidence primitives integr | Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | | Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | | Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. #210 is the unshipped operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | -| Canonical traceability | ACTIVE-PR | This branch is establishing the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | +| Canonical traceability | ACTIVE-PR | This overlay is the current canonical-documentation successor to superseded #214 and to #226, which still froze a transient pull-request state instruction. It establishes the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | | Threat model | ACTIVE-PR | This overlay adds `docs/THREAT_MODEL.md` with assets, trust boundaries, attacker preconditions, package mitigations, residual risk, operator next actions, and APA 7th NIST citations. It is not protected-main truth until this documentation lane integrates, and it does not claim SOC 2/CSAP certification. | Promote only after exact-head gates and merge; keep residual-risk language if a later executor or worker lands. | | Data governance | ACTIVE-PR | This overlay adds `docs/DATA_GOVERNANCE.md` mapping data classes, owners, tenant authority, retention/deletion limits, and the no-blanket-masking privacy boundary with APA 7th citations. | Promote only after exact-head gates and merge; do not treat this file as a records-program certification. | | UML/component/sequence views | ACTIVE-PR | This overlay adds `docs/uml/component-and-sequence.md` showing standalone/embedded composition and the tenant-validation sequence. ACTIVE-PR executors stay off the shipped component list. | Update only when a protected-main component or seam actually changes. | diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 3cc373226..a66fa9f36 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -24,7 +24,7 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | FR-5 recovery evidence binding and live re-verification | ACTIVE-PR | protected main exposes the underlying receipt/schema/artifact evidence primitives only | PRs #215 and #221 exact-head evidence only | Bind-time composition and later re-inspection are active candidate seams, not inspection provenance or restore proof on protected main. A verifier success is integrity agreement at the inspection instant and does not remove TOCTOU or target-isolation requirements. | | FR-5 post-restore catalog acceptance | ACTIVE-PR | protected-main schema and recovery evidence only | PR #223 exact-head catalog/unit/container evidence only; closed #216 is predecessor evidence | Catalog acceptance remains unshipped. Same-name index decoys, tenant-qualified key order, uniqueness/constraint authority, access method, readiness/validity, and live PostgreSQL query behavior must remain fail-closed before this can become protected-main truth. | | FR-5 physical/WAL/PITR recovery profile | ACTIVE-PR | none on protected main beyond bounded recovery evidence | PR #219 exact-head evidence only | The profile records caller-owned recovery intent and objectives; it does not execute `pg_basebackup`, archive/replay WAL, prove an isolated target, or establish package RPO/RTO capability. | -| FR-5 restore-target isolation | PARTIAL | no protected-main target-isolation proof exists | active recovery acceptance work, including PR #224, is PR evidence only | Distinct configuration labels alone are insufficient to prove two service aliases resolve to different clusters. End-to-end acceptance must authenticate the actual restore target before production safety can be claimed. | +| FR-5 restore-target isolation | PARTIAL | no protected-main target-isolation proof exists | PR #225 exact-head evidence only; #224 remains the ADR 0021 collision predecessor | Distinct libpq service names are a configuration-label check only. They are not authenticated cluster isolation. End-to-end acceptance must authenticate the actual restore target before production safety can be claimed. | | FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded receipt/artifact/schema evidence primitives are integrated | Issue #204 acceptance authority plus protected-main recovery evidence tests | Active logical execution, evidence binding/reinspection, catalog acceptance, physical/PITR profiling, and target-isolation slices remain unshipped. No protected-main isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | | FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. #210 is the active operator/runtime-contract successor to the closed #193 line; neither its stricter policy nor provisioning/runtime separation is protected-main truth until integration. | @@ -77,8 +77,9 @@ The following open pull requests are represented only as overlays. Their existen - **#208** — bounded logical PostgreSQL backup executor using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. - **#210** — configuration/secrets operator/runtime contract successor; encryption-required policy, least-privilege runtime readiness, and provisioning separation remain unshipped until this lane is repaired and integrated. - **#212** — direct logical-restore successor to closed #209; it replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying restore-contract documentation. It is not evidence of isolated restore acceptance or end-to-end recovery readiness. -- **#214** — superseded canonical overlay that still froze transient Draft labels; keep it Draft. -- **#226** — current canonical documentation successor. It removes Draft/Ready vocabulary, names adjacent recovery families, and adds threat-model, data-governance, UML, and package ERD overlays. Protected-main status does not change until this lane integrates. +- **#214** — superseded canonical overlay that froze transient pull-request state labels; it is not the landing vehicle. +- **#226** — previous canonical documentation successor that still told operators to keep #214 in a transient pull-request state. It is not the landing vehicle after the register repair. +- **this overlay** — current canonical documentation landing vehicle. It keeps the #226 documentation set, removes the leftover transient-state instruction, names adjacent recovery families, and adds threat-model, data-governance, UML, and package ERD overlays. Protected-main status does not change until this lane integrates. - **#215** — recovery receipt evidence-binding candidate; exact-type evidence objects must not be mistaken for inspection provenance, and the active lane remains unshipped until repaired and accepted. - **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives only and does not execute recovery or claim achieved RPO/RTO. - **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. diff --git a/tests/test_canonical_status_vocabulary.py b/tests/test_canonical_status_vocabulary.py index ea39dbd0d..1afac307e 100644 --- a/tests/test_canonical_status_vocabulary.py +++ b/tests/test_canonical_status_vocabulary.py @@ -70,3 +70,22 @@ def test_product_contract_names_active_recovery_capability_families() -> None: assert "catalog" in document.lower() assert "pitr" in document.lower() assert "target isolation" in document.lower() or "restore-target" in document.lower() + + +def test_canonical_overlay_register_names_current_successor_without_draft_instruction() -> None: + """The durable register must name the live overlay and must not freeze Draft/Ready instructions.""" + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") + fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") + + assert "#214" in traceability + assert "superseded" in traceability.lower() + assert "#226" in traceability + assert "not the landing vehicle" in traceability + assert "keep it Draft" not in traceability + assert "keep it Ready" not in traceability + assert "#225" in traceability + assert "ADR 0022" in traceability + assert "ADR 0021 collision" in traceability + assert "#226" in fitness + assert "superseded #214" in fitness + assert "current canonical documentation landing vehicle" in traceability From 5743a3454a831a114644318f868dec8e63c02a5a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:32:13 +0900 Subject: [PATCH 37/58] test(docs): reject stale merged-capability status --- tests/test_canonical_status_vocabulary.py | 101 +++++++++++++++++----- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/tests/test_canonical_status_vocabulary.py b/tests/test_canonical_status_vocabulary.py index 1afac307e..f46e47f58 100644 --- a/tests/test_canonical_status_vocabulary.py +++ b/tests/test_canonical_status_vocabulary.py @@ -1,11 +1,14 @@ # SPDX-License-Identifier: Apache-2.0 -"""Canonical product documents must not persist transient pull-request state.""" +"""Canonical product documents must track durable protected-main capability truth.""" from __future__ import annotations +import inspect import re from pathlib import Path +from pg_llm_batch.config import SecretStore + REPOSITORY_ROOT = Path(__file__).resolve().parents[1] CANONICAL_STATUS_DOCUMENTS = ( @@ -15,11 +18,19 @@ REPOSITORY_ROOT / "docs" / "TRACEABILITY.md", REPOSITORY_ROOT / "docs" / "adr" / "README.md", ) +_SECRET_POLICY_DOCUMENTS = ( + REPOSITORY_ROOT / "docs" / "product" / "PRD.md", + REPOSITORY_ROOT / "docs" / "product" / "TRD.md", + REPOSITORY_ROOT / "docs" / "DATA_GOVERNANCE.md", + REPOSITORY_ROOT / "docs" / "THREAT_MODEL.md", + REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md", + REPOSITORY_ROOT / "docs" / "TRACEABILITY.md", +) _TRANSIENT_PR_STATE = re.compile( r"(?i)\b(?:draft|ready)\s+#\d+\b|\bpr\s+#\d+\s+remains\s+draft\b" ) _EXACT_HEAD_SHA = re.compile(r"\b[0-9a-f]{40}\b") -_PROTECTED_MAIN_REFERENCE_TREE = "d2f1e32271910a6db98a0757d67194ddadca4566" +_ACTIVE_OVERLAY_ENTRY = re.compile(r"(?m)^- \*\*#(?P\d+)\*\*") def _read(path: Path) -> str: @@ -34,33 +45,78 @@ def test_canonical_status_documents_omit_transient_pr_ready_or_draft_labels() -> assert matches == [], f"{path.name} persists transient PR state: {matches}" -def test_canonical_status_documents_do_not_embed_exact_contributor_heads() -> None: - """Exact SHAs belong in review evidence, not durable product-status prose.""" +def test_canonical_status_documents_do_not_embed_exact_heads() -> None: + """Exact contributor or protected SHAs belong in review evidence, not durable prose.""" for path in CANONICAL_STATUS_DOCUMENTS: - text = _read(path) - leftover = [ - match - for match in _EXACT_HEAD_SHA.findall(text) - if match != _PROTECTED_MAIN_REFERENCE_TREE - ] - assert leftover == [], f"{path.name} embeds exact heads: {leftover}" + matches = _EXACT_HEAD_SHA.findall(_read(path)) + assert matches == [], f"{path.name} embeds exact heads: {matches}" -def test_product_contract_names_restore_successor_without_draft_label() -> None: - """#209 is the unsafe predecessor; #212 is the unshipped active successor.""" +def test_product_contract_records_integrated_logical_restore_boundary() -> None: + """Merged #212 is shipped only as the bounded direct logical-restore executor.""" prd = _read(REPOSITORY_ROOT / "docs" / "product" / "PRD.md") trd = _read(REPOSITORY_ROOT / "docs" / "product" / "TRD.md") fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") - for document in (prd, trd, fitness): - assert "Draft #212" not in document + assert "| PostgreSQL logical restore execution | IMPLEMENTED-ON-PROTECTED-MAIN |" in prd + assert "Direct `pg_restore` execution is **IMPLEMENTED-ON-PROTECTED-MAIN**" in trd + assert "logical restore executor is protected-main behavior" in fitness + assert "| FR-5 executable PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN |" in traceability + for document in (prd, trd, fitness, traceability): assert "#212" in document assert "#209" in document - assert "EOF-consumption" in document or "EOF" in document + assert "EOF" in document + assert "RPO/RTO" in document or "RPO" in document + + +def test_product_contract_records_integrated_single_flight_without_lease_claim() -> None: + """Merged #191 is a transient session advisory lock, not a scheduler or durable lease.""" + prd = _read(REPOSITORY_ROOT / "docs" / "product" / "PRD.md") + trd = _read(REPOSITORY_ROOT / "docs" / "product" / "TRD.md") + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") + + assert "| Cross-process reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN |" in prd + assert "tenant-qualified session advisory single-flight is protected-main behavior" in trd + assert "| FR-4 tenant-qualified cross-process single-flight | IMPLEMENTED-ON-PROTECTED-MAIN |" in traceability + for document in (prd, trd, traceability): + lowered = document.lower() + assert "durable lease" in lowered + assert "scheduler" in lowered + assert "distributed exactly-once" in lowered + + +def test_secret_policy_docs_match_optional_fernet_compatibility_default() -> None: + """Canonical secret prose must not turn optional Fernet into a shipped mandate.""" + parameter = inspect.signature(SecretStore).parameters["require_encryption"] + assert parameter.default is False + + for path in _SECRET_POLICY_DOCUMENTS: + text = _read(path) + lowered = text.lower() + if "secret" not in lowered: + continue + assert "optional fernet" in lowered or "fernet" in lowered + assert "compatibility" in lowered + assert "encrypted secrets are postgresql-backed" not in lowered + assert "postgresql-backed configuration and encrypted secret storage" not in lowered + + +def test_active_overlay_register_excludes_merged_or_closed_recovery_predecessors() -> None: + """The active register must not retain merged #191/#212 or closed #225 as live work.""" + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") + active_numbers = { + int(match.group("number")) for match in _ACTIVE_OVERLAY_ENTRY.finditer(traceability) + } + assert 191 not in active_numbers + assert 212 not in active_numbers + assert 225 not in active_numbers + assert 296 in active_numbers + assert 341 in active_numbers def test_product_contract_names_active_recovery_capability_families() -> None: - """The recovery graph is more than logical dump/restore execution.""" + """The recovery graph remains broader than the integrated logical restore executor.""" prd = _read(REPOSITORY_ROOT / "docs" / "product" / "PRD.md") fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") @@ -72,20 +128,17 @@ def test_product_contract_names_active_recovery_capability_families() -> None: assert "target isolation" in document.lower() or "restore-target" in document.lower() -def test_canonical_overlay_register_names_current_successor_without_draft_instruction() -> None: - """The durable register must name the live overlay and must not freeze Draft/Ready instructions.""" +def test_canonical_overlay_register_preserves_superseded_lineage_without_live_status() -> None: + """Historical documentation predecessors may be named without becoming active overlays.""" traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") assert "#214" in traceability - assert "superseded" in traceability.lower() assert "#226" in traceability - assert "not the landing vehicle" in traceability + assert "superseded" in traceability.lower() assert "keep it Draft" not in traceability assert "keep it Ready" not in traceability - assert "#225" in traceability - assert "ADR 0022" in traceability - assert "ADR 0021 collision" in traceability + assert "#225" not in traceability assert "#226" in fitness assert "superseded #214" in fitness assert "current canonical documentation landing vehicle" in traceability From d8c513ff367387499727e6d5cb4352a13f285f24 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:32:55 +0900 Subject: [PATCH 38/58] docs(product): align shipped recovery and secret policy truth --- docs/product/PRD.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 458f01688..943a9ef96 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -47,23 +47,23 @@ The product must let a qualified host: | Tenant-qualified durable lifecycle with forced RLS | IMPLEMENTED-ON-PROTECTED-MAIN | Tenant scope comes only from a trusted host authorization boundary, is validated before any tenant-client observation reservation, credential resolution, provider I/O, or lifecycle database I/O, and qualifies lifecycle identities, conflict targets, reads, and operational status indexing; direct arbitrary SQL remains outside the isolation guarantee. | | Durable resumable result checkpoint/CAS storage | IMPLEMENTED-ON-PROTECTED-MAIN | PostgreSQL supplies tenant-qualified durable checkpoint authority and conflict detection; this is not a distributed exactly-once claim. | | Redacted readiness reporting | IMPLEMENTED-ON-PROTECTED-MAIN | Public readiness evidence does not disclose arbitrary lower-layer diagnostic content. | -| Scheduler-independent bounded provider reconciliation primitive | IMPLEMENTED-ON-PROTECTED-MAIN | A host can submit a finite, validated candidate set for polling/retrieval through the existing bounded provider client; candidate discovery, scheduling, and cross-process lease ownership remain outside this primitive. | +| Scheduler-independent bounded provider reconciliation primitive | IMPLEMENTED-ON-PROTECTED-MAIN | A host can submit a finite, validated candidate set for polling/retrieval through the existing bounded provider client; candidate discovery and scheduling remain outside this primitive. | +| Cross-process reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | The tenant-qualified PostgreSQL session advisory-lock seam excludes concurrent workers for the same bounded identity while its session is alive. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | | Bounded PostgreSQL recovery receipt | IMPLEMENTED-ON-PROTECTED-MAIN | The package can encode/decode deterministic bounded content-free metadata that identifies package/source/PostgreSQL/schema/backup evidence without carrying credentials, DSNs, SQL, business payloads, or arbitrary diagnostics. | | Bounded PostgreSQL backup-artifact integrity evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from one private regular backup artifact under descriptor-pinned, no-follow, finite-work constraints without executing backup or restore. | | Bounded packaged PostgreSQL schema evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from the exact distributed `schema.sql` resource under a finite package-owned work budget without executing SQL or asserting live-cluster parity. | -| PostgreSQL logical backup execution | ACTIVE-PR | A `pg_dump` candidate exists in #208 but is not shipped; protected main must not be described as creating a restorable backup from the evidence primitives alone. | -| PostgreSQL logical restore execution | ACTIVE-PR | #212 is the unshipped active direct `pg_restore` successor. Predecessor #209 must not merge: its EOF-consumption check can report failure after a seekable custom-format restore has already committed. Caller-owned source trust, target isolation, libpq allowlist, transactional failure, metadata-fingerprint integrity, and permanent documentation remain unshipped. | +| PostgreSQL logical backup execution | ACTIVE-PR | A bounded `pg_dump` candidate exists in #208 but is not shipped; protected main must not be described as creating a restorable backup from the evidence primitives alone. | +| PostgreSQL logical restore execution | IMPLEMENTED-ON-PROTECTED-MAIN | The bounded direct `pg_restore` executor integrated through #212 accepts PostgreSQL custom-format random-access seek behavior and verifies archive metadata rather than requiring final EOF. Closed #209 remains defect evidence for the invalid EOF postcondition. The executor does not provide `pg_dump`, authenticate target isolation, prove post-restore catalog/application parity or PITR, or establish RPO/RTO/HA/DR. | | Recovery evidence binding | ACTIVE-PR | A host can compose one receipt from exact inspected schema and backup-artifact evidence objects. Bind-time composition is not inspection provenance, restorability, or target isolation. | | Live receipt re-inspection | ACTIVE-PR | A later verifier can re-hash current bytes and compare them to a stored receipt. Agreement is valid only at that inspection instant and does not remove TOCTOU or prove restore success. | | Post-restore catalog acceptance | ACTIVE-PR | Isolated restore acceptance must fail closed on same-name catalog decoys, tenant-qualified key order, uniqueness/constraint authority, access method, and live PostgreSQL query behavior. | | Physical/WAL/PITR recovery profile | ACTIVE-PR | A caller-owned physical recovery profile records intent and objectives only. It does not execute `pg_basebackup`, archive or replay WAL, or establish a package RPO/RTO. | | Restore-target isolation | PARTIAL | Distinct configuration labels are not authenticated cluster isolation. End-to-end acceptance must prove the restore target is a different cluster before production safety can be claimed. | -| End-to-end PostgreSQL recovery readiness | PARTIAL | Integrated evidence primitives do not yet prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | +| End-to-end PostgreSQL recovery readiness | PARTIAL | Integrated evidence primitives and the bounded logical restore executor do not yet prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | | Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative before it can become product truth. | -| Cross-process reconciliation single-flight | ACTIVE-PR | Concurrent workers must not race the same tenant/provider identity; merge eligibility remains governed by live repository policy. | | Existing-volume legacy `http` / `pg_cron` retirement | ACTIVE-PR | Existing deployments need fail-closed, reversible migration evidence before compatibility packages can be removed. | | First-class OpenTelemetry installation extra | ACTIVE-PR | Ordinary installs must remain telemetry-dependency-free; the optional package graph must be locked and reproducible. | -| Autonomous package-owned reconciliation worker with crash/restart completion semantics | PARTIAL | Protected main has reconciliation and durable state primitives, but does not yet claim a complete package scheduler/worker control plane. | +| Autonomous package-owned reconciliation worker with crash/restart completion semantics | PARTIAL | Protected main has reconciliation, transient single-flight, and durable state primitives, but does not yet claim a complete package scheduler/worker control plane. | | Durable result application coupled to checkpoint advancement | PARTIAL | Existing checkpoint and retrieval primitives must not be described as end-to-end exactly-once result application until a reviewed coupling contract is integrated. | ## Functional requirements @@ -90,7 +90,7 @@ Protected-main acceptance authority for these invariants is deterministic: `test ### FR-4: Reconciliation and provider-effect recovery -Reconciliation shall be finite, deterministic, payload-free in its operational evidence, and use the same validated provider client boundary as normal operations. Candidate discovery, concurrency control, scheduling, and result-application semantics must be explicit capabilities rather than inferred from polling code. Provider-success/database-failure cases must remain observable recovery states rather than being rewritten as if the provider effect never occurred. +Reconciliation shall be finite, deterministic, payload-free in its operational evidence, and use the same validated provider client boundary as normal operations. Candidate discovery, scheduling, and result-application semantics must be explicit capabilities rather than inferred from polling code. Protected main provides tenant-qualified transient session advisory single-flight for the bounded reconciliation identity; that exclusion is not a durable lease, scheduler, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. Provider-success/database-failure cases must remain observable recovery states rather than being rewritten as if the provider effect never occurred. ### FR-5: Persistence integrity and PostgreSQL recovery evidence @@ -98,11 +98,11 @@ Package-owned database rows shall use descriptive two-or-more-word `snake_case` Protected main shall provide bounded, content-free recovery evidence without overstating its guarantee. `PostgresRecoveryReceipt` identifies one evidence set using package version, exact source commit, PostgreSQL major version, schema SHA-256, a reviewed backup-method vocabulary, backup-artifact SHA-256 and size, and bounded start/completion epochs. Backup-artifact inspection shall pin directory/file identity, reject symlink traversal and unsafe file shapes, remain within a caller-visible finite hashing budget, and return only hash/size evidence. Packaged-schema inspection shall stream the exact distributed `schema.sql` under a finite package-owned budget and return only hash/size evidence. Malformed, ambiguous, duplicate-member, hostile-subclass, oversized, mutating, unreadable, or cleanup-failing evidence shall fail closed through fixed package diagnostics. -These primitives do not execute `pg_dump` or `pg_restore`, persist backup bytes, prove backup provenance or restorability, prove a live-cluster schema matches the package, authorize a tenant/operator, manage encryption keys, manage WAL, establish PITR, or prove RPO/RTO/HA/DR/compliance. Executable logical backup/restore and isolated-restore acceptance remain separate governed capabilities. A future direct restore must make caller-owned source-superuser trust, target isolation, allowed libpq credential/service environment, transaction rollback behavior, and post-restore acceptance explicit before it can become protected-main truth. +Those evidence primitives do not themselves execute backup or restore, persist backup bytes, prove backup provenance or restorability, prove a live-cluster schema matches the package, authorize a tenant/operator, manage encryption keys, manage WAL, establish PITR, or prove RPO/RTO/HA/DR/compliance. Protected main separately contains the bounded custom-format logical restore executor integrated through #212. That executor preserves caller-owned source-superuser trust and a constrained libpq environment and uses transactional failure plus archive metadata checks, but it does not create a backup, authenticate restore-target separation, establish post-restore catalog/application readiness, manage keys/WAL, or prove PITR/RPO/RTO/HA/DR. Logical `pg_dump`, authenticated target isolation, application-readiness acceptance, and end-to-end recovery remain separately governed capabilities. ### FR-6: Configuration and secrets -PostgreSQL-backed configuration and encrypted-secret support remain available for standalone use. Environment variables are bootstrap transport only where explicitly documented. Embedding hosts may inject credential providers without changing provider protocol semantics. The package shall not invent an external secret-management product dependency. +PostgreSQL-backed configuration and secret storage remain available for standalone use. Fernet encryption is optional on protected main; `SecretStore(require_encryption=False)` permits the explicit compatibility mode that stores base64-obfuscated rows with `is_encrypted = FALSE`. Deployments may opt into Fernet with `require_encryption=True`, but mandatory encryption, historical compatibility-row migration, key rotation/recovery, and external key custody are not shipped guarantees. Environment variables are bootstrap transport only where explicitly documented. Embedding hosts may inject credential providers without changing provider protocol semantics. The package shall not invent an external secret-management product dependency. ### FR-7: Observability and diagnostics From 3490a81b629d93aceb7dfb29783fa0620fc68456 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:33:39 +0900 Subject: [PATCH 39/58] docs(technical): repair merged recovery capability status --- docs/product/TRD.md | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/docs/product/TRD.md b/docs/product/TRD.md index 8b82746fa..33c57bf5b 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -8,7 +8,7 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A ## System boundary -`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It may run standalone or be embedded by another service. The package owns batch preparation, package persistence, validated provider Batch API access, durable lifecycle projection, resumable checkpoint storage, bounded reconciliation primitives, and bounded content-free PostgreSQL recovery-evidence primitives. It does not own host authentication, business authorization, ingress/WAF, infrastructure TLS policy, external secret-manager choice, global OpenTelemetry configuration, backup-storage infrastructure, WAL/archive infrastructure, or a cross-system distributed transaction. +`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It may run standalone or be embedded by another service. The package owns batch preparation, package persistence, validated provider Batch API access, durable lifecycle projection, resumable checkpoint storage, bounded reconciliation primitives, tenant-qualified transient reconciliation single-flight, a bounded direct logical-restore executor, and bounded content-free PostgreSQL recovery-evidence primitives. It does not own host authentication, business authorization, ingress/WAF, infrastructure TLS policy, external secret-manager choice, global OpenTelemetry configuration, backup-storage infrastructure, WAL/archive infrastructure, or a cross-system distributed transaction. ## Component contract @@ -20,18 +20,20 @@ Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **A | `durable_client.py` | compose provider operations with durable lifecycle ordering/persistence; preserve `DurableBatchAPIClient` source compatibility, its four-argument `LifecycleRecorder(postgres_dsn, endpoint_alias, provider_batch, observation_order)` seam, and default `standalone` database scope; provide a distinct tenant-qualified recorder seam | authenticating or authorizing host tenants, deriving tenant authority from provider data | | `db.py` | schema application and parameterized persistence/read helpers, including tenant-qualified lifecycle context, conflict identity, and exact-row lookup | database-side provider networking, authenticating tenant callers | | `checkpoint_store.py` | tenant-qualified PostgreSQL checkpoint/CAS operations and conflict semantics | distributed exactly-once claims | -| `reconciliation.py` | finite host-selected polling/retrieval pass using the existing validated client surface | candidate discovery, scheduling, cross-process leasing | +| `reconciliation.py` | finite host-selected polling/retrieval pass using the existing validated client surface | candidate discovery and scheduling | +| `reconciliation_single_flight.py` | tenant-qualified transient PostgreSQL session advisory-lock exclusion for one bounded reconciliation identity | durable lease, scheduler, result-application transaction, terminal-work retirement, distributed exactly-once | | `postgres_recovery_receipt.py` | encode/decode one deterministic bounded content-free PostgreSQL recovery evidence receipt | proving backup success/restorability, authenticating operators, carrying DSNs/credentials/business content | | `postgres_backup_evidence.py` | derive SHA-256 and byte-size evidence from one private regular backup artifact through descriptor-pinned no-follow traversal and finite work | executing `pg_dump`/`pg_restore`, persisting backup bytes, proving restore semantics | | `postgres_schema_evidence.py` | derive SHA-256 and byte-size evidence from the exact distributed `pg_llm_batch/schema.sql` resource under a finite package-owned budget | executing SQL, proving live-cluster parity or migration currency | -| `config.py` | PostgreSQL-backed configuration and encrypted secret storage for standalone composition | prescribing an embedding host's external secret manager | +| `postgres_logical_restore.py` | execute the bounded reviewed custom-format `pg_restore` path using caller-owned source trust, constrained libpq environment, transactional failure handling, and archive metadata verification | creating backups, authenticating target isolation, proving post-restore catalog/application readiness, PITR, RPO/RTO/HA/DR | +| `config.py` | PostgreSQL-backed configuration and secret storage with optional Fernet plus an explicit compatibility mode | claiming mandatory encryption, historical-row migration, key rotation/recovery, external key custody, or prescribing an embedding host's external secret manager | | `observability.py` | opt-in bounded traces/metrics around reviewed operations | configuring global SDK/exporter/resource policy | | `health.py` | readiness aggregation and redacted public health response | general-purpose web serving or arbitrary diagnostic reflection | | `cli.py` | standalone operator composition and bounded input surfaces | higher-level workflow orchestration | The protected-main validation authority for the `durable_client.py` compatibility row is `pg_llm_batch/durable_client.py`, `tests/test_tenant_durable_client.py`, and `tests/test_tenant_lifecycle_persistence.py`: the tests prove construction-time tenant rejection before downstream effects, exact four-argument standalone recorder invocation, explicit `standalone` persistence/read delegation, and tenant-qualified lifecycle persistence/read identities. -The protected-main validation authority for recovery evidence is the three recovery modules plus their focused test suites. Historical merged PRs #205, #206, and #207 are integration evidence, not runtime authority. `docs/TRACEABILITY.md` remains the canonical status map for the distinction between integrated evidence primitives and active backup/restore execution candidates. +The protected-main validation authority for recovery evidence is the three recovery-evidence modules plus their focused test suites. Historical merged PRs #205, #206, and #207 are integration evidence, not runtime authority. The bounded logical-restore executor integrated through #212 is a separate execution capability with narrower authority than end-to-end recovery readiness. `docs/TRACEABILITY.md` remains the canonical status map for the distinction between integrated evidence/restore primitives and active backup, target-authentication, and application-readiness candidates. ## Runtime architecture @@ -80,9 +82,9 @@ Checkpoint counters, offsets, and identities must validate before mutation. Conf Protected main supplies a scheduler-independent `reconcile_batch_candidates(...)` primitive. A host supplies candidate identities and a finite `max_jobs` budget. The primitive validates candidates, bounds scanning/work, polls through the validated provider client, retrieves completed jobs through that same client, and returns payload-free finite outcome/error categories. -The host still owns candidate discovery, tenant authorization, scheduling, and cross-process concurrency. Durable candidate discovery and tenant-qualified advisory single-flight are **ACTIVE-PR** surfaces; neither is treated as shipped until protected-main integration. Package-owned autonomous scheduling, crash/restart completion semantics, terminal-work retirement after durable result application, and an end-to-end exactly-once worker remain **PARTIAL** or **PLANNED** capabilities. +The host still owns candidate discovery, tenant authorization, and scheduling. Durable candidate discovery remains an **ACTIVE-PR** surface. The tenant-qualified session advisory single-flight is protected-main behavior: it provides transient, session-lifetime exclusion for one bounded reconciliation identity and releases with session/process loss. It is not a durable lease, scheduler, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. Package-owned autonomous scheduling, crash/restart completion semantics, terminal-work retirement after durable result application, and an end-to-end exactly-once worker remain **PARTIAL** or **PLANNED** capabilities. -### PostgreSQL recovery evidence +### PostgreSQL recovery evidence and logical restore Protected main supplies three deliberately non-executing recovery-evidence primitives. @@ -90,11 +92,11 @@ Protected main supplies three deliberately non-executing recovery-evidence primi 2. `inspect_postgres_backup_artifact(...)` traverses path components through pinned directory descriptors with no-follow semantics, rejects `..`, symlinked parents/final components, non-regular/empty/oversized files and unsafe link counts/permissions as defined by the implementation contract, hashes under an explicit finite maximum-size work budget, bounds each read request by remaining budget, compares descriptor identity/metadata before and after hashing, and treats cleanup failures as bounded evidence without masking an already-selected primary error. 3. `inspect_postgres_schema()` streams the exact distributed `pg_llm_batch/schema.sql` resource through SHA-256 under a finite package-owned work budget and returns only SHA-256 plus byte size. Missing, unreadable, empty, oversized, malformed-chunk, hostile-subclass, or cleanup-failing resources fail closed through fixed content-free diagnostics. -These primitives do not execute SQL or database mutation. They do not prove the backup command succeeded, prove backup provenance beyond caller-controlled receipt fields, prove restorability, prove a live database matches the packaged schema, provide target isolation, manage keys/secrets, manage physical/WAL/PITR infrastructure, or establish RPO/RTO/HA/DR/compliance. Those are separate acceptance domains. +These evidence primitives do not execute SQL or database mutation. They do not prove a backup command succeeded, prove backup provenance beyond caller-controlled receipt fields, prove restorability, prove a live database matches the packaged schema, provide target isolation, manage keys/secrets, manage physical/WAL/PITR infrastructure, or establish RPO/RTO/HA/DR/compliance. Those are separate acceptance domains. -Logical `pg_dump` execution in #208 remains **ACTIVE-PR**. Direct `pg_restore` execution is also **ACTIVE-PR**, and #212 is the unshipped active successor. Predecessor #209 is not a merge path: its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after `--single-transaction` has already committed. Until integration, no protected-main technical contract may rely on those executors. The #212 successor additionally requires permanent operator/architecture/ADR/doctoring/CHANGELOG coverage for caller-owned source-superuser trust, the non-authorizing service selector, permitted inherited libpq variables, single-transaction rollback behavior, target isolation, metadata-fingerprint verification, and post-restore acceptance before it may be represented as shipped. +Logical `pg_dump` execution in #208 remains **ACTIVE-PR**. Direct `pg_restore` execution is **IMPLEMENTED-ON-PROTECTED-MAIN** through merged #212. The integrated executor deliberately accepts PostgreSQL custom-format random-access seek positions and verifies archive metadata instead of requiring final descriptor EOF. Closed predecessor #209 remains historical defect evidence because its EOF-consumption postcondition could report failure after `--single-transaction` had already committed. The integrated executor keeps caller-owned source-superuser trust, a constrained libpq environment, single-transaction failure semantics, and metadata-fingerprint checks explicit; it does not provide `pg_dump`, authenticate that the target is a different cluster, prove post-restore catalog/application readiness, manage external keys or WAL, or establish PITR/RPO/RTO/HA/DR. -Active recovery work also includes evidence binding, live receipt re-inspection, post-restore catalog acceptance, a caller-owned physical/WAL/PITR profile, and restore-target isolation. Those are capability families, not shipped executors. Distinct service-name labels are not authenticated cluster isolation. +Active recovery work still includes executable logical backup, evidence binding, live receipt re-inspection, post-restore catalog/application acceptance, a caller-owned physical/WAL/PITR profile, and authenticated restore-target isolation. #296 is an active application-readiness candidate stacked behind the permanent live-PostgreSQL CI lane in #341; neither branch is protected-main truth. Those are capability families beyond the integrated restore executor, not evidence that end-to-end recovery is shipped. Distinct service-name labels are not authenticated cluster isolation. ## Persistence requirements @@ -118,9 +120,9 @@ Recovery evidence is identity/integrity metadata, not a second persistence autho ### Secrets -Standalone provider configuration and encrypted secrets are PostgreSQL-backed. Environment variables are limited to explicitly documented bootstrap transport such as the database DSN and optional encryption key. CLI secret entry uses no-echo prompting or bounded standard input rather than plaintext process arguments. Embedding hosts may supply another credential provider through the supported seam. +Standalone provider configuration and secret storage are PostgreSQL-backed. Fernet is optional on protected main. With `SecretStore(require_encryption=False)`, the compatibility path can persist base64-obfuscated rows with `is_encrypted = FALSE`; callers that require Fernet must explicitly select `require_encryption=True` and provide usable key material. Mandatory encryption, migration of historical compatibility rows, key rotation/recovery, and external key custody are not protected-main guarantees. Environment variables are limited to explicitly documented bootstrap transport such as the database DSN and optional Fernet key. CLI secret entry uses no-echo prompting or bounded standard input rather than plaintext process arguments. Embedding hosts may supply another credential provider through the supported seam. -Recovery evidence must not carry DSNs, passwords, Fernet keys, prompts/results, ciphertext, arbitrary SQL, provider payloads, paths where not required by the callable interface, dynamic exception names, or reflected lower-layer diagnostics. A future backup/restore executor must isolate credentials from process arguments and ambient environment according to its separately reviewed contract. +Recovery evidence must not carry DSNs, passwords, Fernet keys, prompts/results, ciphertext, arbitrary SQL, provider payloads, paths where not required by the callable interface, dynamic exception names, or reflected lower-layer diagnostics. A backup/restore executor must isolate credentials from process arguments and ambient environment according to its reviewed contract. ### Authorized content fidelity @@ -142,7 +144,7 @@ Provider URLs, statuses, IDs, headers, JSON, JSONL, retry guidance, and metadata ### Recovery authority boundary -A backup artifact, receipt, service selector, schema hash, or backup method string is not authorization to read, write, restore, or replace a database. Authentication, authorization, target isolation, backup custody, key custody, destructive-operation approval, and recovery-objective ownership remain external until a separately integrated contract explicitly supplies and verifies them. Recovery evidence must never be used to infer those authorities. +A backup artifact, receipt, service selector, schema hash, or backup method string is not authorization to read, write, restore, or replace a database. Authentication, authorization, target isolation, backup custody, key custody, destructive-operation approval, and recovery-objective ownership remain external unless an integrated contract explicitly supplies and verifies them. The protected logical-restore executor does not convert a service selector or archive into authenticated target-isolation authority. Recovery evidence must never be used to infer those authorities. ## Observability requirements @@ -156,11 +158,11 @@ Readiness covers the required PostgreSQL/tokenizer/configuration boundary and re Operational migrations require backup/preflight/acceptance/recovery documentation before release. A recovery instruction must preserve package and operator-owned state; destructive `CASCADE`, hidden history rewrite, or deletion of unknown operator objects is not an acceptable shortcut. -A recovery drill must distinguish artifact identity from restore acceptance. At minimum, acceptance criteria for a future end-to-end logical restore must address exact schema/package identity, required schema/RLS/constraint/extension behavior, migration compatibility, intended target isolation, credential/key availability, and rollback/recovery behavior. Physical/WAL/PITR drills additionally require their own timeline/target and infrastructure acceptance criteria. No repository evidence should claim universal RPO/RTO/HA/DR without an explicit measured deployment objective. +A recovery drill must distinguish artifact identity and successful command execution from restore acceptance. End-to-end acceptance must address exact schema/package identity, required schema/RLS/constraint/extension behavior, migration compatibility, authenticated target isolation, credential/key availability, and rollback/recovery behavior. Physical/WAL/PITR drills additionally require their own timeline/target and infrastructure acceptance criteria. No repository evidence should claim universal RPO/RTO/HA/DR without an explicit measured deployment objective. ## Concurrency requirements -Batch preparation uses database coordination/transactionality appropriate to its package-owned state. Durable lifecycle writes use explicit ordering/conflict semantics. Any cross-process reconciliation exclusion must be tenant-qualified, non-blocking or finitely bounded, exception-safe, and clear about whether it is transient session state or durable lease state. Session advisory locking must never be promoted into a durable lease or distributed exactly-once claim. +Batch preparation uses database coordination/transactionality appropriate to its package-owned state. Durable lifecycle writes use explicit ordering/conflict semantics. The protected reconciliation single-flight seam is tenant-qualified, non-blocking, exception-safe, and session-scoped. Process/session loss releases it. Session advisory locking must never be promoted into a durable lease, scheduler, result-application transaction, terminal-work-retirement authority, or distributed exactly-once claim. Recovery-evidence file inspection must remain finite and fail closed under concurrent mutation. A successful hash/size result is valid only for the descriptor identity/metadata contract that was revalidated by the implementation; it is not a lock or lease over external backup infrastructure. @@ -176,6 +178,7 @@ Every source defect follows realistic RED → narrow fix → GREEN → focused/f - package and container installation/health validation; - migration idempotency and rollback/recovery coverage where applicable; - recovery-evidence tests for exact primitive types, duplicate/unknown metadata, finite work, descriptor/path boundaries, concurrent mutation, cleanup failure, and content-free diagnostics; +- logical-restore tests for custom-format seek semantics, archive metadata verification, constrained environment, and transactional failure boundaries; - confidentiality regressions that inspect full exception/traceback surfaces when relevant; - security scanning and SAST; - dependency-lock and packaging reproducibility; @@ -187,10 +190,10 @@ Queued, pending, skipped, cancelled, absent, neutral, stale, predecessor-head, s A release may originate only from the exact integrated protected head after all live required quality, security, review, migration, rollback/recovery, operational, packaging, provenance, and release-acceptance gates are terminal-success. Versioning and CHANGELOG updates are followed by publication and artifact verification. Repository control evidence may support SOC 2 / CSAP readiness but must not be represented as certification. -The presence of recovery-evidence primitives does not make a release recovery-ready for a deployment. A release or operator contract that claims restore/PITR/RPO/RTO/HA/DR readiness must cite the exact integrated executor/drill/acceptance evidence for that deployment objective rather than extrapolating from hash/receipt modules. +The presence of recovery-evidence primitives or the bounded logical-restore executor does not make a release end-to-end recovery-ready for a deployment. A release or operator contract that claims isolated restore/PITR/RPO/RTO/HA/DR readiness must cite the exact integrated drill/acceptance evidence for that deployment objective rather than extrapolating from hash/receipt or command-execution modules. ## Documentation requirements -Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. +Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs or exact commit SHAs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. -Direct-SQL or rollback authority introduced by a future backup/restore executor requires coordinated permanent README, operator, architecture, ADR (or explicit accepted amendment/no-new-decision rationale), doctoring/reference, and CHANGELOG coverage. Active PR source may document its own callable boundary, but canonical docs must not represent it as shipped before integration. +Protected logical-restore authority must keep caller-owned source trust, target-isolation limits, allowed libpq environment, transactional failure behavior, archive metadata verification, and post-restore acceptance gaps explicit. Any future change that broadens those authorities requires coordinated permanent operator/architecture/ADR/doctoring/CHANGELOG coverage through the appropriate live documentation owners. From 430c0c6ff351b4a69f0d4fe77797bfa204b558a6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:34:37 +0900 Subject: [PATCH 40/58] docs: repair canonical documentation fitness truth --- docs/DOCUMENTATION_FITNESS.md | 97 ++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 08a6e2d72..2b2b306e0 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -2,66 +2,67 @@ ## Authority and status model -This inventory evaluates the documentation graph against the exact protected-main tree `d2f1e32271910a6db98a0757d67194ddadca4566`. It does not promote pull-request content into shipped truth. The canonical status vocabulary is shared with `docs/product/PRD.md` and `docs/product/TRD.md`: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. +This inventory evaluates the canonical documentation graph against the live protected-default-branch behavior. It deliberately does not freeze an exact protected commit SHA: exact heads belong in PR and review evidence, while durable documentation records capability contracts. Pull-request content remains work-in-progress until normal protected-branch integration. -A document is *fit* only when it states the correct authority boundary, is consistent with the protected-main code/schema/tests it describes, avoids transferring predecessor or active-branch evidence into shipped claims, and gives an operator or reviewer enough information to use, verify, recover, or reject the relevant behavior safely. +The canonical status vocabulary is shared with `docs/product/PRD.md` and `docs/product/TRD.md`: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. -The tenant lifecycle material in this canonical cohort is a reconstruction of already integrated protected-main behavior, not a new runtime tenant/RLS/migration contract. Companion-document verification against protected main confirms the same contract is already present in the public `README.md`, root `ARCHITECTURE.md`, topic operator guide `docs/remote-batch-lifecycle.md`, accepted ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md`. Those authorities already cover trusted tenant identity, `NOSUPERUSER NOBYPASSRLS`, transaction-local/forced RLS, direct-SQL limits, legacy-to-`standalone` migration, and rollback constraints. The canonical PRD/TRD therefore may cite that existing evidence without rewriting those protected-main files or racing PR #184's separate legacy-extension-retirement documentation lane. +A document is fit only when it agrees with protected code/schema/tests, preserves non-guarantees, keeps active-branch evidence out of shipped claims, and tells an operator or reviewer enough to use, verify, recover, or reject the relevant behavior safely. -Protected main now also contains the bounded recovery-evidence primitives integrated by #205, #206, and #207: content-free PostgreSQL recovery receipts, descriptor-pinned backup-artifact hash/size evidence, and packaged-schema hash/size evidence. These are evidence primitives only. They do not make executable logical backup/restore, isolated restore acceptance, WAL/PITR, key/config custody, or any RPO/RTO/HA/DR objective shipped. #208 remains the active logical-backup candidate. Direct-restore predecessor #209 is not mergeable as a product contract because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives; #212 is the unshipped active successor. Adjacent unshipped recovery families are evidence binding, live receipt re-inspection, post-restore catalog acceptance, a caller-owned physical/WAL/PITR profile, and restore-target isolation. Issue #204 remains the end-to-end recovery authority. +The tenant lifecycle material reconstructs protected behavior rather than creating a new tenant/RLS contract. `README.md`, `ARCHITECTURE.md`, `docs/remote-batch-lifecycle.md`, ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md` remain companion authorities for trusted tenant selection, `NOSUPERUSER NOBYPASSRLS`, transaction-local forced RLS, arbitrary-SQL limits, legacy-to-`standalone` migration, and rollback constraints. + +Protected main also contains bounded recovery-evidence primitives integrated through #205, #206, and #207, the tenant-qualified session advisory single-flight seam integrated through #191, and the bounded direct custom-format logical restore executor integrated through #212. These are deliberately narrower than end-to-end recovery. Logical `pg_dump`, evidence binding/re-inspection, authenticated target isolation, post-restore application readiness, physical/WAL/PITR execution, external key custody, and measured RPO/RTO/HA/DR remain separate capability families. ## Current fitness matrix | Documentation surface | Status | Fitness assessment | Required next action | | --- | --- | --- | --- | -| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Useful public entry point; protected-main tenant lifecycle guidance already reflects trusted tenant scope and standalone compatibility. It is not the sole product/architecture authority and must not absorb transient PR/check state. The newly integrated recovery-evidence primitives are not yet a complete operator recovery procedure. | Keep beginner-readable; add shipped recovery semantics only when adjacent writer ownership permits and do not present evidence primitives as a restorable-backup guarantee. | -| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers standalone/embedded deployment, durable tenancy/RLS, migration boundary, direct-SQL trust limits, rollback considerations, interoperability, and verification, but does not by itself form a complete system/UML/data model. Recovery evidence has advanced on protected main without establishing end-to-end recovery semantics. | Keep architectural contracts synchronized; add separate UML/data views rather than overloading this file, and update recovery architecture only through a non-conflicting governed documentation lane. | -| `docs/product/PRD.md` | ACTIVE-PR | First current-main-compatible canonical product contract. It explicitly separates shipped, active, partial, planned, and superseded capability states, cites deterministic protected-main tenant/standalone acceptance authority, records the `set_config` capability/trust boundary, and treats #212 as the unshipped active restore successor while freezing predecessor #209. | Keep executable backup/restore, evidence binding, catalog acceptance, physical/PITR profiling, restore-target isolation, and end-to-end recovery PARTIAL/ACTIVE-PR; refresh only after protected-main integration. | -| `docs/product/TRD.md` | ACTIVE-PR | First current-main-compatible technical requirements authority; component boundaries, tenant pre-effect validation, standalone recorder compatibility, #209/#212 restore overlay separation, and release/testing invariants are explicit. | Keep the bounded recovery-evidence technical boundary without promoting #208/#212; do not restore predecessor #209 to any implied merge path. | -| ADR set (`0002`, `0003`, `0004`, `0006`, `0007`, `0015`) | IMPLEMENTED-ON-PROTECTED-MAIN | Material tenant, release-evidence, result-checkpoint, and retry decisions exist. ADR 0002 already records trusted tenant identity, explicit `standalone` compatibility, RLS/direct-SQL role boundaries, migration, and rollback. Individual ADR status remains authoritative: `0003` and `0004` are still `Proposed`, while the accepted records keep their own bounded decision status. No protected-main ADR is inferred for the newly integrated recovery-evidence primitives merely because code exists. | Preserve those record-local statuses; do not infer architectural acceptance from related implementation. #212 proposes ADR 0016 for custom-format restore seek semantics, but that record is not protected-main authority until integrated. | -| `docs/adr/README.md` | ACTIVE-PR | This canonical branch supplies the missing protected-main ADR navigation/status index, explains numbering gaps, separates ADR decision status from implementation status, and forbids implicit supersession. | Keep the referenced protected-main tree current; do not list #212's proposed ADR 0016 as a protected-main decision before integration. | -| `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded provider result streaming/checkpoint behavior; checkpoint persistence has a separate accepted ADR. | Update only when the integrated result-application contract changes the operator-facing boundary. | -| `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Serves as the topic-specific operator authority for durable lifecycle tenancy. It already specifies trusted scope selection, pre-effect validation, four-argument standalone recorder compatibility, tenant-qualified identity/conflict/read behavior, forced RLS/application-role limits, migration, direct-SQL impact, rollback, recovery, and deterministic verification. | Keep synchronized with tenant/RLS and lifecycle migrations; do not duplicate this contract into a competing operator file. | -| `docs/doctoring/tenant-scoped-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Supporting evidence independently records pre-effect validation, explicit standalone compatibility, database role/RLS limits, migration and rollback, plus current primary references. | Keep supporting references current; do not promote doctoring into the sole product authority. | -| `CHANGELOG.md` tenant lifecycle entry | IMPLEMENTED-ON-PROTECTED-MAIN | The protected-main Unreleased section already records tenant-scoped durable lifecycle, forced default-deny RLS, standalone compatibility, and the atomic tenant migration fix. | Change only when integrated shipped behavior changes; do not log active-PR claims as shipped. | -| Topic-specific doctoring/reference docs | IMPLEMENTED-ON-PROTECTED-MAIN | Useful deep evidence exists, but doctoring material is supporting evidence, not the canonical product-status authority. | Keep primary-reference and APA-style citations current where material. | -| PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py` are integrated protected-main primitives with focused tests. They produce bounded content-free metadata/hash/size evidence without executing SQL or claiming cluster parity. | Keep the evidence/guarantee distinction explicit. Do not claim restorable backup, isolated restore, PITR, RPO/RTO/HA/DR, or compliance readiness from these primitives alone. | -| PostgreSQL logical backup/restore execution | ACTIVE-PR | #208 proposes bounded `pg_dump` execution. #209's direct-restore predecessor has a verified false-failure defect because a seekable custom-format `pg_restore` need not leave the shared descriptor at EOF after successful transactional restore. #212 is the unshipped active successor: it removes that invalid EOF postcondition while preserving metadata-fingerprint verification and owns the permanent README/architecture/ADR/doctoring/CHANGELOG restore-contract documentation. None is protected-main truth. | Freeze #209 rather than merge or patch it in parallel; do not race #208/#212 active writers. Promote only the unchanged successor after exact-head gates, valid findings, required documentation, qualifying approval, and protected-main integration. | -| Recovery evidence binding and live re-inspection | ACTIVE-PR | Adjacent overlays compose receipts from exact inspected evidence and later re-hash current bytes. Agreement is integrity at one inspection instant, not provenance, restorability, or target isolation. | Keep bind/re-inspect seams unshipped until exact-head gates and qualifying approval land; do not treat object construction as live inspection. | -| Post-restore catalog acceptance | ACTIVE-PR | Catalog acceptance must prove live PostgreSQL query behavior against same-name index decoys, tenant-qualified key order, uniqueness/constraint authority, and access method. | Do not promote catalog greps of SQL text into shipped acceptance. | -| Physical/WAL/PITR recovery profile | ACTIVE-PR | A caller-owned profile records physical recovery intent and objectives. It does not execute `pg_basebackup` or WAL replay. | Keep RPO/RTO language as caller-owned intent, not a package capability. | -| Restore-target isolation | PARTIAL | Distinct libpq service names are a configuration-label check. They do not authenticate that two aliases resolve to different clusters. | Require authenticated target proof before claiming production restore safety. | -| Existing-volume legacy PostgreSQL retirement operability material | ACTIVE-PR | PR #184 contains bounded migration/operator documentation for retiring legacy `http` / `pg_cron`; it is a different contract from the already-shipped tenant lifecycle migration and is not protected-main truth. | Do not duplicate or rewrite #184-owned README/architecture/operability/retirement surfaces here. | -| OpenTelemetry installation/operation documentation | ACTIVE-PR | PR #175 owns the packaging-extra lane; protected main must not imply the optional dependency lock is integrated. | Promote only after exact lock/materialization and release gates are proven. | -| Durable reconciliation candidate/single-flight documentation | ACTIVE-PR | PRs #190 and #191 own current reconciliation additions; protected main has only the scheduler-independent bounded reconciliation primitive. | Update canonical shipped status only after each exact head merges. | -| Atomic durable result application | ACTIVE-PR | PR #194 contains a current-main-compatible test-first caller-owned PostgreSQL transaction seam for applying one validated streamed result/error record together with checkpoint advancement. It remains an active overlay; FR-4/end-to-end result application stays `PARTIAL` on protected main, and neither this row nor the TRD content-fidelity invariant promotes #194 into shipped truth. | Keep FR-4 and `docs/TRACEABILITY.md` as the validation/status authority until #194 integrates normally; preserve the explicit same-transaction and no-distributed-exactly-once boundary. | -| Runtime config/schema provisioning separation | ACTIVE-PR | PR #193 is a current-main least-privilege candidate: runtime constructors move away from DDL/default seeding, validate the search-path-resolved base-table shape and current-role read capability through bounded catalog probes, and retain provisioning/default seeding at the explicit schema boundary. #210 is the unshipped operator-contract successor that aligns public install/README/architecture/CHANGELOG wording with that runtime fail-closed Fernet/provisioning seam. Neither is shipped until normal governance integrates the unchanged successor. | Preserve the trusted-search-path/non-ownership caveat; treat #210 as the public-contract overlay rather than a second runtime rewrite; reacquire exact-head checks/review after every push; do not transfer predecessor or earlier-head evidence. | -| Canonical traceability | ACTIVE-PR | This overlay is the current canonical-documentation successor to superseded #214 and to #226, which still froze a transient pull-request state instruction. It establishes the first current-main-compatible requirements-to-evidence map and distinguishes integrated recovery evidence from active executable candidates and unsafe predecessor heads. | Maintain `docs/TRACEABILITY.md` using stable code/test/doc authorities, not run IDs; record #212 only as an active overlay until integration. | -| Threat model | ACTIVE-PR | This overlay adds `docs/THREAT_MODEL.md` with assets, trust boundaries, attacker preconditions, package mitigations, residual risk, operator next actions, and APA 7th NIST citations. It is not protected-main truth until this documentation lane integrates, and it does not claim SOC 2/CSAP certification. | Promote only after exact-head gates and merge; keep residual-risk language if a later executor or worker lands. | -| Data governance | ACTIVE-PR | This overlay adds `docs/DATA_GOVERNANCE.md` mapping data classes, owners, tenant authority, retention/deletion limits, and the no-blanket-masking privacy boundary with APA 7th citations. | Promote only after exact-head gates and merge; do not treat this file as a records-program certification. | -| UML/component/sequence views | ACTIVE-PR | This overlay adds `docs/uml/component-and-sequence.md` showing standalone/embedded composition and the tenant-validation sequence. ACTIVE-PR executors stay off the shipped component list. | Update only when a protected-main component or seam actually changes. | -| ERD / schema model | ACTIVE-PR | This overlay adds `docs/erd/package-owned-schema.md` from packaged `schema.sql` plus migration-owned `llm_result_stream_checkpoints`. SQL remains stronger authority. Active recovery/reconciliation tables stay off the diagram until they exist on protected main. | Refresh the diagram only after a packaged table or migration-owned identity actually changes. | -| General standalone operator guide | PARTIAL | Protected main has strong operational guidance across `README.md` and topic authorities such as `docs/remote-batch-lifecycle.md`; there is no single omnibus protected-main `docs/OPERABILITY.md`. This is a navigation/consolidation gap, not absence of tenant lifecycle operator guidance. | Establish one general operator index/authority only after checking adjacent writers; do not race #184 or #212 documentation surfaces. | -| Release governance | PARTIAL | Release-evidence ADRs/tests/workflows are strong, but the canonical graph lacks one concise protected-main release/operator authority tying versioning, SBOM, provenance, artifact identity, rollback/recovery, and publication verification together. | Add a stable release contract after checking active release writers; do not copy workflow-run IDs. | -| Licensing / third-party notices | PARTIAL | Apache-2.0 source headers and repository licensing exist, but acquisition diligence should explicitly trace package license, dependency/SBOM evidence, and third-party notice process. | Evaluate a concise licensing/compliance evidence index without claiming legal certification. | +| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Public entry point for standalone/embedded operation and tenant lifecycle. It is not the sole architecture or recovery authority. | Change only through its live owner when protected behavior changes. | +| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers principal runtime boundaries but is separately owned by the active root-documentation lane. | Keep #229 out of this path; reconcile through the current owner. | +| `docs/product/PRD.md` | ACTIVE-PR | Canonical product contract now records #191 single-flight and #212 logical restore at their integrated bounded scope, while leaving broader worker/recovery guarantees unshipped. | Revalidate after each protected integration before changing status. | +| `docs/product/TRD.md` | ACTIVE-PR | Technical contract now separates transient session exclusion from durable leasing and integrated logical restore from backup, target authentication, catalog/application acceptance, and PITR. | Keep source/test authority stronger than prose. | +| ADR set | IMPLEMENTED-ON-PROTECTED-MAIN / record-local | Existing ADRs retain their own decision status. The restore-seek decision integrated with #212 is protected history; ADR status must not be inferred merely from neighboring active work. | Preserve record-local status and avoid number collisions. | +| `docs/adr/README.md` | ACTIVE-PR | Provides navigation and separates ADR decision status from implementation status. | Keep the index synchronized without embedding exact heads. | +| `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded result streaming/checkpoint behavior, not end-to-end exactly-once application. | Update only with integrated result-application changes. | +| `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Operator authority for trusted tenant scope, standalone compatibility, forced RLS, direct-SQL limits, migration, and rollback. | Do not duplicate this contract into a competing operator guide. | +| PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | Receipt, artifact, and packaged-schema evidence are bounded content-free identity/integrity primitives. | Never promote hashes/receipts into restorability, target-isolation, PITR, or RPO/RTO claims. | +| PostgreSQL logical backup | ACTIVE-PR | #208 remains a bounded `pg_dump` candidate. | Keep unshipped until normal integration and final-head evidence. | +| PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | The logical restore executor is protected-main behavior through merged #212. Closed #209 remains historical defect evidence because its EOF-consumption postcondition was invalid for seekable custom-format archives. | Preserve caller-owned source trust, constrained libpq environment, transactional failure, metadata verification, target-isolation and post-restore acceptance gaps; do not imply RPO/RTO/PITR. | +| Recovery evidence binding and live re-inspection | ACTIVE-PR | Candidate seams compose or re-inspect bounded evidence; success is not provenance, restorability, or target isolation. | Keep branch evidence distinct from shipped truth. | +| Post-restore catalog/application acceptance | ACTIVE-PR | Catalog/application readiness must reject same-name decoys and prove the actual live PostgreSQL authority it claims. #296 remains a Draft branch candidate. | Promote only after protected integration of unchanged source and tests. | +| Permanent live PostgreSQL integration acceptance | ACTIVE-PR | #341 owns the hosted `pytest -m integration` lane. Its current branch and child #296 have branch-level GREEN evidence, not protected-main authority. | Preserve the permanent lane through protected integration; do not substitute deselected or mocked tests. | +| Physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | Current branches record bounded evidence and intent; they do not prove actual replay, promotion, or achieved objectives. | Require deployment-specific execution and measured acceptance before RPO/RTO claims. | +| Restore-target isolation | PARTIAL | Configuration/service-name separation is not authenticated cluster identity. Closed #225 is historical lineage only, not live authority. | Require authenticated target proof before production restore-safety claims. | +| Existing-volume legacy PostgreSQL retirement | ACTIVE-PR | Migration/operator work remains separate from already shipped tenant lifecycle. | Do not duplicate its README/architecture/operability surface here. | +| OpenTelemetry installation/operation documentation | ACTIVE-PR | Packaging-extra work remains an overlay until exact lock/install/release evidence integrates. | Keep base installs dependency-light. | +| Durable reconciliation candidate discovery | ACTIVE-PR | Discovery remains unshipped even though the bounded reconciliation primitive and transient session single-flight are protected behavior. | Preserve bounded deterministic tenant-qualified discovery requirements. | +| Tenant-qualified reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | #191 integrated the transient PostgreSQL session advisory-lock seam. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | Keep those non-goals explicit. | +| Atomic durable result application | ACTIVE-PR / end-to-end PARTIAL | Existing checkpoint/stream primitives do not prove complete exactly-once application; #194 remains active candidate work. | Require same-transaction local authority and preserve external-effect limits. | +| Runtime config/schema provisioning and secret policy | ACTIVE-PR / protected compatibility baseline | Protected main permits `SecretStore(require_encryption=False)` and compatibility rows with `is_encrypted = FALSE`; optional Fernet is supported, not mandated. #210 remains an active stricter runtime/operator-contract candidate. | Do not claim mandatory encryption, historical-row migration, rotation/recovery, or external key custody until those contracts integrate. | +| Canonical traceability | ACTIVE-PR | This overlay is the current canonical documentation landing vehicle. #226 and superseded #214 are historical documentation predecessors, not live authority. | Keep stable implementation/test/doc references and no exact heads. | +| Threat model | ACTIVE-PR | `docs/THREAT_MODEL.md` records assets, boundaries, attacker preconditions, mitigations, residual risk, and APA 7th NIST references without claiming certification. | Promote only through normal merge; update residual risk when runtime authority changes. | +| Data governance | ACTIVE-PR | `docs/DATA_GOVERNANCE.md` maps data classes, owners, tenant authority, retention/deletion limits, authorized-content fidelity, and optional Fernet compatibility. | Do not turn evidence readiness into a records-program certification. | +| UML/component/sequence views | ACTIVE-PR | `docs/uml/component-and-sequence.md` shows standalone/embedded composition and tenant-validation sequence. | Keep active-only components off shipped diagrams until integrated. | +| ERD / schema model | ACTIVE-PR | `docs/erd/package-owned-schema.md` maps packaged tables and migration-owned checkpoint identity. | SQL remains stronger authority; refresh only after integrated schema identity changes. | +| General standalone operator guide | PARTIAL | Operator guidance exists across README and topic authorities but no single omnibus `docs/OPERABILITY.md` is protected authority. | Consolidate only after checking adjacent writers. | +| Release governance | PARTIAL | Release-evidence code/workflows exist, but publication remains valid only from a fully accepted exact protected head. | Tie version, CHANGELOG, package, SBOM, provenance, reproducibility, rollback, tag and publication verification together through the release owner. | +| Licensing / third-party notices | PARTIAL | Apache-2.0 source licensing and SBOM evidence exist; acquisition diligence still needs a concise third-party notice process. | Add evidence without making legal-certification claims. | ## Non-negotiable documentation invariants -- Protected-main behavior is the shipped authority. Active PRs and historical branches are overlays, not proof of implementation. -- Exact contributor heads, generated merge commits, check IDs, and transient queue state belong in PR/review evidence, not durable architecture/product documents. -- Standalone operation and modular MSA embedding must be documented as co-equal supported boundaries; no ContextualWisdomLab host is a hidden runtime requirement. -- Tenant scope is selected only by a trusted authenticated/authorized host boundary and, for the tenant durable client, validates before observation reservation, credential lookup, provider I/O, or lifecycle database I/O. Lifecycle identities, conflict targets, exact reads, and operational status indexes remain tenant-qualified where tenancy is enabled. -- `pg_llm_batch.tenant_scope` is transaction-local routing context, not a credential or authenticated identity. Any database role capable of arbitrary SQL can call `set_config` with an arbitrary tenant scope; the trusted application boundary must therefore prevent generic tenant-controlled SQL, SQL injection, and incorrect identity mapping from selecting tenant authority. RLS does not provide those guarantees. -- The standalone `DurableBatchAPIClient` retains its four-argument lifecycle-recorder seam and explicit `standalone` persistence/read scope unless a separately reviewed compatibility change is integrated. -- PostgreSQL RLS is defense in depth, not host authentication/authorization, SQL-injection prevention, or correct identity mapping; production application roles for the tenant lifecycle boundary are `NOSUPERUSER NOBYPASSRLS`. +- Protected-main behavior is shipped authority; active PRs and historical branches are not. +- Exact contributor/protected heads, generated merge commits, run IDs, and queue state belong in PR/review evidence, not durable product documents. +- Standalone operation and modular embedding remain co-equal boundaries; no CWL host repository is a hidden runtime dependency. +- Tenant scope comes only from a trusted authenticated/authorized host selection. RLS is defense in depth, not authentication, SQL-injection prevention, or correct identity mapping. +- The standalone `DurableBatchAPIClient` retains its four-argument lifecycle-recorder seam and explicit `standalone` scope unless a reviewed compatibility change integrates. - Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. -- Content-fidelity invariants constrain any result-application path that exists, but they do not prove that end-to-end result application is shipped; FR-4 and `docs/TRACEABILITY.md` remain the capability-status authority while protected main is `PARTIAL`. -- Bounded recovery receipts, artifact hashes, and packaged-schema hashes are evidence primitives, not proof that a backup is restorable or that a stated recovery objective is met. -- A direct logical restore contract must keep caller-owned source trust, target isolation, allowed libpq environment, transaction rollback behavior, and post-restore acceptance explicit. Its archive-completion checks must match PostgreSQL custom-format random-access semantics: final descriptor offset is not proof of complete restore. #209 is therefore an unsafe predecessor, while #212 remains only an ACTIVE-PR successor until integrated. -- Distributed exactly-once processing is never implied by PostgreSQL checkpoint atomicity alone. -- Security, privacy, SOC 2, and CSAP material is evidence-readiness documentation only unless an external certification actually exists. -- Database object names, migration/rollback behavior, exact owned coverage requirements, Python-version acceptance, packaging/SBOM/provenance expectations, and bounded diagnostics must remain synchronized with repository tests and live governance. +- #191 proves only tenant-qualified transient session advisory single-flight; it does not prove a durable lease, scheduler, result-application transaction, terminal retirement, or distributed exactly-once semantics. +- #212 proves the bounded direct logical restore executor and corrected custom-format seek semantics; #209 remains historical EOF-defect evidence. The integrated executor does not prove backup creation, authenticated target isolation, post-restore catalog/application readiness, PITR, or RPO/RTO/HA/DR. +- Protected secret storage supports optional Fernet plus an explicit compatibility mode. Mandatory encrypted-at-rest policy, migration of compatibility rows, key rotation/recovery, and external custody are not inferred. +- Content-fidelity constraints do not prove end-to-end result application. +- Recovery receipts and hashes are evidence primitives, not restoration success. +- Security, privacy, SOC 2, and CSAP material is evidence readiness unless an external certification actually exists. +- Owned coverage, supported Python versions, packaging, SBOM/provenance, rollback, release and bounded-diagnostic requirements remain synchronized with live governance. ## Fitness gate for future canonical changes -Before changing a canonical surface, refetch protected main, open PRs, non-default branches, the exact affected source/schema/test authorities, and any adjacent documentation writer. A documentation repair must not race a source-affecting writer whose behavior is still unsettled. When a canonical change merely reconstructs an already integrated contract, verify the existing permanent companion set before widening the change; when runtime behavior actually changes, update the required permanent companion surfaces in that same governed change or explicitly coordinate their writer ownership. After a product PR merges, update the canonical status classification from `ACTIVE-PR` or `PARTIAL` only when the protected-main tree contains the capability and the integrated evidence contract remains valid. +Before changing a canonical surface, refetch protected main, open PRs, non-default branches, affected source/schema/test authorities, and adjacent documentation writers. Repair the earliest stale authority boundary without widening writer ownership. After a capability merges, update status only after reading the resulting protected tree; after a capability is superseded, keep historical lineage only where it explains a current constraint. Every changed documentation head must reacquire exact-head quality/security/release evidence and qualifying review under the then-live ruleset. From d6d09aab92367b0c9b731d7ead14396388d72029 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:35:18 +0900 Subject: [PATCH 41/58] docs(trace): remove stale active recovery authorities --- docs/TRACEABILITY.md | 99 +++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index a66fa9f36..a01bee09b 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -2,9 +2,7 @@ ## Purpose and authority -This map ties the canonical PRD/TRD requirements to stable protected-main implementation, test, ADR, and operator evidence. It intentionally avoids workflow-run IDs, predecessor SHAs, generated merge commits, and review comments because those are transient verification records rather than durable requirements authority. - -The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. Rows marked **ACTIVE-PR** or **PARTIAL** are not shipped implementation claims. +This map ties canonical PRD/TRD requirements to durable protected-main implementation, tests, ADRs, and operator evidence. It intentionally avoids workflow-run IDs, exact commit SHAs, generated merge commits, and transient review/check state. Rows marked **ACTIVE-PR** or **PARTIAL** are not shipped implementation claims. ## Product-to-technical traceability @@ -13,31 +11,32 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | FR-1 deterministic bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/orchestrator.py`, `pg_llm_batch/token_counter.py`, package schema | preparation/token tests; `docs/idempotent-preparation.md`; `docs/schema-integrity.md` | No gap claimed by the canonical product contract. | | FR-2 validated bounded provider interaction | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/batch_api_client.py` | provider URL/resource/retry/response-budget tests; `docs/batch-endpoints.md`; `docs/resource-identifiers.md`; ADR 0015 | Provider-specific widening requires a separately reviewed contract. | | FR-3 standalone + tenant-qualified durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/durable_client.py`, `pg_llm_batch/db.py`, schema/RLS objects | tenant lifecycle/integration tests; `ARCHITECTURE.md`; `docs/remote-batch-lifecycle.md`; ADR 0002 | Arbitrary SQL, superuser, and BYPASSRLS remain outside the isolation guarantee. | -| FR-4 scheduler-independent bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation.py` | reconciliation tests and protected-main release gates | Discovery #190 and single-flight #191 remain ACTIVE-PR; autonomous worker semantics remain PARTIAL. | -| FR-4 durable reconciliation candidate discovery | ACTIVE-PR | none on protected main beyond existing lifecycle/read primitives | PR #190 exact-head evidence only | Not shipped; current review/infrastructure gates must not be transferred. | -| FR-4 tenant-qualified cross-process single-flight | ACTIVE-PR | none on protected main beyond existing DB primitives | PR #191 exact-head evidence only | Not shipped; qualifying independent approval remains a live-governance concern. | -| FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | PR #194 is ACTIVE-PR test-first work that adds a same-transaction local result-effect/checkpoint seam; protected main still does not claim end-to-end or distributed exactly-once application. | -| FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement is separately ACTIVE-PR #184. | -| FR-5 bounded PostgreSQL recovery evidence primitives | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/postgres_recovery_receipt.py`, `pg_llm_batch/postgres_backup_evidence.py`, `pg_llm_batch/postgres_schema_evidence.py` | focused receipt/artifact/schema evidence tests; merged PRs #205, #206, #207 are historical integration evidence | Protected main can derive bounded content-free receipt, backup-artifact hash/size, and packaged-schema hash/size evidence. These primitives do not prove that a backup command ran successfully, that an artifact is restorable, that a live cluster matches packaged schema, or that PITR/RPO/RTO/HA/DR objectives are satisfied. | -| FR-5 executable PostgreSQL logical backup | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #208 exact-head evidence only | The `pg_dump` execution candidate is not shipped. Its service selector is not tenant authorization, and current exact-head review/check evidence must be reacquired before integration. | -| FR-5 executable PostgreSQL logical restore | ACTIVE-PR | none on protected main beyond the recovery-evidence primitives | PR #212 exact-head evidence only; closed #209 is predecessor defect evidence | #212 is the active direct-`pg_restore` successor. Closed predecessor #209 remains historical defect evidence because its EOF-consumption postcondition conflicts with seekable PostgreSQL custom archives and can report failure after transactional restore has already succeeded. The successor's caller-owned source-superuser trust, target-isolation responsibility, libpq allowlist, single-transaction failure boundary, metadata-integrity checks, and permanent documentation remain unshipped until integration. | -| FR-5 recovery evidence binding and live re-verification | ACTIVE-PR | protected main exposes the underlying receipt/schema/artifact evidence primitives only | PRs #215 and #221 exact-head evidence only | Bind-time composition and later re-inspection are active candidate seams, not inspection provenance or restore proof on protected main. A verifier success is integrity agreement at the inspection instant and does not remove TOCTOU or target-isolation requirements. | -| FR-5 post-restore catalog acceptance | ACTIVE-PR | protected-main schema and recovery evidence only | PR #223 exact-head catalog/unit/container evidence only; closed #216 is predecessor evidence | Catalog acceptance remains unshipped. Same-name index decoys, tenant-qualified key order, uniqueness/constraint authority, access method, readiness/validity, and live PostgreSQL query behavior must remain fail-closed before this can become protected-main truth. | -| FR-5 physical/WAL/PITR recovery profile | ACTIVE-PR | none on protected main beyond bounded recovery evidence | PR #219 exact-head evidence only | The profile records caller-owned recovery intent and objectives; it does not execute `pg_basebackup`, archive/replay WAL, prove an isolated target, or establish package RPO/RTO capability. | -| FR-5 restore-target isolation | PARTIAL | no protected-main target-isolation proof exists | PR #225 exact-head evidence only; #224 remains the ADR 0021 collision predecessor | Distinct libpq service names are a configuration-label check only. They are not authenticated cluster isolation. End-to-end acceptance must authenticate the actual restore target before production safety can be claimed. | -| FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded receipt/artifact/schema evidence primitives are integrated | Issue #204 acceptance authority plus protected-main recovery evidence tests | Active logical execution, evidence binding/reinspection, catalog acceptance, physical/PITR profiling, and target-isolation slices remain unshipped. No protected-main isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | -| FR-5 legacy `http` / `pg_cron` authority retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the retirement migration contract | PR #184 migration/smoke/operator evidence only | Must remain active until unchanged exact head satisfies migration/security/release/review gates and merges. | -| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret tests and bootstrap docs | Protected main deliberately retains `SecretStore(require_encryption=False)` as the compatibility default; Fernet support is therefore not an encryption-required production claim. #210 is the active operator/runtime-contract successor to the closed #193 line; neither its stricter policy nor provisioning/runtime separation is protected-main truth until integration. | -| FR-6 production secret-at-rest policy lifecycle | PARTIAL | Protected main can enforce Fernet when callers explicitly select `require_encryption=True`, and fails before database access when required encryption lacks usable configuration. | config/secret/bootstrap tests; security issue acceptance criteria | No protected-main contract yet detects and atomically migrates existing `is_encrypted = FALSE` rows, proves bounded key rotation/recovery, or exposes selected deployment policy through redacted readiness/operator evidence. #210 remains an ACTIVE-PR candidate rather than shipped policy. | -| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic validation rejected-value confidentiality is not protected-main truth; PR #202 is the ACTIVE-PR compatibility-aware repair and must not be inferred as shipped before integration. | -| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected-main `ValidationError` still renders and retains arbitrary rejected values by default | PR #202 candidate privacy/compatibility tests and review evidence only | PR #202 remains an ACTIVE-PR candidate with a hostile-type boundary defect on its current lane; intended safe-default redaction/bounded `safe_value` behavior remains unshipped until the exact current source and governance evidence are repaired and integrated. | -| FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR #175. | +| FR-4 scheduler-independent bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation.py` | reconciliation tests and protected-main release gates | Durable candidate discovery remains ACTIVE-PR; autonomous worker semantics remain PARTIAL. | +| FR-4 durable reconciliation candidate discovery | ACTIVE-PR | existing lifecycle/read primitives only | active discovery branch evidence | Candidate selection must remain tenant-qualified, bounded, deterministic, and database-authoritative before integration. | +| FR-4 tenant-qualified cross-process single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation_single_flight.py` | focused single-flight exact-type/traceback tests; merged #191 is historical integration evidence | Protected behavior is a transient PostgreSQL session advisory lock only. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | +| FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | #194 remains ACTIVE-PR same-transaction local work; protected main still does not claim end-to-end or distributed exactly-once application. | +| FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement remains separately active. | +| FR-5 bounded PostgreSQL recovery evidence primitives | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | focused receipt/artifact/schema evidence tests; merged #205/#206/#207 are historical integration evidence | Evidence identifies bounded bytes/metadata; it does not prove backup execution, restorability, live-schema parity, target isolation, PITR, or RPO/RTO/HA/DR. | +| FR-5 executable PostgreSQL logical backup | ACTIVE-PR | no protected-main `pg_dump` executor | #208 branch evidence only | A backup candidate exists but protected main must not be described as creating a restorable backup. | +| FR-5 executable PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/postgres_logical_restore.py` | logical-restore tests and integrated restore-seek ADR/docs; merged #212 is historical integration evidence; closed #209 is predecessor defect evidence | The bounded direct executor accepts custom-format random-access seek behavior and verifies archive metadata instead of final EOF. It does not provide `pg_dump`, authenticated target isolation, post-restore catalog/application readiness, PITR, or RPO/RTO/HA/DR. | +| FR-5 recovery evidence binding and live re-verification | ACTIVE-PR | protected main exposes the underlying receipt/schema/artifact evidence primitives only | active binding/reinspection branch evidence | Bind-time composition and later re-inspection are not provenance, restore proof, or target isolation. | +| FR-5 post-restore catalog/application acceptance | ACTIVE-PR | protected schema/recovery/restore primitives only | active catalog work plus #296 application-readiness candidate | Same-name decoys, key order, constraints, language/function identity, current-role privileges, and live PostgreSQL behavior must fail closed before this can become shipped acceptance. | +| FR-5 permanent live PostgreSQL integration acceptance | ACTIVE-PR | protected main has existing CI but not the #341 permanent integration lane | #341 branch executes `pytest -m integration`; #296 is its active child | Branch-level GREEN does not make the workflow or #296 specimen protected-main truth. | +| FR-5 physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | bounded protected evidence only | active physical/WAL/PITR branch tests and ADR evidence | Intent/evidence does not prove `pg_basebackup`, WAL archive/replay, promotion, or achieved recovery objectives. | +| FR-5 restore-target isolation | PARTIAL | no authenticated target-isolation proof exists on protected main | current recovery acceptance requirements | Distinct service/configuration labels are not proof that two names resolve to different clusters. | +| FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded evidence primitives plus bounded logical restore executor | issue-level recovery acceptance plus protected recovery tests | No protected isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or measured RPO/RTO/HA/DR. | +| FR-5 legacy `http` / `pg_cron` retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the complete retirement migration contract | active migration/smoke/operator evidence | Keep separate from already-shipped tenant lifecycle migration. | +| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret/bootstrap tests | Protected main supports optional Fernet and explicit compatibility mode. `SecretStore(require_encryption=False)` can persist `is_encrypted = FALSE`; this is not a mandatory encryption-at-rest claim. | +| FR-6 production secret-at-rest policy lifecycle | PARTIAL | callers can opt into `require_encryption=True` with usable Fernet configuration | config/secret/bootstrap tests; #210 active stricter runtime/operator-contract work | Historical compatibility-row migration, key rotation/recovery, external custody, and a mandatory default are not protected guarantees. | +| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic rejected-value confidentiality remains active work. | +| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected `ValidationError` compatibility baseline | active privacy/compatibility branch evidence | Intended safe-default redaction remains unshipped until exact source/governance evidence integrates. | +| FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR. | | FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | | Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | -| Python 3.10/3.12/3.14 validation | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | package metadata/workflow matrix | exact-head repository CI | Requires exact-head terminal success; queued/skipped/infrastructure-failed jobs are not proof. | -| Reproducible release evidence | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/release_evidence.py` and release workflows | ADR 0003; ADR 0004; release-evidence/artifact-identity tests | Release publication itself still occurs only from a fully accepted integrated protected head. | -| SBOM/provenance/artifact identity | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | release workflows/evidence helpers | release acceptance and artifact verification tests | No certification claim follows from repository evidence alone. | -| SOC 2 / CSAP evidence readiness | PARTIAL | security, tenancy, logging, release and governance controls | PRD/TRD/security tests/ADRs | Evidence readiness only; no external certification is claimed. | +| Python 3.10/3.12/3.14 validation | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | package metadata/workflow matrix | exact-head repository CI | Queued/skipped/infrastructure-failed jobs are not proof. | +| Reproducible release evidence | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/release_evidence.py` and release workflows | ADR 0003; ADR 0004; release-evidence/artifact-identity tests | Publication itself occurs only from a fully accepted integrated protected head. | +| SBOM/provenance/artifact identity | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | release workflows/evidence helpers | release acceptance and artifact verification tests | Repository evidence does not imply external certification. | +| SOC 2 / CSAP evidence readiness | PARTIAL | security, tenancy, logging, release and governance controls | PRD/TRD/security tests/ADRs | Evidence readiness only; no certification is claimed. | ## Security and privacy traceability @@ -47,11 +46,13 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | RLS defense in depth | tenant-qualified schema and transaction-local scope binding | live PostgreSQL isolation/migration tests | Superuser/BYPASSRLS/arbitrary SQL are administrative bypasses. | | Provider destination validation | `batch_api_client.py` | endpoint/URL tests | Host/network infrastructure TLS policy is external. | | Bounded provider input | provider client + result streaming | response/download/JSONL/resource-budget tests | Provider authenticity is not established by payload validation. | -| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Protected main supports Fernet but does not require it by default; compatibility mode is not a production confidentiality claim. #210 is ACTIVE-PR, while enterprise secret-manager choice and key custody remain host-owned. | -| Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic `ValidationError` rejected-value confidentiality remains incomplete on protected main; PR #202 is ACTIVE-PR and its evidence does not transfer until merge. | +| Reconciliation exclusion | `reconciliation_single_flight.py` | exact-type, lock/release and traceback regressions | Session lifetime is not a durable lease; scheduler and terminal retirement remain separate. | +| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Optional Fernet plus compatibility mode are protected behavior; mandatory encryption, compatibility-row migration, rotation/recovery, and external key custody are not. | +| Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic rejected-value confidentiality remains incomplete on protected main. | | Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | -| Recovery evidence confidentiality/integrity | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | recovery receipt/artifact/schema evidence regressions | Evidence is bounded and content-free but does not authenticate an operator, prove live inspection provenance beyond the integrated primitives, prove target isolation, or prove restore semantics. | -| Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability are operational dependencies. | +| Recovery evidence confidentiality/integrity | recovery receipt/artifact/schema modules | focused recovery evidence regressions | Evidence does not authenticate an operator, prove target isolation, or prove restore semantics. | +| Logical restore execution | `postgres_logical_restore.py` | custom-format seek, metadata, environment and transactional regressions | Command execution does not prove target identity, application readiness, PITR, or achieved RPO/RTO. | +| Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability remain operational dependencies. | ## Data and persistence traceability @@ -60,9 +61,9 @@ The reference protected-main tree is `d2f1e32271910a6db98a0757d67194ddadca4566`. | Tenant lifecycle state | `(tenant_scope, endpoint_alias, remote_batch_id)` | `ARCHITECTURE.md`, ADR 0002, `docs/remote-batch-lifecycle.md` | Tenant scope must come from trusted host authorization; direct SQL bypass is out of scope. | | Result checkpoints | `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | ADR 0006, ADR 0007, `docs/result-streaming.md` | Prefix checkpoint is not provider authentication or whole-stream immutability; cross-system exactly-once is not claimed. | | Package JSONL/payload state | package-owned schema identities and virtual payload references | PRD/TRD, schema-integrity and payload docs/tests | Persisted package data is canonical, not a disposable cache. | -| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Shipped compatibility mode can still persist `is_encrypted = FALSE`; runtime/provisioning least-privilege separation, required-encryption default, legacy-row migration, key rotation/recovery, and redacted policy-readiness evidence are not all protected-main behavior. | -| PostgreSQL recovery evidence | bounded receipt metadata plus backup/schema SHA-256 and byte-size evidence | protected-main recovery evidence modules/tests; canonical PRD/TRD/this traceability map once integrated | The evidence does not itself persist a backup, execute backup/restore, prove isolated target parity, or establish PITR/RPO/RTO/HA/DR. Backup storage, encryption, retention, key custody, and external copies remain deployment/operator responsibilities unless a separately integrated contract says otherwise. | -| Release evidence | descriptor/artifact identity contracts | ADR 0003, ADR 0004 | Evidence proves the reviewed artifact path, not organizational certification. | +| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Compatibility mode can persist `is_encrypted = FALSE`; optional Fernet support is not a mandatory policy. Migration, key rotation/recovery, and external custody remain separate. | +| PostgreSQL recovery evidence | bounded receipt metadata plus backup/schema SHA-256 and byte-size evidence | protected recovery evidence modules/tests; canonical PRD/TRD | Evidence does not persist a backup, execute backup, prove isolated target parity, or establish PITR/RPO/RTO/HA/DR. | +| Release evidence | descriptor/artifact identity contracts | ADR 0003, ADR 0004 | Evidence proves reviewed artifact identity, not organizational certification. | ## Active overlay register @@ -70,28 +71,24 @@ The following open pull requests are represented only as overlays. Their existen - **#175** — OpenTelemetry packaging extra; dependency-lock/materialization and final package evidence remain outside protected-main truth. - **#184** — existing-volume legacy PostgreSQL extension retirement; migration/operator behavior remains active until merged. -- **#190** — durable reconciliation candidate discovery; not protected-main truth and subject to live review/tooling evidence. -- **#191** — tenant-qualified reconciliation single-flight; not protected-main truth until live approval/gates and merge. -- **#194** — atomic local result-effect/checkpoint application; same-transaction behavior remains an active overlay and is not shipped. -- **#202** — compatibility-aware `ValidationError` rejected-value confidentiality hardening; current candidate evidence does not transfer into shipped behavior. +- **#190** — durable reconciliation candidate discovery; not protected-main truth. +- **#194** — atomic local result-effect/checkpoint application; same-transaction behavior remains active and is not end-to-end exactly-once proof. +- **#202** — compatibility-aware rejected-value confidentiality hardening; current candidate evidence does not transfer into shipped behavior. - **#208** — bounded logical PostgreSQL backup executor using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. -- **#210** — configuration/secrets operator/runtime contract successor; encryption-required policy, least-privilege runtime readiness, and provisioning separation remain unshipped until this lane is repaired and integrated. -- **#212** — direct logical-restore successor to closed #209; it replaces the invalid EOF postcondition with metadata-fingerprint verification and owns the accompanying restore-contract documentation. It is not evidence of isolated restore acceptance or end-to-end recovery readiness. -- **#214** — superseded canonical overlay that froze transient pull-request state labels; it is not the landing vehicle. -- **#226** — previous canonical documentation successor that still told operators to keep #214 in a transient pull-request state. It is not the landing vehicle after the register repair. -- **this overlay** — current canonical documentation landing vehicle. It keeps the #226 documentation set, removes the leftover transient-state instruction, names adjacent recovery families, and adds threat-model, data-governance, UML, and package ERD overlays. Protected-main status does not change until this lane integrates. -- **#215** — recovery receipt evidence-binding candidate; exact-type evidence objects must not be mistaken for inspection provenance, and the active lane remains unshipped until repaired and accepted. -- **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives only and does not execute recovery or claim achieved RPO/RTO. +- **#210** — configuration/secrets runtime/operator contract successor; least-privilege readiness and stricter policy work remain unshipped until normal integration. +- **#215** — recovery receipt evidence-binding candidate; object composition must not be mistaken for inspection provenance. +- **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives but does not prove recovery execution. - **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. -- **#222** — read-only exact-SHA workflow-registry audit candidate; governance tooling remains an overlay until normal integration, and ADR identity must remain collision-free across concurrent writers. -- **#223** — live PostgreSQL restore-catalog acceptance successor to closed #216; catalog/index-semantic acceptance remains unshipped. -- **#224** — restore-target isolation predecessor that files ADR 0021; that number collides with the workflow-registry audit lane, so this head is not the landing vehicle. -- **#225** — collision-free restore-target isolation successor using ADR 0022. Distinct libpq service names are a configuration-label check only; they are not authenticated cluster isolation or a restore executor. +- **#222** — read-only workflow-registry audit candidate; governance tooling remains an overlay until normal integration. +- **#223** — live PostgreSQL restore-catalog acceptance candidate; catalog/index semantics remain unshipped. +- **#229** — current canonical documentation landing vehicle. It repairs stale capability classification without taking ownership of root `ARCHITECTURE.md`, `CHANGELOG.md`, or product-gap-baseline paths. +- **#296** — isolated restore application-readiness candidate; branch evidence proves bounded catalog/language/privilege checks but not end-to-end recovery readiness. +- **#341** — permanent live PostgreSQL integration-lane candidate; current branch evidence executes the full integration marker and carries #296 as a tested child, but the workflow is not protected-main authority until normal integration. -Closed or superseded predecessors such as #192, #193, #209, #211, #213, and #216 remain historical evidence only. Merged recovery PRs #205, #206, and #207 are no longer active overlays; their bounded receipt, backup-artifact, and packaged-schema evidence primitives are present on the referenced protected-main tree. +Merged #191 and #212 are protected-main history, not active overlays. Closed documentation predecessors #214 and #226 are superseded historical lineage; they explain why this overlay avoids transient PR-state instructions but are not current authority. Closed recovery predecessors including #209 remain historical defect evidence only where they explain a current safety invariant. -This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its exact contributor head, live protected-main base, ancestry, current reviews/threads, exact-head gates, and resulting protected-main integration. +This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its current contributor head, live protected-main ancestry, reviews/threads, exact-head gates, and resulting protected integration. ## Change-control rule -When a capability merges, update the PRD/TRD status and this traceability map in a canonical documentation change only after the new protected-main tree is read. When a capability is abandoned or superseded, mark the overlay accordingly rather than silently deleting its historical decision context. New requirements must identify at least one intended implementation authority and one deterministic verification authority before they can be called acquisition-ready. +When a capability merges, update the PRD/TRD status and this traceability map only after reading the new protected-main tree. When a capability is abandoned or superseded, retain historical context only where it explains a live constraint. New requirements must identify an intended implementation authority and deterministic verification authority before they can be called acquisition-ready. From 6df96583ce7b0fd5ceb7db3e9fe6e0f98dffacde Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:35:45 +0900 Subject: [PATCH 42/58] docs(adr): align index with integrated restore decision --- docs/adr/README.md | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index d9f677522..446e3e044 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -2,36 +2,37 @@ ## Authority -This index is a navigation and status aid for architecture decision records that exist on protected `main`. The decision record itself remains the normative source for its context, decision, consequences, security boundary, and supersession rules. +This index is a navigation and status aid for architecture decision records present on the protected default branch. The decision record itself remains normative for its context, decision, consequences, security boundary, and supersession rules. -The protected-main tree used to reconstruct this index is `d2f1e32271910a6db98a0757d67194ddadca4566`. A pull request, historical branch, generated merge commit, workflow run, review comment, or proposed file that is not on protected main is not silently promoted into this index. +The index intentionally does not embed an exact protected commit SHA. Pull requests, historical branches, generated merge commits, workflow runs, and review comments are evidence rather than durable architecture authority. ## Protected-main decisions | ADR | Decision | Document status | Protected-main applicability | | --- | --- | --- | --- | -| [0002](0002-tenant-scoped-lifecycle.md) | Tenant-scoped durable lifecycle state | Accepted | Defines trusted host-selected `tenant_scope`, tenant-qualified durable lifecycle identity, transaction-local RLS binding, and the standalone compatibility scope. | -| [0003](0003-reproducible-release-evidence.md) | Reproducible release evidence before publication | Proposed | Documents the reproducibility/evidence design present in the repository. The ADR's own `Proposed` status is retained and must not be rewritten as architectural acceptance merely because related release-evidence code or workflows exist. | -| [0004](0004-descriptor-pinned-release-artifact-verification.md) | Descriptor-pinned release artifact verification | Proposed | Documents the descriptor-pinned TOCTOU-hardening design. Its `Proposed` decision status remains authoritative until explicitly changed through reviewed documentation governance. | -| [0006](0006-resumable-result-checkpoints.md) | Resumable provider-result checkpoints | Accepted | Defines immutable prefix checkpoint evidence and its explicit prefix-only, non-authentication, non-whole-stream assurance boundary. | -| [0007](0007-durable-result-checkpoint-store.md) | Durable tenant-isolated result checkpoint store | Accepted | Adds optional PostgreSQL persistence, tenant isolation, compare-and-swap concurrency, and a caller-owned transaction seam without claiming distributed exactly-once delivery. Depends on ADR 0006. | +| [0002](0002-tenant-scoped-lifecycle.md) | Tenant-scoped durable lifecycle state | Accepted | Defines trusted host-selected `tenant_scope`, tenant-qualified lifecycle identity, transaction-local RLS binding, and standalone compatibility. | +| [0003](0003-reproducible-release-evidence.md) | Reproducible release evidence before publication | Proposed | Records the reproducibility/evidence design while retaining the ADR's own `Proposed` status. Related implementation does not silently promote the decision status. | +| [0004](0004-descriptor-pinned-release-artifact-verification.md) | Descriptor-pinned release artifact verification | Proposed | Records descriptor-pinned TOCTOU hardening while retaining the record-local `Proposed` status. | +| [0006](0006-resumable-result-checkpoints.md) | Resumable provider-result checkpoints | Accepted | Defines immutable prefix checkpoint evidence and its prefix-only, non-authentication, non-whole-stream boundary. | +| [0007](0007-durable-result-checkpoint-store.md) | Durable tenant-isolated result checkpoint store | Accepted | Adds PostgreSQL persistence, tenant isolation, compare-and-swap concurrency, and a caller-owned transaction seam without a distributed exactly-once claim. | | [0015](0015-http-425-too-early-retry.md) | HTTP 425 retry for bounded idempotent GETs | Accepted for the bounded retry slice | Keeps the default GET retry-status set closed, side-effecting POSTs single-attempt, and TLS/certificate/fingerprint failures outside automatic retry. | +| [0016](0016-postgres-logical-restore-seek.md) | PostgreSQL custom-format logical restore seek semantics | Accepted for the bounded direct-restore slice | Integrated with #212. Final descriptor EOF is not a completion invariant for random-access custom archives; archive metadata verification and transactional failure handling remain bounded by the executor contract. This decision does not establish backup creation, authenticated target isolation, post-restore application readiness, PITR, or RPO/RTO/HA/DR. | -Protected main also contains bounded PostgreSQL recovery-evidence primitives in `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py`. Their integration does **not** create an implicit ADR. They are implementation/evidence contracts recorded by the PRD/TRD/traceability map, while executable logical backup/restore and end-to-end recovery remain active/partial work. If a future restore executor introduces a durable architectural decision about direct SQL authority, target isolation, source-superuser trust, libpq credential/environment handling, or rollback/acceptance semantics, that decision must be added or explicitly amended through normal ADR governance rather than inferred from the implementation. +Protected main also contains bounded PostgreSQL recovery-evidence primitives in `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py`. Their integration did not create an implicit ADR. They remain implementation/evidence contracts recorded by the PRD/TRD/traceability map. The direct logical-restore executor is separately governed by ADR 0016; executable logical backup and end-to-end recovery remain active/partial work. ## Numbering and missing identifiers -ADR numbers are stable identifiers, not a promise of contiguous numbering. The absence of `0001`, `0005`, or `0008` through `0014` from the protected-main directory does **not** mean those decisions are missing, rejected, accepted elsewhere, or safe to reconstruct from old branches. Gaps may reflect historical work, superseded proposals, unmerged branches, or reserved identifiers. Only a reviewed protected-main document may establish the status of a missing number. +ADR numbers are stable identifiers, not a promise of contiguous numbering. A missing number does not establish that a decision is rejected, accepted elsewhere, or safe to reconstruct from an old branch. Gaps may reflect historical work, superseded proposals, unmerged branches, or reserved identifiers. Only a reviewed protected-main document may establish the status of a missing number. -New ADRs should use the next repository-approved stable identifier rather than renumbering existing records. Renaming an integrated ADR changes external references and should be treated as an architecture-governance migration, not cleanup. +New ADRs should use a repository-approved stable identifier rather than renumbering existing records. Renaming an integrated ADR changes external references and is an architecture-governance migration, not cosmetic cleanup. ## Decision status versus implementation status -ADR status answers whether an architectural decision has been accepted, proposed, deprecated, or superseded. It is not interchangeable with product implementation status. +ADR status answers whether an architectural decision is accepted, proposed, deprecated, or superseded. It is not interchangeable with product implementation status. -The canonical product/technical documents use `IMPLEMENTED-ON-PROTECTED-MAIN`, `ACTIVE-PR`, `PARTIAL`, `PLANNED`, and `SUPERSEDED` for implementation truth. A `Proposed` ADR can coexist with related code on protected main, and an `Accepted` ADR can describe a bounded contract whose larger product capability is still only partial. Do not infer one status system from the other. +The canonical product/technical documents use `IMPLEMENTED-ON-PROTECTED-MAIN`, `ACTIVE-PR`, `PARTIAL`, `PLANNED`, and `SUPERSEDED` for implementation truth. A `Proposed` ADR can coexist with related code on protected main, and an `Accepted` ADR can describe a bounded decision whose larger product capability remains partial. Do not infer one status system from the other. -When an ADR and protected-main implementation appear inconsistent, treat the inconsistency as a defect to reconcile explicitly. Do not silently edit the index to make the conflict disappear. +When an ADR and protected-main implementation appear inconsistent, treat the inconsistency as a defect to reconcile explicitly rather than editing the index to hide it. ## Supersession and amendments @@ -39,13 +40,13 @@ A decision is superseded only when a reviewed record or amendment says so explic For a material architecture change: -1. refetch protected main and all source/documentation writers touching the decision boundary; -2. identify the existing ADRs and product/technical requirements that constrain the change; -3. record the new decision or explicit amendment, including rejected alternatives and operational/security consequences where material; +1. refetch protected main and source/documentation writers touching the decision boundary; +2. identify existing ADRs and product/technical requirements that constrain the change; +3. record the decision or explicit amendment, including rejected alternatives and material operational/security consequences; 4. keep active/unmerged behavior classified as an overlay rather than protected-main truth; -5. update traceability after the capability actually reaches protected main; and +5. update traceability after the capability reaches protected main; and 6. preserve standalone operation and modular MSA embedding unless a separately accepted decision changes that product contract. ## Non-guarantees that must remain visible -The current ADR set does not establish authentication from PostgreSQL RLS alone, provider authenticity from result checkpointing, full-stream immutability from a prefix checkpoint, distributed exactly-once processing, retry permission for arbitrary HTTP failures, backup restorability or PITR/RPO/RTO/HA/DR from recovery receipts/hashes alone, or organizational security/compliance certification. Those boundaries must not be weakened by summaries, operator docs, marketing material, or future ADR titles. +The current ADR set does not establish authentication from PostgreSQL RLS alone, provider authenticity from result checkpointing, full-stream immutability from a prefix checkpoint, distributed exactly-once processing, retry permission for arbitrary HTTP failures, backup restorability or PITR/RPO/RTO/HA/DR from recovery evidence or direct restore execution alone, or organizational security/compliance certification. Those boundaries must not be weakened by summaries, operator docs, marketing material, or future ADR titles. From 48e97d1304edbf10dfb9e081192faabfcfffd194 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:36:10 +0900 Subject: [PATCH 43/58] docs(security): bound optional Fernet compatibility risk --- docs/THREAT_MODEL.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md index c02059166..5924b931f 100644 --- a/docs/THREAT_MODEL.md +++ b/docs/THREAT_MODEL.md @@ -8,8 +8,8 @@ readiness for SOC 2 / CSAP preparation. It is not a certification, a penetration test, or a claim that a deployment is authorized for production. Use it to decide the next host control, not to infer that PostgreSQL row-level -security, recovery receipts, or redacted diagnostics have already closed a -business risk. +security, recovery receipts, redacted diagnostics, or optional Fernet support +have already closed a business risk. The methodology follows data-centric threat modeling (Scarfone & Souppaya, 2016/2016 IPD) and the NIST risk-assessment process (Joint Task Force, 2012): @@ -28,7 +28,12 @@ Control families are aligned to NIST SP 800-53 Revision 5 (Joint Task Force, and downstream decisions. 4. Treat recovery receipts and artifact hashes as identity evidence only. They do not prove a backup is restorable or that a restore target is isolated. -5. Run `standalone` when you are a single-tenant operator. Use +5. Treat Fernet as an optional protected-main mechanism, not a mandatory + encryption-at-rest guarantee. Compatibility mode can persist + `is_encrypted = FALSE`; production policy, migration, key rotation/recovery, + and external key custody remain deployment responsibilities unless a later + integrated contract changes that boundary. +6. Run `standalone` when you are a single-tenant operator. Use `TenantDurableBatchAPIClient` only after your host has already chosen `tenant_scope`. @@ -39,7 +44,7 @@ Control families are aligned to NIST SP 800-53 Revision 5 (Joint Task Force, | Authorized prompts, JSONL payloads, and provider results | `llm_requests`, `llm_batch_file_payloads`, `llm_jsonl_lines`, provider files | Business meaning. Silent masking or truncation invalidates accounting. | | Durable remote lifecycle identity | `llm_remote_batch_jobs` keyed by `(tenant_scope, endpoint_alias, remote_batch_id)` | Prevents one tenant from observing or advancing another tenant's batch. | | Result-stream checkpoints | `llm_result_stream_checkpoints` keyed by `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | Prefix resume only. Not provider authenticity or whole-stream immutability. | -| Standalone secrets and configuration | `com_secrets`, `com_config` | Bootstrap transport. Compatibility mode can still persist `is_encrypted = FALSE`. | +| Standalone secrets and configuration | `com_secrets`, `com_config` | Bootstrap transport. Optional Fernet is supported; compatibility mode can still persist `is_encrypted = FALSE`. | | Provider credentials | Host-injected credential provider or standalone secret store | Never a tenant-selected authority and never a telemetry attribute. | | Recovery evidence | In-memory receipts plus caller-owned backup/schema bytes | Content-free hash/size identity. Not restorability. | @@ -58,7 +63,7 @@ Control families are aligned to NIST SP 800-53 Revision 5 (Joint Task Force, [PostgreSQL] -- forced RLS for lifecycle and checkpoint tables | +--> [Provider Batch API] untrusted statuses, IDs, JSON, JSONL - +--> [Caller-owned backup/restore tools] untrusted until a shipped executor lands + +--> [Caller-owned backup/restore tools] authority bounded by integrated contracts ``` The package does not authenticate callers. `tenant_scope` is routing context @@ -74,8 +79,8 @@ depth after that trusted write. | Cross-tenant lifecycle read/write | Application role plus missing or wrong transaction-local scope | Forced RLS default-deny; tenant-qualified unique key and status index | `SUPERUSER` / `BYPASSRLS` / arbitrary SQL bypass the guarantee. | | SQL injection or generic tenant SQL | Application role exposed through a SQL console | Parameterized statements; documented prohibition on generic SQL | The custom setting is not a credential. Do not grant arbitrary SQL. | | Provider spoofing or oversized bodies | Network path to an unvalidated URL or unbounded parser | HTTPS production destinations, finite decoded-byte budgets, closed GET retry set `{408, 425, 429, 502, 503, 504}` | Provider authenticity is not proved by payload validation. HTTP 500 and POST stay single-attempt. | -| Secret reflection | Diagnostics copy DSNs, keys, prompts, or provider bodies | Bounded error vocabularies; public readiness omits lower-layer text | Generic `ValidationError` rejected-value confidentiality is still an active overlay. | -| Backup theft or unsafe restore | Operator points restore at the live cluster or a guessed artifact | Receipts and hashes identify bytes; they do not execute dump/restore | Executable backup/restore, catalog acceptance, and authenticated target isolation remain unshipped. | +| Secret reflection or weak at-rest policy | Diagnostics expose values, or an operator mistakes compatibility mode for encryption | Bounded error vocabularies; public readiness omits lower-layer text; Fernet can be explicitly required by callers | The default compatibility path is not a production confidentiality guarantee; migration, rotation/recovery, and key custody remain external. | +| Unsafe restore | Operator points restore at the live cluster or treats command success as application readiness | Bounded direct logical restore keeps source trust, environment, transaction, and archive metadata constraints explicit | Authenticated target isolation, application/catalog acceptance, PITR, and achieved RPO/RTO remain separate. | | Checkpoint fork or replay | Concurrent consumers advance the same identity | CAS `SELECT ... FOR UPDATE` with exact previous checkpoint | PostgreSQL atomicity does not extend to provider or network effects. | | Content-fidelity sabotage | A privacy filter rewrites authorized payloads | Package paths preserve authorized content unless a reviewed host policy says otherwise | A host that transforms content must keep provenance and acceptance tests. | @@ -85,8 +90,11 @@ depth after that trusted write. certification. - RLS does not replace authentication, authorization, or SQL-injection prevention. -- A recovery receipt, schema hash, or backup-artifact hash does not prove - restorability, live-cluster parity, PITR, RPO, RTO, HA, or DR. +- Optional Fernet support and redacted diagnostics do not prove that all stored + secrets are encrypted at rest or that key rotation/recovery/custody is solved. +- A recovery receipt, schema hash, backup-artifact hash, or successful bounded + restore command does not prove restorability, authenticated target identity, + application readiness, live-cluster parity, PITR, RPO, RTO, HA, or DR. - A prefix checkpoint is not a distributed exactly-once claim. - `standalone` is an explicit single-tenant scope, not an anonymous public mode. From 47b284969f5f7f0e60e123fc14743c343304b6d9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:37:20 +0900 Subject: [PATCH 44/58] docs(data): distinguish compatibility obfuscation from encryption --- docs/DATA_GOVERNANCE.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/DATA_GOVERNANCE.md b/docs/DATA_GOVERNANCE.md index ce403c7de..43f9f746f 100644 --- a/docs/DATA_GOVERNANCE.md +++ b/docs/DATA_GOVERNANCE.md @@ -14,9 +14,11 @@ certification and not a claim that a deployment has a complete records program. 2. Do not mask, tokenize away, or truncate authorized business payloads inside this package. If your policy requires transformation, do it in an explicit host boundary with provenance and acceptance tests. -3. Keep Fernet or an external secret manager as a host/deployment choice. - Protected main can persist `com_secrets.is_encrypted = FALSE` in - compatibility mode. +3. Treat Fernet as an optional host/deployment policy on protected main. + `SecretStore(require_encryption=False)` permits base64-obfuscated + compatibility rows with `com_secrets.is_encrypted = FALSE`; that mode is not + a mandatory encryption-at-rest guarantee. Historical-row migration, key + rotation/recovery, and external key custody remain separate responsibilities. 4. Own backup copies, replica retention, log/telemetry retention, and destructive deletion yourself. The package will not invent a general purge. 5. Use `standalone` for a single-tenant operator. Do not reuse that scope as an @@ -30,7 +32,7 @@ certification and not a claim that a deployment has a complete records program. | Durable lifecycle projection | `llm_remote_batch_jobs` | Host-selected `tenant_scope` plus package recorder | Tenant-qualify identity, bind `set_config`, force RLS. | | Result checkpoints | `llm_result_stream_checkpoints` | Host-selected consumer name plus tenant | Store prefix evidence only. | | Standalone configuration | `com_config` | Operator | Key/value settings. Not tenant authorization. | -| Standalone secrets | `com_secrets` | Operator / secret-manager host | Optional Fernet. Compatibility plaintext is not a production claim. | +| Standalone secrets | `com_secrets` | Operator / secret-manager host | Optional Fernet or explicit compatibility mode. Compatibility rows are base64-obfuscated, not an encryption-at-rest claim. | | Provider credentials | Host credential provider | Deployment | Resolve after tenant validation. Never tenant-keyed by this package. | | Recovery evidence | Receipts, artifact hashes, schema hashes | Operator | Content-free identity. Not restorability. | | Operational diagnostics | Errors, logs, readiness, telemetry | Package | Omit payloads, DSNs, credentials, and dynamic exception text. | @@ -75,4 +77,4 @@ https://www.iso.org/standard/85938.html Joint Task Force. (2020). *Security and privacy controls for information systems and organizations* (NIST Special Publication 800-53, Revision 5). National -Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-53r5 +Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-53r5 \ No newline at end of file From bd468d2d642fdf02efb2991fe55eedc362e82a68 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:41:44 +0900 Subject: [PATCH 45/58] test(docs): require merged restore-target identity truth --- tests/test_canonical_status_vocabulary.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/test_canonical_status_vocabulary.py b/tests/test_canonical_status_vocabulary.py index f46e47f58..00fb6d059 100644 --- a/tests/test_canonical_status_vocabulary.py +++ b/tests/test_canonical_status_vocabulary.py @@ -86,6 +86,25 @@ def test_product_contract_records_integrated_single_flight_without_lease_claim() assert "distributed exactly-once" in lowered +def test_product_contract_records_integrated_restore_target_identity_boundary() -> None: + """Merged #228 proves bounded name-plus-cluster separation, not end-to-end restore safety.""" + prd = _read(REPOSITORY_ROOT / "docs" / "product" / "PRD.md") + trd = _read(REPOSITORY_ROOT / "docs" / "product" / "TRD.md") + fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") + adr_index = _read(REPOSITORY_ROOT / "docs" / "adr" / "README.md") + + assert "| PostgreSQL restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN |" in prd + assert "`postgres_restore_target.py`" in trd + assert "merged #228" in fitness + assert "| FR-5 restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN |" in traceability + assert "[0022](0022-postgres-restore-target-isolation.md)" in adr_index + for document in (prd, trd, fitness, traceability, adr_index): + lowered = document.lower() + assert "system_identifier" in document + assert "rpo/rto" in lowered or "rpo" in lowered + + def test_secret_policy_docs_match_optional_fernet_compatibility_default() -> None: """Canonical secret prose must not turn optional Fernet into a shipped mandate.""" parameter = inspect.signature(SecretStore).parameters["require_encryption"] @@ -103,7 +122,7 @@ def test_secret_policy_docs_match_optional_fernet_compatibility_default() -> Non def test_active_overlay_register_excludes_merged_or_closed_recovery_predecessors() -> None: - """The active register must not retain merged #191/#212 or closed #225 as live work.""" + """The active register must not retain merged #191/#212/#228 or closed #225 as live work.""" traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") active_numbers = { int(match.group("number")) for match in _ACTIVE_OVERLAY_ENTRY.finditer(traceability) @@ -111,6 +130,7 @@ def test_active_overlay_register_excludes_merged_or_closed_recovery_predecessors assert 191 not in active_numbers assert 212 not in active_numbers assert 225 not in active_numbers + assert 228 not in active_numbers assert 296 in active_numbers assert 341 in active_numbers From bed5ba279e9eb6e02b82d13531342ec4b0aa1c2d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:42:32 +0900 Subject: [PATCH 46/58] docs(product): record merged restore-target identity boundary --- docs/product/PRD.md | 166 ++++++++++++++++---------------------------- 1 file changed, 60 insertions(+), 106 deletions(-) diff --git a/docs/product/PRD.md b/docs/product/PRD.md index 943a9ef96..9d3de3c74 100644 --- a/docs/product/PRD.md +++ b/docs/product/PRD.md @@ -2,152 +2,106 @@ ## Document authority -This PRD defines the product contract for `pg-llm-batch`. Repository behavior is authoritative only after it is integrated into the protected default branch. Pull requests, issue plans, historical branches, generated merge commits, workflow artifacts, and review commentary are evidence or work-in-progress, not shipped product truth. +This PRD is the canonical product-status contract for `pg-llm-batch`. Protected default-branch code, schema, tests, and accepted decisions are shipped authority. Pull requests, issue plans, historical branches, generated merge commits, exact SHAs, run IDs, and review commentary are evidence or work-in-progress rather than durable product truth. -Use these status terms consistently: +Status vocabulary: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. -- **IMPLEMENTED-ON-PROTECTED-MAIN** — present in the protected default-branch tree and covered by its repository contract. -- **ACTIVE-PR** — implemented or being repaired in an open pull request; not shipped. -- **PARTIAL** — a protected-main primitive exists, but an end-to-end product capability still has an explicit gap. -- **PLANNED** — accepted requirement without an integrated implementation. -- **SUPERSEDED** — historical implementation or proposal that is not current product authority. +## Product purpose and users -## Product purpose +`pg-llm-batch` is a standalone and embeddable PostgreSQL-centered engine for durable/asynchronous LLM Batch API workloads. It owns deterministic token/resource accounting, bounded JSONL preparation, package-owned PostgreSQL persistence, validated provider Batch API interaction, durable lifecycle/checkpoint state, tenant/RLS boundaries, bounded reconciliation, and bounded recovery controls without requiring a particular CWL host service. -`pg-llm-batch` is a standalone and embeddable PostgreSQL-centered engine for preparing, submitting, observing, and retrieving bounded LLM Batch API workloads. It is intended for operators and host applications that need durable batch state, deterministic token/resource accounting, explicit tenant boundaries, bounded provider I/O, and acquisition-grade operational evidence without coupling the package to one gateway, scheduler, web application, or ContextualWisdomLab host service. - -## Primary users - -1. **Platform operators** running the package as an independently deployable service or Compose component. -2. **Application/platform engineers** embedding the Python package and PostgreSQL schema in a larger product. -3. **Multi-tenant host services** that authenticate and authorize callers before supplying a trusted `tenant_scope`. -4. **Reliability and security reviewers** who need deterministic failure boundaries, migrations, rollback, audit evidence, security gates, SBOM/provenance evidence, and bounded diagnostics. - -## Product outcomes - -The product must let a qualified host: - -- count model tokens through the reviewed PostgreSQL tokenizer boundary; -- prepare JSONL batch payloads under finite token, byte, and record limits; -- preserve package-owned payloads and lifecycle state durably in PostgreSQL; -- submit, poll, wait, cancel, and retrieve through validated OpenAI-compatible Batch API clients; -- operate in exact `standalone` mode or with a trusted tenant-qualified lifecycle identity; -- recover or reconcile provider lifecycle state without introducing a second database-side networking authority; -- derive bounded content-free PostgreSQL recovery evidence for backup artifacts and the packaged schema without treating evidence as proof of restorability; and -- prove package quality, security, reproducibility, release-artifact identity, and rollback assumptions through repository evidence. +Primary users are platform operators, application/platform engineers, multi-tenant hosts that authenticate and authorize callers before choosing `tenant_scope`, and reliability/security reviewers who need deterministic failure, migration, rollback, release, and evidence boundaries. ## Protected-main capability contract -| Capability | Status | Product requirement | +| Capability | Status | Product boundary | | --- | --- | --- | -| PostgreSQL token counting and bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | Token/resource accounting and batch partitioning remain deterministic and finite. | -| Disk-free package payload persistence | IMPLEMENTED-ON-PROTECTED-MAIN | Package-owned JSONL payloads persist in PostgreSQL and are validated before credential/provider effects. | -| OpenAI-compatible upload/create/poll/wait/cancel/retrieve | IMPLEMENTED-ON-PROTECTED-MAIN | Provider destinations, resource identifiers, control responses, downloads, retries, and timeouts remain bounded and validated. | -| Standalone durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | `DurableBatchAPIClient` preserves the existing four-argument lifecycle-recorder seam `(postgres_dsn, endpoint_alias, provider_batch, observation_order)` and its default recorder stores lifecycle state under the exact `standalone` scope. | -| Tenant-qualified durable lifecycle with forced RLS | IMPLEMENTED-ON-PROTECTED-MAIN | Tenant scope comes only from a trusted host authorization boundary, is validated before any tenant-client observation reservation, credential resolution, provider I/O, or lifecycle database I/O, and qualifies lifecycle identities, conflict targets, reads, and operational status indexing; direct arbitrary SQL remains outside the isolation guarantee. | -| Durable resumable result checkpoint/CAS storage | IMPLEMENTED-ON-PROTECTED-MAIN | PostgreSQL supplies tenant-qualified durable checkpoint authority and conflict detection; this is not a distributed exactly-once claim. | -| Redacted readiness reporting | IMPLEMENTED-ON-PROTECTED-MAIN | Public readiness evidence does not disclose arbitrary lower-layer diagnostic content. | -| Scheduler-independent bounded provider reconciliation primitive | IMPLEMENTED-ON-PROTECTED-MAIN | A host can submit a finite, validated candidate set for polling/retrieval through the existing bounded provider client; candidate discovery and scheduling remain outside this primitive. | -| Cross-process reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | The tenant-qualified PostgreSQL session advisory-lock seam excludes concurrent workers for the same bounded identity while its session is alive. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | -| Bounded PostgreSQL recovery receipt | IMPLEMENTED-ON-PROTECTED-MAIN | The package can encode/decode deterministic bounded content-free metadata that identifies package/source/PostgreSQL/schema/backup evidence without carrying credentials, DSNs, SQL, business payloads, or arbitrary diagnostics. | -| Bounded PostgreSQL backup-artifact integrity evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from one private regular backup artifact under descriptor-pinned, no-follow, finite-work constraints without executing backup or restore. | -| Bounded packaged PostgreSQL schema evidence | IMPLEMENTED-ON-PROTECTED-MAIN | The package can derive SHA-256 and byte-size evidence from the exact distributed `schema.sql` resource under a finite package-owned work budget without executing SQL or asserting live-cluster parity. | -| PostgreSQL logical backup execution | ACTIVE-PR | A bounded `pg_dump` candidate exists in #208 but is not shipped; protected main must not be described as creating a restorable backup from the evidence primitives alone. | -| PostgreSQL logical restore execution | IMPLEMENTED-ON-PROTECTED-MAIN | The bounded direct `pg_restore` executor integrated through #212 accepts PostgreSQL custom-format random-access seek behavior and verifies archive metadata rather than requiring final EOF. Closed #209 remains defect evidence for the invalid EOF postcondition. The executor does not provide `pg_dump`, authenticate target isolation, prove post-restore catalog/application parity or PITR, or establish RPO/RTO/HA/DR. | -| Recovery evidence binding | ACTIVE-PR | A host can compose one receipt from exact inspected schema and backup-artifact evidence objects. Bind-time composition is not inspection provenance, restorability, or target isolation. | -| Live receipt re-inspection | ACTIVE-PR | A later verifier can re-hash current bytes and compare them to a stored receipt. Agreement is valid only at that inspection instant and does not remove TOCTOU or prove restore success. | -| Post-restore catalog acceptance | ACTIVE-PR | Isolated restore acceptance must fail closed on same-name catalog decoys, tenant-qualified key order, uniqueness/constraint authority, access method, and live PostgreSQL query behavior. | -| Physical/WAL/PITR recovery profile | ACTIVE-PR | A caller-owned physical recovery profile records intent and objectives only. It does not execute `pg_basebackup`, archive or replay WAL, or establish a package RPO/RTO. | -| Restore-target isolation | PARTIAL | Distinct configuration labels are not authenticated cluster isolation. End-to-end acceptance must prove the restore target is a different cluster before production safety can be claimed. | -| End-to-end PostgreSQL recovery readiness | PARTIAL | Integrated evidence primitives and the bounded logical restore executor do not yet prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or a stated RPO/RTO/HA/DR objective. | -| Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative before it can become product truth. | -| Existing-volume legacy `http` / `pg_cron` retirement | ACTIVE-PR | Existing deployments need fail-closed, reversible migration evidence before compatibility packages can be removed. | -| First-class OpenTelemetry installation extra | ACTIVE-PR | Ordinary installs must remain telemetry-dependency-free; the optional package graph must be locked and reproducible. | -| Autonomous package-owned reconciliation worker with crash/restart completion semantics | PARTIAL | Protected main has reconciliation, transient single-flight, and durable state primitives, but does not yet claim a complete package scheduler/worker control plane. | -| Durable result application coupled to checkpoint advancement | PARTIAL | Existing checkpoint and retrieval primitives must not be described as end-to-end exactly-once result application until a reviewed coupling contract is integrated. | +| PostgreSQL token counting and bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | Deterministic token/resource accounting and finite batch partitioning. | +| Disk-free package payload persistence | IMPLEMENTED-ON-PROTECTED-MAIN | Package JSONL/file/line/request state is durable PostgreSQL state, not a disposable local cache. | +| OpenAI-compatible upload/create/poll/wait/cancel/retrieve | IMPLEMENTED-ON-PROTECTED-MAIN | Provider destinations, identifiers, responses, downloads, retries, and waits are validated and bounded. | +| Standalone durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | `DurableBatchAPIClient` retains its four-argument recorder seam and explicit `standalone` scope. | +| Tenant-qualified lifecycle with forced RLS | IMPLEMENTED-ON-PROTECTED-MAIN | Trusted host-selected `tenant_scope` qualifies durable identity and is bound transaction-locally; arbitrary SQL, `SUPERUSER`, and `BYPASSRLS` remain outside the isolation guarantee. | +| Durable result checkpoint/CAS storage | IMPLEMENTED-ON-PROTECTED-MAIN | Tenant-qualified checkpoint authority and conflict detection; not distributed exactly-once. | +| Scheduler-independent bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | Finite host-selected candidates use the reviewed provider client; discovery and scheduling remain separate. | +| Cross-process reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | Merged #191 provides tenant-qualified PostgreSQL session advisory-lock exclusion. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | +| Bounded recovery receipt / backup-artifact / packaged-schema evidence | IMPLEMENTED-ON-PROTECTED-MAIN | Content-free identity/integrity evidence only; not backup execution, provenance, restorability, live-schema parity, PITR, or RPO/RTO. | +| PostgreSQL logical backup execution | ACTIVE-PR | #208 remains a bounded `pg_dump` candidate; protected main must not be described as creating a restorable backup from evidence primitives alone. | +| PostgreSQL logical restore execution | IMPLEMENTED-ON-PROTECTED-MAIN | Merged #212 provides the bounded direct custom-format `pg_restore` executor. It accepts random-access seek behavior and verifies archive metadata instead of requiring final EOF. Closed #209 remains historical defect evidence. No `pg_dump`, target-authentication, application-readiness, PITR, or RPO/RTO/HA/DR guarantee follows. | +| PostgreSQL restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN | Merged #228 provides `verify_postgres_restore_target_isolation(...)`: live and restore libpq service names must differ and caller-owned `pg_control_system().system_identifier` values must differ. The package does not open either connection, authenticate who collected the identities, accept a DSN, execute restore, or prove post-restore application/catalog/PITR/RPO-RTO readiness. | +| Recovery evidence binding / live reinspection | ACTIVE-PR | Composition or later re-hashing is not provenance, restorability, or target isolation. | +| Post-restore catalog/application readiness | ACTIVE-PR | #296 is an unshipped application-readiness candidate; branch GREEN is not protected-main truth. | +| Permanent live PostgreSQL integration lane | ACTIVE-PR | #341 executes the full integration marker on its branch and carries #296 as a tested child; the workflow is not protected authority until integration. | +| Physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | Intent/evidence candidates do not prove `pg_basebackup`, WAL replay, promotion, or achieved objectives. | +| End-to-end PostgreSQL recovery readiness | PARTIAL | Evidence, direct logical restore, and bounded name+cluster separation still do not prove an isolated restore with schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, application readiness, or measured RPO/RTO/HA/DR. | +| Durable reconciliation candidate discovery | ACTIVE-PR | Discovery must be tenant-qualified, bounded, deterministic, and database-authoritative. | +| Autonomous package worker | PARTIAL | Reconciliation, transient single-flight, and durable state exist; a complete scheduler/crash-recovery/terminal-retirement control plane does not. | +| Durable result application coupled to checkpoint advancement | PARTIAL | Existing checkpoint/retrieval primitives do not establish end-to-end exactly-once result application. | +| Existing-volume legacy `http` / `pg_cron` retirement | ACTIVE-PR | Existing deployments require fail-closed, reversible migration evidence before legacy authority is retired. | +| PostgreSQL-backed configuration and secret storage | IMPLEMENTED-ON-PROTECTED-MAIN | Protected main supports optional Fernet plus explicit compatibility mode. `SecretStore(require_encryption=False)` can persist base64-obfuscated `is_encrypted = FALSE` rows. | +| Production secret-at-rest policy lifecycle | PARTIAL | Mandatory encryption, historical compatibility-row migration, key rotation/recovery, and external key custody are not protected guarantees; #210 remains stricter active work. | +| Redacted readiness and bounded diagnostics | IMPLEMENTED-ON-PROTECTED-MAIN | Public/operational evidence omits content-bearing lower-layer details. | +| First-class OpenTelemetry installation extra | ACTIVE-PR | Base installs remain telemetry-dependency-free until the optional graph integrates with lock/release evidence. | +| Standalone + modular embedding | IMPLEMENTED-ON-PROTECTED-MAIN | CWL services may integrate, but are not hidden runtime dependencies. | ## Functional requirements -### FR-1: Batch preparation - -The engine shall resolve an existing batch identity, select eligible requests, count tokens through the package tokenizer boundary, partition work under explicit provider/resource limits, and persist payload/file/line/request assignment state atomically for one preparation operation. Re-running a supported preparation path must not silently duplicate assignment or corrupt package-owned state. - -### FR-2: Provider interaction - -All provider operations shall use validated endpoint configuration and finite response/download budgets. Automatic retries are restricted to reviewed idempotent GET behavior. Side-effecting provider POST operations shall not gain implicit retry authority. Credentials and provider content shall not be copied into ordinary diagnostics. +### FR-1 — Batch preparation -### FR-3: Durable lifecycle and tenancy +Resolve a valid package batch identity, select eligible requests, count tokens through the reviewed PostgreSQL tokenizer boundary, partition under explicit token/byte/record/provider limits, and persist package-owned payload/file/line/request assignments atomically. Supported retries must not silently duplicate assignment or corrupt state. -The durable business identity is tenant-qualified where tenancy is enabled. `TenantDurableBatchAPIClient` shall validate its trusted host-selected `tenant_scope` synchronously at construction, before observation reservation, credential resolution, provider I/O, or lifecycle database I/O can occur. The tenant-qualified lifecycle key is `(tenant_scope, endpoint_alias, remote_batch_id)`; lifecycle persistence conflict targets, exact-row lookups, and operational status indexes shall retain `tenant_scope`, and package reads/writes shall bind that validated scope through parameterized transaction-local PostgreSQL context with forced row-level security for application roles. Provider/model content, endpoint aliases, remote identifiers, and transport data never select tenant authority. +### FR-2 — Provider interaction -The transaction-local `pg_llm_batch.tenant_scope` custom setting is routing context, not a credential or authenticated identity. Package code may set it only from a trusted authenticated/authorized host selection. A database role that can execute arbitrary SQL can still call `set_config` with an arbitrary tenant scope; the trusted application boundary must prevent generic tenant-controlled SQL, SQL injection, and incorrect identity mapping from selecting tenant authority. PostgreSQL RLS is defense in depth and does not replace those controls. PostgreSQL superuser/BYPASSRLS and arbitrary SQL access remain administrative escape hatches outside the tenant isolation guarantee. +Provider operations use validated endpoints and finite response/download budgets. Automatic retries are limited to reviewed idempotent GET behavior. Side-effecting POSTs do not gain implicit retry authority. Credentials and provider content are excluded from ordinary diagnostics. -The deployment credential provider remains a separate host/configuration authority: validating tenant scope before credential resolution does not make credentials tenant-keyed and does not authorize a tenant to select secrets. +### FR-3 — Durable lifecycle and tenancy -Standalone source compatibility is also normative. `DurableBatchAPIClient` retains its four-argument lifecycle-recorder interface `(postgres_dsn, endpoint_alias, provider_batch, observation_order)`, and the default persistence/read helpers use the explicit `standalone` database scope rather than silently introducing a required tenant argument. +Tenant-aware clients validate trusted host-selected `tenant_scope` synchronously before observation reservation, credential lookup, provider I/O, or lifecycle SQL. The durable key is `(tenant_scope, endpoint_alias, remote_batch_id)` and tenant-aware writes/reads bind that scope through parameterized transaction-local PostgreSQL context with forced RLS. `pg_llm_batch.tenant_scope` is routing context, not authentication. A role capable of arbitrary SQL can set it arbitrarily, so host identity mapping, authorization, SQL-injection prevention, and administrative database roles remain outside the RLS guarantee. -Protected-main acceptance authority for these invariants is deterministic: `tests/test_tenant_durable_client.py` proves construction-time pre-effect tenant validation and the four-argument standalone recorder seam; `tests/test_tenant_lifecycle_persistence.py` proves explicit `standalone` delegation, tenant-qualified conflict targets and reads, malformed-scope rejection before database access, and distinct tenant identities; `pg_llm_batch/schema.sql` supplies the tenant-qualified unique key, forced RLS policy, and tenant-qualified operational status index. `docs/remote-batch-lifecycle.md`, ADR 0002, and `docs/doctoring/tenant-scoped-lifecycle.md` describe the same protected-main contract. +Standalone compatibility is normative: `DurableBatchAPIClient` retains `(postgres_dsn, endpoint_alias, provider_batch, observation_order)` and explicit `standalone` persistence/read scope. -### FR-4: Reconciliation and provider-effect recovery +### FR-4 — Reconciliation and provider-effect recovery -Reconciliation shall be finite, deterministic, payload-free in its operational evidence, and use the same validated provider client boundary as normal operations. Candidate discovery, scheduling, and result-application semantics must be explicit capabilities rather than inferred from polling code. Protected main provides tenant-qualified transient session advisory single-flight for the bounded reconciliation identity; that exclusion is not a durable lease, scheduler, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. Provider-success/database-failure cases must remain observable recovery states rather than being rewritten as if the provider effect never occurred. +Reconciliation is finite, deterministic, payload-free in operational evidence, and reuses the validated provider-client boundary. Protected main supplies transient tenant-qualified session advisory single-flight. Candidate discovery, scheduling, durable leasing, result application, terminal-work retirement, and cross-system exactly-once semantics are separate capabilities. Provider-success/database-failure states remain observable rather than being rewritten as if the provider effect never occurred. -### FR-5: Persistence integrity and PostgreSQL recovery evidence +### FR-5 — Persistence and PostgreSQL recovery -Package-owned database rows shall use descriptive two-or-more-word `snake_case` object names where applicable, explicit durable identities, parameterized SQL, and migrations that are idempotent or have a documented one-way boundary. Schema copies maintained for package and Docker initialization shall remain synchronized where the repository contract requires it. Malformed durable payload/state shall fail closed before downstream credential or provider effects when correctness depends on that state. +Package-owned database objects use explicit durable identities, parameterized SQL, synchronized schema copies where required, and documented migration/rollback boundaries. Malformed durable state fails closed before downstream effects when correctness depends on it. -Protected main shall provide bounded, content-free recovery evidence without overstating its guarantee. `PostgresRecoveryReceipt` identifies one evidence set using package version, exact source commit, PostgreSQL major version, schema SHA-256, a reviewed backup-method vocabulary, backup-artifact SHA-256 and size, and bounded start/completion epochs. Backup-artifact inspection shall pin directory/file identity, reject symlink traversal and unsafe file shapes, remain within a caller-visible finite hashing budget, and return only hash/size evidence. Packaged-schema inspection shall stream the exact distributed `schema.sql` under a finite package-owned budget and return only hash/size evidence. Malformed, ambiguous, duplicate-member, hostile-subclass, oversized, mutating, unreadable, or cleanup-failing evidence shall fail closed through fixed package diagnostics. +Protected main contains bounded content-free recovery evidence, the bounded #212 logical restore executor, and the bounded #228 restore-target name+cluster-identity verifier. The verifier requires distinct exact libpq service names and distinct caller-owned PostgreSQL `system_identifier` values gathered from already-opened connections. It does not establish connection provenance or authorize destructive action. The logical restore executor does not create backups or prove target/application readiness. End-to-end recovery still requires independent backup authority, authenticated target provenance, post-restore schema/RLS/constraint/extension/application acceptance, migration compatibility, key/config custody, and physical/WAL/PITR evidence where claimed. -Those evidence primitives do not themselves execute backup or restore, persist backup bytes, prove backup provenance or restorability, prove a live-cluster schema matches the package, authorize a tenant/operator, manage encryption keys, manage WAL, establish PITR, or prove RPO/RTO/HA/DR/compliance. Protected main separately contains the bounded custom-format logical restore executor integrated through #212. That executor preserves caller-owned source-superuser trust and a constrained libpq environment and uses transactional failure plus archive metadata checks, but it does not create a backup, authenticate restore-target separation, establish post-restore catalog/application readiness, manage keys/WAL, or prove PITR/RPO/RTO/HA/DR. Logical `pg_dump`, authenticated target isolation, application-readiness acceptance, and end-to-end recovery remain separately governed capabilities. +### FR-6 — Configuration and secrets -### FR-6: Configuration and secrets +Configuration and secrets are PostgreSQL-backed. Fernet is optional on protected main. Compatibility mode may store base64-obfuscated rows with `is_encrypted = FALSE`; this is not an encryption-at-rest claim. Deployments may require Fernet explicitly, but mandatory-default policy, migration of historical compatibility rows, rotation/recovery, and external key custody require separately integrated contracts. Environment variables are bootstrap transport only where documented; embedding hosts may inject credential providers. -PostgreSQL-backed configuration and secret storage remain available for standalone use. Fernet encryption is optional on protected main; `SecretStore(require_encryption=False)` permits the explicit compatibility mode that stores base64-obfuscated rows with `is_encrypted = FALSE`. Deployments may opt into Fernet with `require_encryption=True`, but mandatory encryption, historical compatibility-row migration, key rotation/recovery, and external key custody are not shipped guarantees. Environment variables are bootstrap transport only where explicitly documented. Embedding hosts may inject credential providers without changing provider protocol semantics. The package shall not invent an external secret-management product dependency. +### FR-7 — Observability and diagnostics -### FR-7: Observability and diagnostics +Operational telemetry is opt-in. Finite operation/outcome vocabularies may be emitted; prompts, provider bodies, credentials, arbitrary endpoint aliases/resource IDs, and arbitrary exception text are not telemetry attributes. Public readiness uses bounded categories where lower-layer text could contain sensitive data. -Operational telemetry is opt-in. Bounded operation/outcome vocabularies may be emitted; prompts, provider response bodies, credentials, arbitrary endpoint aliases, resource IDs, and arbitrary exception text are not telemetry attributes. Public readiness and ordinary errors shall use bounded categories when lower-layer text could contain sensitive data. +### FR-8 — Deployment -### FR-8: Standalone and modular deployment - -The package shall remain usable without `contextual-orchestrator`, `naruon`, or another CWL repository. Host services may provide authentication, tenant routing, secret resolution, gateway/model routing, OpenTelemetry export, or scheduling, but those integrations shall not become hidden standalone requirements. +The package remains usable without `contextual-orchestrator`, `naruon`, or another CWL repository. Host services may supply authentication, tenant routing, secret resolution, gateway/model routing, OpenTelemetry export, or scheduling through explicit seams. ## Non-functional requirements -### Quality - -Owned production Python must maintain exact 100% statement and branch coverage and complete public docstrings under the repository's configured gates. Supported validation includes Python 3.10, 3.12, and 3.14 plus realistic PostgreSQL/container integration where behavior depends on PostgreSQL. - -### Security and privacy - -Security-sensitive validation fails closed. Secrets, DSNs, prompt/provider content, unvalidated identifiers, and arbitrary lower-layer exception text must not be retained in logs or review evidence merely for debugging. Repository controls should support SOC 2 / CSAP evidence preparation without claiming certification. - -The package must not apply blanket masking or lossy transformation to authorized business payloads merely because they contain PII: changing prompt, request, or result content can invalidate business meaning, token accounting, provider behavior, auditability, or downstream decisions. Authorized content fidelity is therefore a product requirement. Confidentiality controls belong at explicit boundaries instead: trusted host authentication/authorization and tenant selection, least-privilege database/service access, transport protection, deployment/storage protection where provided, purpose-limited retention and deletion, and package-owned logs/telemetry/errors that omit content-bearing values. Any content transformation must be an explicit host/business policy with provenance and acceptance evidence, not a hidden package default or a claim that redacted diagnostics mean persisted business data was masked. - -### Reliability - -Network, response, retry, wait, candidate-scan, payload, recovery-evidence, and release-evidence operations must be explicitly bounded. Recovery receipts and hashes are integrity/identity evidence, not restoration success. Recovery and rollback must be documented before migrations or release changes are considered complete. Queued, skipped, cancelled, absent, stale, predecessor-head, synthetic-merge-only, or infrastructure-failed evidence is not success for an exact source head. - -### Interoperability +Owned production Python maintains exact 100% statement/branch coverage and complete public docstrings under repository gates. Supported validation includes Python 3.10, 3.12, and 3.14 plus realistic PostgreSQL/container integration when behavior depends on PostgreSQL. -Provider interaction stays OpenAI-Batch-compatible behind a validated Python client seam. Embedding hosts can provide credentials and control-plane context without changing the package's durable/provider semantics. PostgreSQL backup/restore executors, when integrated, must remain caller-targeted infrastructure seams rather than hidden dependencies on a specific ContextualWisdomLab host. +Security-sensitive validation fails closed. Authorized business payloads are not silently masked or transformed: doing so changes token counts, provider semantics, persisted evidence, replay, and business meaning. Confidentiality is enforced at explicit authentication/authorization, database/service, transport/storage, retention, and operational-evidence boundaries. Any content transformation is an explicit host/business policy with provenance and acceptance evidence. -### Packaging and release +Network, response, retry, wait, candidate-scan, payload, recovery, and release-evidence work is explicitly bounded. Queued, skipped, cancelled, absent, stale, predecessor-head, synthetic-only, or infrastructure-failed evidence is not exact-head success. -Dependencies must be locked/reproducible according to repository policy. Release acceptance must include required quality, security, package/container, SBOM, provenance, artifact-identity, rollback/recovery, and governance evidence on the exact integrated protected head. A release is not implied by a version string or a successful pull request. +Dependencies and release artifacts are locked/reproducible according to repository policy. Release acceptance covers the then-live quality, security, package/container, SBOM, provenance, artifact-identity, rollback/recovery, review, and governance gates on the exact integrated protected head. A version string or successful PR does not imply publication. ## Explicit non-goals - Replacing host authentication or authorization. -- Treating PostgreSQL RLS as a credential or as SQL-injection prevention. -- Making provider payload/model output an authority for tenant or endpoint selection. -- Providing an unbounded general-purpose HTTP proxy. +- Treating RLS or `tenant_scope` as a credential or SQL-injection prevention. +- Making provider/model content an authority for tenant, endpoint, credential, or filesystem selection. - Reintroducing provider networking or independent scheduling inside PostgreSQL. -- Claiming a backup is restorable, a live cluster matches packaged schema, or a recovery objective is met from receipt/hash evidence alone. +- Inferring restorability, target provenance, PITR, RPO/RTO/HA/DR, or compliance from recovery hashes, a restore command, or `system_identifier` comparison alone. - Claiming distributed exactly-once processing without an integrated transaction/recovery contract spanning every external effect. -- Requiring a specific ContextualWisdomLab host service for standalone operation. -- Claiming SOC 2, CSAP, or other certification solely from repository controls. +- Requiring a particular CWL host service for standalone use. +- Claiming SOC 2, CSAP, or another certification from repository evidence alone. ## Product acceptance boundary -A product capability moves to **IMPLEMENTED-ON-PROTECTED-MAIN** only after its unchanged source has satisfied the live ruleset, required exact-head CI/security/coverage/package/provenance/release checks, valid review findings are resolved, and the resulting tree is integrated into the protected default branch. Documentation must then be updated to move the capability out of `ACTIVE-PR`, `PARTIAL`, or `PLANNED`; historical evidence must not be transferred as if it were proof for a different head. +A capability moves to **IMPLEMENTED-ON-PROTECTED-MAIN** only after its unchanged source satisfies the live ruleset, required exact-head quality/security/coverage/package/provenance/release evidence, valid review findings, and protected-default-branch integration. Canonical documentation is then refreshed from the resulting protected tree; predecessor evidence never transfers automatically. From 0587d9d169892d8932475bb1058e113fee3a7d21 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:43:02 +0900 Subject: [PATCH 47/58] docs(technical): record merged cluster identity verifier --- docs/product/TRD.md | 200 +++++++++----------------------------------- 1 file changed, 41 insertions(+), 159 deletions(-) diff --git a/docs/product/TRD.md b/docs/product/TRD.md index 33c57bf5b..cafb2d5b2 100644 --- a/docs/product/TRD.md +++ b/docs/product/TRD.md @@ -2,198 +2,80 @@ ## Document authority -This TRD defines technical invariants for `pg-llm-batch`. It distinguishes protected-main behavior from work that is only present in an active pull request. The repository's live code, schema, tests, ruleset, and exact-head evidence remain stronger authority than historical branches, stale PR prose, predecessor checks, or generated merge commits. - -Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. +This TRD defines technical invariants for `pg-llm-batch`. Protected default-branch code, schema, tests, and accepted decisions are stronger authority than historical branches, stale PR prose, predecessor checks, exact SHAs, generated merge commits, or run IDs. Status vocabulary is shared with the PRD: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. ## System boundary -`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It may run standalone or be embedded by another service. The package owns batch preparation, package persistence, validated provider Batch API access, durable lifecycle projection, resumable checkpoint storage, bounded reconciliation primitives, tenant-qualified transient reconciliation single-flight, a bounded direct logical-restore executor, and bounded content-free PostgreSQL recovery-evidence primitives. It does not own host authentication, business authorization, ingress/WAF, infrastructure TLS policy, external secret-manager choice, global OpenTelemetry configuration, backup-storage infrastructure, WAL/archive infrastructure, or a cross-system distributed transaction. +`pg-llm-batch` is a Python package plus PostgreSQL schema and container assets. It can run standalone or be embedded. It owns bounded batch preparation, PostgreSQL persistence, validated provider Batch API access, durable lifecycle/checkpoint state, tenant/RLS controls, bounded reconciliation, tenant-qualified transient single-flight, bounded recovery evidence, bounded logical restore, and bounded restore-target cluster-identity comparison. It does not own host authentication/business authorization, infrastructure TLS, external secret-manager choice, global telemetry policy, backup/WAL infrastructure, connection provenance, or cross-system distributed transactions. ## Component contract | Component | Protected-main responsibility | Prohibited authority | | --- | --- | --- | -| `token_counter.py` | resolve reviewed tokenizer metadata and call `pg_tiktoken` for token accounting | provider credentials, tenant authorization, provider I/O | -| `orchestrator.py` | select queued requests, partition under limits, persist package payload/file/line/request assignments | provider protocol and retry policy | -| `batch_api_client.py` | validate provider destination and remote identifiers; upload/create/poll/wait/cancel/retrieve under finite budgets | tenant authentication, scheduler ownership | -| `durable_client.py` | compose provider operations with durable lifecycle ordering/persistence; preserve `DurableBatchAPIClient` source compatibility, its four-argument `LifecycleRecorder(postgres_dsn, endpoint_alias, provider_batch, observation_order)` seam, and default `standalone` database scope; provide a distinct tenant-qualified recorder seam | authenticating or authorizing host tenants, deriving tenant authority from provider data | -| `db.py` | schema application and parameterized persistence/read helpers, including tenant-qualified lifecycle context, conflict identity, and exact-row lookup | database-side provider networking, authenticating tenant callers | -| `checkpoint_store.py` | tenant-qualified PostgreSQL checkpoint/CAS operations and conflict semantics | distributed exactly-once claims | -| `reconciliation.py` | finite host-selected polling/retrieval pass using the existing validated client surface | candidate discovery and scheduling | -| `reconciliation_single_flight.py` | tenant-qualified transient PostgreSQL session advisory-lock exclusion for one bounded reconciliation identity | durable lease, scheduler, result-application transaction, terminal-work retirement, distributed exactly-once | -| `postgres_recovery_receipt.py` | encode/decode one deterministic bounded content-free PostgreSQL recovery evidence receipt | proving backup success/restorability, authenticating operators, carrying DSNs/credentials/business content | -| `postgres_backup_evidence.py` | derive SHA-256 and byte-size evidence from one private regular backup artifact through descriptor-pinned no-follow traversal and finite work | executing `pg_dump`/`pg_restore`, persisting backup bytes, proving restore semantics | -| `postgres_schema_evidence.py` | derive SHA-256 and byte-size evidence from the exact distributed `pg_llm_batch/schema.sql` resource under a finite package-owned budget | executing SQL, proving live-cluster parity or migration currency | -| `postgres_logical_restore.py` | execute the bounded reviewed custom-format `pg_restore` path using caller-owned source trust, constrained libpq environment, transactional failure handling, and archive metadata verification | creating backups, authenticating target isolation, proving post-restore catalog/application readiness, PITR, RPO/RTO/HA/DR | -| `config.py` | PostgreSQL-backed configuration and secret storage with optional Fernet plus an explicit compatibility mode | claiming mandatory encryption, historical-row migration, key rotation/recovery, external key custody, or prescribing an embedding host's external secret manager | -| `observability.py` | opt-in bounded traces/metrics around reviewed operations | configuring global SDK/exporter/resource policy | -| `health.py` | readiness aggregation and redacted public health response | general-purpose web serving or arbitrary diagnostic reflection | -| `cli.py` | standalone operator composition and bounded input surfaces | higher-level workflow orchestration | - -The protected-main validation authority for the `durable_client.py` compatibility row is `pg_llm_batch/durable_client.py`, `tests/test_tenant_durable_client.py`, and `tests/test_tenant_lifecycle_persistence.py`: the tests prove construction-time tenant rejection before downstream effects, exact four-argument standalone recorder invocation, explicit `standalone` persistence/read delegation, and tenant-qualified lifecycle persistence/read identities. - -The protected-main validation authority for recovery evidence is the three recovery-evidence modules plus their focused test suites. Historical merged PRs #205, #206, and #207 are integration evidence, not runtime authority. The bounded logical-restore executor integrated through #212 is a separate execution capability with narrower authority than end-to-end recovery readiness. `docs/TRACEABILITY.md` remains the canonical status map for the distinction between integrated evidence/restore primitives and active backup, target-authentication, and application-readiness candidates. +| `token_counter.py` | reviewed PostgreSQL tokenizer boundary | provider credentials, tenant authorization, provider I/O | +| `orchestrator.py` | deterministic bounded preparation and package persistence | provider protocol/retry policy | +| `batch_api_client.py` | validated bounded provider upload/create/poll/wait/cancel/retrieve | tenant authentication, scheduler ownership | +| `durable_client.py` | standalone and tenant-qualified lifecycle composition | authenticating/authorizing host tenants | +| `db.py` | schema application and parameterized durable reads/writes/RLS context | database-side provider networking | +| `checkpoint_store.py` | tenant-qualified checkpoint/CAS operations | distributed exactly-once claims | +| `reconciliation.py` | finite host-selected reconciliation | discovery and scheduling | +| `reconciliation_single_flight.py` | transient tenant-qualified PostgreSQL session advisory-lock exclusion | durable lease, scheduler, result application, terminal retirement, distributed exactly-once | +| `postgres_recovery_receipt.py` | deterministic bounded content-free receipt | backup/restore execution or operator authentication | +| `postgres_backup_evidence.py` | descriptor-pinned finite artifact hash/size evidence | backup execution or restorability proof | +| `postgres_schema_evidence.py` | finite packaged-schema hash/size evidence | SQL execution or live-cluster parity proof | +| `postgres_logical_restore.py` | bounded custom-format direct restore with caller-owned source trust, constrained libpq environment, transactional failure handling, and archive metadata verification | backup creation, target authentication, application readiness, PITR/RPO-RTO | +| `postgres_restore_target.py` | require distinct exact service names and distinct caller-owned PostgreSQL `system_identifier` values before a host treats targets as separate | opening connections, accepting DSNs/passwords, authenticating identity collection, executing restore, application/catalog/PITR/RPO-RTO proof | +| `config.py` | PostgreSQL-backed config/secret storage with optional Fernet and explicit compatibility mode | mandatory encryption, compatibility-row migration, rotation/recovery, external key custody | +| `observability.py` | opt-in bounded telemetry | global SDK/exporter/resource policy | +| `health.py` | redacted readiness aggregation | arbitrary diagnostic reflection | +| `cli.py` | standalone operator composition | higher-level workflow orchestration | ## Runtime architecture -### Batch preparation - -1. Resolve a supported package batch identity. -2. Read eligible unassigned requests from PostgreSQL. -3. Count model tokens through the reviewed PostgreSQL tokenizer boundary. -4. Partition requests in memory under explicit batch token, byte, record, and provider limits. -5. Under one package preparation transaction, persist virtual payloads, batch-file rows, JSONL line rows, request assignments, and aggregate totals in deterministic order. -6. On failure before commit, roll back the package preparation transaction rather than exposing a partially committed preparation from that invocation. - -Package-generated provider payloads are represented by `memory://` references and are reconstructed from PostgreSQL rather than written to a package-owned local payload file. +### Batch preparation and provider I/O -### Provider I/O +Preparation resolves a supported package identity, reads eligible requests, counts tokens through `pg_tiktoken`, partitions under finite token/byte/record/provider limits, and commits package payload/file/line/request assignments atomically. Package payloads remain PostgreSQL-backed rather than package-owned local files. -Provider gateway URLs and endpoint aliases are configuration inputs but are untrusted until validated by the applicable package boundary. Production gateway destinations require HTTPS; only explicitly reviewed loopback development HTTP destinations are accepted. Userinfo, query, fragment, whitespace, malformed port, or other forbidden URL forms must fail before credentials are used. - -Control-plane responses are consumed through a finite decoded-byte budget and strict UTF-8/JSON parsing. Provider output/error files are streamed in finite chunks with an independent decoded-byte ceiling before JSONL parsing. The client must fail closed when an adapter cannot provide the bounded streaming interface required by the operation. - -Automatic provider retry is limited to reviewed idempotent GET operations and the exact default status set `{408, 425, 429, 502, 503, 504}`. TLS handshake, certificate, and fingerprint failures are not automatically retried. Upload/create/cancel POST operations remain single-attempt unless a separately reviewed provider-specific contract is introduced. +Provider URLs and identifiers are untrusted until validated. Production destinations require the reviewed secure URL policy. Control responses and result/error files are consumed under finite decoded-byte budgets. Automatic retry stays limited to reviewed idempotent GET semantics; side-effecting POSTs remain single-attempt unless a separately reviewed provider contract changes that rule. ### Durable lifecycle tenancy -Standalone lifecycle data uses the exact `standalone` tenant scope. `DurableBatchAPIClient` preserves its original four-argument lifecycle-recorder interface `(postgres_dsn, endpoint_alias, provider_batch, observation_order)`; its default persistence path and `get_remote_batch_state(...)` compatibility helper resolve through the explicit `standalone` scope. Tenant-aware hosts instead use `TenantDurableBatchAPIClient` with a distinct tenant-qualified recorder seam so tenant identity cannot be silently dropped. - -A tenant-aware client validates the trusted host-selected `tenant_scope` synchronously during construction, before any observation reservation, credential-provider lookup, provider I/O, or lifecycle database I/O can occur. Provider metadata, request payloads, model output, transport headers, endpoint aliases, provider resource identifiers, and credential data never choose tenant authority. Credential resolution remains a separate deployment/host concern: ordering tenant validation before it does not make the credential store tenant-keyed. - -The durable lifecycle identity is: - -```text -(tenant_scope, endpoint_alias, remote_batch_id) -``` - -Every tenant-aware lifecycle persistence conflict target and exact-row lookup includes the full identity. The protected schema's lifecycle operational status index begins with `tenant_scope`, and package reads/writes bind the validated scope with parameterized transaction-local `set_config`. The schema enables and forces PostgreSQL row-level security for tenant-qualified lifecycle state. Production application roles must be `NOSUPERUSER NOBYPASSRLS`. A role that can execute arbitrary SQL can choose arbitrary custom setting values; therefore generic arbitrary SQL access is explicitly outside the package isolation guarantee. - -These invariants are deterministically verified on protected main: `tests/test_tenant_durable_client.py` proves malformed scope fails before reservation or credentials and proves the unchanged four-argument standalone recorder seam; `tests/test_tenant_lifecycle_persistence.py` proves malformed scope fails before database access, the upsert conflict target is `(tenant_scope, endpoint_alias, remote_batch_id)`, exact reads bind the same full identity, and standalone helpers delegate to `standalone`; `pg_llm_batch/schema.sql` supplies the tenant-qualified unique constraint, forced RLS policy, and `idx_llm_remote_batch_jobs_tenant_status_observed` index. `docs/remote-batch-lifecycle.md`, ADR 0002, and `docs/doctoring/tenant-scoped-lifecycle.md` document the same migration, direct-SQL/RLS, role, and rollback boundaries. - -### Durable result checkpoints - -Protected main contains tenant-qualified durable result checkpoint storage with compare-and-swap/conflict semantics. The checkpoint store can participate in a caller-owned PostgreSQL transaction where the caller's durable result application is in the same database transaction. The mere existence of this store does not prove exactly-once application across provider/network/database boundaries. - -Checkpoint counters, offsets, and identities must validate before mutation. Conflicting writes fail explicitly rather than silently overwriting a newer checkpoint. Rollback/recovery tests and schema parity are part of the storage contract. - -### Reconciliation - -Protected main supplies a scheduler-independent `reconcile_batch_candidates(...)` primitive. A host supplies candidate identities and a finite `max_jobs` budget. The primitive validates candidates, bounds scanning/work, polls through the validated provider client, retrieves completed jobs through that same client, and returns payload-free finite outcome/error categories. - -The host still owns candidate discovery, tenant authorization, and scheduling. Durable candidate discovery remains an **ACTIVE-PR** surface. The tenant-qualified session advisory single-flight is protected-main behavior: it provides transient, session-lifetime exclusion for one bounded reconciliation identity and releases with session/process loss. It is not a durable lease, scheduler, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. Package-owned autonomous scheduling, crash/restart completion semantics, terminal-work retirement after durable result application, and an end-to-end exactly-once worker remain **PARTIAL** or **PLANNED** capabilities. - -### PostgreSQL recovery evidence and logical restore - -Protected main supplies three deliberately non-executing recovery-evidence primitives. - -1. `PostgresRecoveryReceipt` binds exact built-in primitive metadata for package version, source commit, PostgreSQL major, packaged-schema SHA-256, reviewed backup-method vocabulary (`logical`, `physical`, or `pitr`), backup artifact SHA-256/size, and bounded timestamps. Its JSON representation is deterministic and size-bounded, rejects duplicate/unknown fields and hostile subclasses, and maps ordinary malformed input/decoder failures to fixed content-free diagnostics. -2. `inspect_postgres_backup_artifact(...)` traverses path components through pinned directory descriptors with no-follow semantics, rejects `..`, symlinked parents/final components, non-regular/empty/oversized files and unsafe link counts/permissions as defined by the implementation contract, hashes under an explicit finite maximum-size work budget, bounds each read request by remaining budget, compares descriptor identity/metadata before and after hashing, and treats cleanup failures as bounded evidence without masking an already-selected primary error. -3. `inspect_postgres_schema()` streams the exact distributed `pg_llm_batch/schema.sql` resource through SHA-256 under a finite package-owned work budget and returns only SHA-256 plus byte size. Missing, unreadable, empty, oversized, malformed-chunk, hostile-subclass, or cleanup-failing resources fail closed through fixed content-free diagnostics. - -These evidence primitives do not execute SQL or database mutation. They do not prove a backup command succeeded, prove backup provenance beyond caller-controlled receipt fields, prove restorability, prove a live database matches the packaged schema, provide target isolation, manage keys/secrets, manage physical/WAL/PITR infrastructure, or establish RPO/RTO/HA/DR/compliance. Those are separate acceptance domains. - -Logical `pg_dump` execution in #208 remains **ACTIVE-PR**. Direct `pg_restore` execution is **IMPLEMENTED-ON-PROTECTED-MAIN** through merged #212. The integrated executor deliberately accepts PostgreSQL custom-format random-access seek positions and verifies archive metadata instead of requiring final descriptor EOF. Closed predecessor #209 remains historical defect evidence because its EOF-consumption postcondition could report failure after `--single-transaction` had already committed. The integrated executor keeps caller-owned source-superuser trust, a constrained libpq environment, single-transaction failure semantics, and metadata-fingerprint checks explicit; it does not provide `pg_dump`, authenticate that the target is a different cluster, prove post-restore catalog/application readiness, manage external keys or WAL, or establish PITR/RPO/RTO/HA/DR. - -Active recovery work still includes executable logical backup, evidence binding, live receipt re-inspection, post-restore catalog/application acceptance, a caller-owned physical/WAL/PITR profile, and authenticated restore-target isolation. #296 is an active application-readiness candidate stacked behind the permanent live-PostgreSQL CI lane in #341; neither branch is protected-main truth. Those are capability families beyond the integrated restore executor, not evidence that end-to-end recovery is shipped. Distinct service-name labels are not authenticated cluster isolation. - -## Persistence requirements - -### Naming and schema ownership +Standalone lifecycle state uses the explicit `standalone` scope and preserves the four-argument `DurableBatchAPIClient` recorder seam. Tenant-aware clients validate trusted host-selected `tenant_scope` before reservation, credential resolution, provider I/O, or lifecycle SQL. Durable tenant identity is `(tenant_scope, endpoint_alias, remote_batch_id)` and package reads/writes bind that scope using parameterized transaction-local `set_config` under forced RLS. `tenant_scope` is routing context, not authentication. `SUPERUSER`, `BYPASSRLS`, and arbitrary SQL are administrative escape hatches outside the tenant guarantee. -New package-owned database objects use descriptive two-or-more-word `snake_case` names where applicable. SQL is parameterized; identifiers are not constructed from unvalidated user/provider text. Packaged schema and Docker initialization copies that represent the same contract must remain synchronized by regression tests. +### Checkpoints and reconciliation -### Migration behavior +Checkpoint storage is tenant-qualified and compare-and-swap based. PostgreSQL transactionality does not extend to provider/network effects. -Migrations must have an explicit compatibility and rollback boundary. Tenant migrations preserve legacy data under `standalone`, avoid a committed intermediate RLS-bypass state, restore forced RLS atomically, and remain idempotent where documented. Existing-volume retirement of legacy `http` / `pg_cron` authority is **ACTIVE-PR** and may not be described as shipped merely because fresh initialization no longer depends on SQL-side provider networking. +`reconcile_batch_candidates(...)` performs one finite host-selected reconciliation pass. Protected main also contains the tenant-qualified session advisory single-flight integrated through #191. That lock is session-lifetime transient state, not a scheduler, durable lease, result-application transaction, terminal-work-retirement authority, or distributed exactly-once mechanism. Durable discovery remains active work. -### Data integrity +### PostgreSQL recovery -Package-owned persisted virtual JSONL is canonical state, not a best-effort cache. Malformed shape, line count, framing, duplicate JSON members, non-finite numeric forms, or invalid record type fail closed through bounded package errors. Local payload integrity validation occurs before provider credentials/provider I/O where the provider effect relies on that payload. +Protected main contains bounded receipt, backup-artifact, and packaged-schema evidence primitives. These do not execute backup/restore, establish provenance, prove live schema, or establish PITR/RPO/RTO/HA/DR. -Durable provider/resource identifiers and tenant identities are validated before they become persistence or authorization inputs. Database/query failures must not be silently reclassified as an authoritative no-row result when correctness depends on distinguishing those cases. +Direct `pg_restore` execution is **IMPLEMENTED-ON-PROTECTED-MAIN** through merged #212. The executor accepts PostgreSQL custom-format random-access seek semantics and verifies archive metadata rather than requiring final descriptor EOF. Closed #209 remains historical defect evidence for the invalid EOF postcondition. The executor retains caller-owned source-superuser trust, constrained libpq environment, and single-transaction failure semantics; it does not provide `pg_dump`, target identity authentication, application/catalog readiness, WAL/PITR, or recovery-objective proof. -Recovery evidence is identity/integrity metadata, not a second persistence authority. The package does not own backup storage, replica lifecycle, object-store retention, WAL archives, encryption-at-rest infrastructure, or backup deletion merely because it can hash an operator-selected artifact. Operators/deployments must keep those responsibilities explicit. +Restore-target cluster identity verification is also **IMPLEMENTED-ON-PROTECTED-MAIN** through merged #228. `postgres_restore_target.py` accepts exact live/restore libpq service names and exact `PostgresRestoreTargetIdentity` values; both names and both `pg_control_system().system_identifier` values must differ. Callers collect the identifiers from connections they already opened. The package does not open a connection, read `pg_service.conf`, accept a DSN/password/host/port, authenticate the collector or connection provenance, execute `pg_restore`, or prove post-restore schema/application readiness. Thus the seam rejects same-cluster aliases but is not end-to-end restore authorization. -## Security and privacy requirements +Logical `pg_dump` remains active work. #296 remains an unshipped application-readiness candidate, and #341 remains the active owner of a permanent hosted live-PostgreSQL integration lane. Their branch-level evidence does not become protected-main truth until integration. -### Secrets +## Persistence, security, and privacy -Standalone provider configuration and secret storage are PostgreSQL-backed. Fernet is optional on protected main. With `SecretStore(require_encryption=False)`, the compatibility path can persist base64-obfuscated rows with `is_encrypted = FALSE`; callers that require Fernet must explicitly select `require_encryption=True` and provide usable key material. Mandatory encryption, migration of historical compatibility rows, key rotation/recovery, and external key custody are not protected-main guarantees. Environment variables are limited to explicitly documented bootstrap transport such as the database DSN and optional Fernet key. CLI secret entry uses no-echo prompting or bounded standard input rather than plaintext process arguments. Embedding hosts may supply another credential provider through the supported seam. +Package-owned persisted payload/state is canonical and validated before downstream effects when correctness depends on it. New database objects use descriptive snake_case naming where applicable, parameterized SQL, synchronized schema copies, explicit durable identities, and documented migration/rollback boundaries. -Recovery evidence must not carry DSNs, passwords, Fernet keys, prompts/results, ciphertext, arbitrary SQL, provider payloads, paths where not required by the callable interface, dynamic exception names, or reflected lower-layer diagnostics. A backup/restore executor must isolate credentials from process arguments and ambient environment according to its reviewed contract. +Standalone config and secrets are PostgreSQL-backed. Fernet is optional on protected main. `SecretStore(require_encryption=False)` permits base64-obfuscated compatibility rows with `is_encrypted = FALSE`; callers may explicitly require Fernet. Mandatory encrypted-at-rest policy, migration of historical compatibility rows, key rotation/recovery, and external key custody are separate capabilities. -### Authorized content fidelity +Authorized prompts, requests, JSONL, and provider results are not silently masked or truncated merely because they may contain PII. Such transformation changes token counts, replay, provider semantics, and business meaning. Host authentication/authorization, tenant selection, least-privilege identities, transport/storage controls, retention/deletion policy, and redacted operational evidence are the confidentiality boundaries. Any content transformation requires an explicit host/business policy with provenance and acceptance tests. -The package does not gain authority to mask, tokenize away, truncate for privacy, or otherwise alter an authorized prompt, request, JSONL record, or provider result merely because the content may contain PII. Silent transformation would change token counts, provider semantics, persisted evidence, replay behavior, and downstream business meaning. Serialization, token accounting, persistence, upload, and retrieval paths implemented on protected main therefore preserve authorized business content unless an explicit reviewed feature contract says otherwise. The same content-fidelity invariant constrains any result-application path that exists, but end-to-end result application remains **PARTIAL** under FR-4 and `docs/TRACEABILITY.md`; PR #194 is an **ACTIVE-PR** transaction-seam candidate, not protected-main proof of a completed result-application capability. +Errors, logs, telemetry, readiness, and review evidence omit DSNs, credentials, prompt/provider content, arbitrary SQL, untrusted identifiers, and dynamic lower-layer text where it is unnecessary. RLS remains defense in depth rather than authentication or SQL-injection prevention. -Confidentiality for content-bearing data is enforced through boundary controls rather than a blanket masking default: the embedding host authenticates and authorizes the caller and selects tenant scope; package/database/service identities remain least-privilege; and transport uses the reviewed secure destination policy. Protected main does not define a universal business-data retention duration or a general destructive deletion workflow. The embedding host owns business purpose, retention period, deletion authorization/trigger, and evidence that its policy was executed; the deployment owner separately owns PostgreSQL backup/replica, log/telemetry, and infrastructure retention/deletion controls; provider-side retention/deletion remains a provider/account-policy responsibility unless an explicit reviewed package adapter contract implements and verifies it. Package-owned errors, logs, telemetry, readiness, CI/review evidence, and other operational surfaces omit content-bearing values. A host that intentionally transforms content must do so through an explicit business-policy boundary with provenance and acceptance tests. Redacted operational evidence must never be represented as proof that persisted or provider-bound business content was masked or deleted. +## Concurrency, testing, and release -### Diagnostic confidentiality +Batch preparation and durable writes use PostgreSQL transactionality appropriate to their aggregate boundary. Session advisory locking is transient and must not be promoted to durable leasing. Recovery file inspection remains finite and fail-closed under mutation; a successful hash is evidence for the revalidated descriptor identity, not a lock on external storage. -Errors, logs, telemetry, check evidence, and public readiness must avoid DSNs, credentials, prompts, provider bodies, arbitrary SQL/provider exception text, unvalidated identifiers, and dynamic exception-class names where those values are not required for operation. Failure categories intended for public/operational evidence use bounded vocabularies. +Every defect follows realistic RED → minimum causal fix → exact-head GREEN. Repository evidence includes Python 3.10/3.12/3.14, exact owned production statement/branch coverage, public docstrings, lint/static checks, PostgreSQL integration for SQL/RLS/migration/concurrency behavior, package/container validation, migration rollback where applicable, security/SAST, locked packaging, release acceptance, SBOM/provenance, and artifact identity. Queued, skipped, cancelled, absent, stale, predecessor, synthetic-only, or infrastructure-failed evidence is not success. -### Tenant boundary - -RLS augments a trusted host authorization boundary; it is not itself authentication, a credential, or SQL-injection prevention. Administrative database identities are outside the ordinary tenant guarantee. Pooling code must not leak transaction-local tenant context between logical operations. - -### Provider boundary - -Provider URLs, statuses, IDs, headers, JSON, JSONL, retry guidance, and metadata are untrusted external input. Validation occurs before the downstream effect that relies on that value. Model/provider output never grants tenant, endpoint, credential, or filesystem authority. - -### Recovery authority boundary - -A backup artifact, receipt, service selector, schema hash, or backup method string is not authorization to read, write, restore, or replace a database. Authentication, authorization, target isolation, backup custody, key custody, destructive-operation approval, and recovery-objective ownership remain external unless an integrated contract explicitly supplies and verifies them. The protected logical-restore executor does not convert a service selector or archive into authenticated target-isolation authority. Recovery evidence must never be used to infer those authorities. - -## Observability requirements - -OpenTelemetry support is opt-in. Base installations must not require OpenTelemetry packages solely to use normal batch functionality. Operation names, outcomes, and error categories are finite. Telemetry attributes exclude endpoint aliases, provider URLs, resource identifiers, credentials, metadata, prompts, and provider response bodies. - -A first-class packaging extra for OpenTelemetry is **ACTIVE-PR** until its exact generated dependency lock is committed normally, temporary materialization machinery is removed, and final package/install/release gates succeed. - -## Health and operability - -Readiness covers the required PostgreSQL/tokenizer/configuration boundary and returns redacted public evidence. A failing dependency must not cause arbitrary lower-layer text to be reflected to a caller. Docker/container health and package health semantics must remain aligned. - -Operational migrations require backup/preflight/acceptance/recovery documentation before release. A recovery instruction must preserve package and operator-owned state; destructive `CASCADE`, hidden history rewrite, or deletion of unknown operator objects is not an acceptable shortcut. - -A recovery drill must distinguish artifact identity and successful command execution from restore acceptance. End-to-end acceptance must address exact schema/package identity, required schema/RLS/constraint/extension behavior, migration compatibility, authenticated target isolation, credential/key availability, and rollback/recovery behavior. Physical/WAL/PITR drills additionally require their own timeline/target and infrastructure acceptance criteria. No repository evidence should claim universal RPO/RTO/HA/DR without an explicit measured deployment objective. - -## Concurrency requirements - -Batch preparation uses database coordination/transactionality appropriate to its package-owned state. Durable lifecycle writes use explicit ordering/conflict semantics. The protected reconciliation single-flight seam is tenant-qualified, non-blocking, exception-safe, and session-scoped. Process/session loss releases it. Session advisory locking must never be promoted into a durable lease, scheduler, result-application transaction, terminal-work-retirement authority, or distributed exactly-once claim. - -Recovery-evidence file inspection must remain finite and fail closed under concurrent mutation. A successful hash/size result is valid only for the descriptor identity/metadata contract that was revalidated by the implementation; it is not a lock or lease over external backup infrastructure. - -## Testing requirements - -Every source defect follows realistic RED → narrow fix → GREEN → focused/full validation. Required repository evidence includes: - -- Python 3.10, 3.12, and 3.14 where configured; -- exact 100% owned production statement and branch coverage; -- public docstring coverage; -- lint/static checks; -- realistic PostgreSQL integration for SQL/RLS/migration/concurrency behavior; -- package and container installation/health validation; -- migration idempotency and rollback/recovery coverage where applicable; -- recovery-evidence tests for exact primitive types, duplicate/unknown metadata, finite work, descriptor/path boundaries, concurrent mutation, cleanup failure, and content-free diagnostics; -- logical-restore tests for custom-format seek semantics, archive metadata verification, constrained environment, and transactional failure boundaries; -- confidentiality regressions that inspect full exception/traceback surfaces when relevant; -- security scanning and SAST; -- dependency-lock and packaging reproducibility; -- release acceptance, artifact identity, SBOM, and provenance evidence required by the live repository contract. - -Queued, pending, skipped, cancelled, absent, neutral, stale, predecessor-head, synthetic-merge-only, status-only, infrastructure-failed, or rate-limited evidence is not exact-head success. - -## Release requirements - -A release may originate only from the exact integrated protected head after all live required quality, security, review, migration, rollback/recovery, operational, packaging, provenance, and release-acceptance gates are terminal-success. Versioning and CHANGELOG updates are followed by publication and artifact verification. Repository control evidence may support SOC 2 / CSAP readiness but must not be represented as certification. - -The presence of recovery-evidence primitives or the bounded logical-restore executor does not make a release end-to-end recovery-ready for a deployment. A release or operator contract that claims isolated restore/PITR/RPO/RTO/HA/DR readiness must cite the exact integrated drill/acceptance evidence for that deployment objective rather than extrapolating from hash/receipt or command-execution modules. +A release originates only from an exact integrated protected head after all then-required quality, security, review, migration/recovery, packaging, provenance, and release gates pass. Version/CHANGELOG/package/tag/publication do not become authoritative until publication and artifact verification complete. Recovery evidence, logical restore execution, or `system_identifier` comparison alone does not make a release end-to-end recovery-ready. ## Documentation requirements -Canonical product/technical/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability documents must distinguish shipped protected-main state from active or planned work. Durable documents should describe contracts rather than transient check-run IDs or exact commit SHAs. When an active capability merges, the canonical graph is updated in the same governance model rather than relying on stale PR body claims. - -Protected logical-restore authority must keep caller-owned source trust, target-isolation limits, allowed libpq environment, transactional failure behavior, archive metadata verification, and post-restore acceptance gaps explicit. Any future change that broadens those authorities requires coordinated permanent operator/architecture/ADR/doctoring/CHANGELOG coverage through the appropriate live documentation owners. +Canonical PRD/TRD/architecture/ADR/UML/ERD/security/operability/release/data-governance/traceability surfaces distinguish protected-main state from active work and avoid exact SHAs/run IDs. ADR 0016 records bounded restore-seek semantics. ADR 0022 records bounded restore-target name+cluster-identity separation. Broader direct-SQL, target-authentication, application-readiness, PITR, or recovery-objective changes require coordinated permanent documentation through their current owners. From 29c400a492a9575d1f3fcfcbae284642c95a3e7c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:43:29 +0900 Subject: [PATCH 48/58] docs: promote merged restore-target identity seam precisely --- docs/DOCUMENTATION_FITNESS.md | 95 ++++++++++++++++------------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 2b2b306e0..23ab16e30 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -2,67 +2,56 @@ ## Authority and status model -This inventory evaluates the canonical documentation graph against the live protected-default-branch behavior. It deliberately does not freeze an exact protected commit SHA: exact heads belong in PR and review evidence, while durable documentation records capability contracts. Pull-request content remains work-in-progress until normal protected-branch integration. +This inventory evaluates canonical documentation against live protected-default-branch behavior. It deliberately does not freeze an exact protected SHA: exact heads and run IDs belong in PR/review evidence, while durable documentation records capability contracts. Status vocabulary is **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. -The canonical status vocabulary is shared with `docs/product/PRD.md` and `docs/product/TRD.md`: **IMPLEMENTED-ON-PROTECTED-MAIN**, **ACTIVE-PR**, **PARTIAL**, **PLANNED**, and **SUPERSEDED**. +A document is fit only when it agrees with protected code/schema/tests, preserves non-guarantees, keeps branch evidence out of shipped claims, and gives operators/reviewers enough information to use or reject the behavior safely. -A document is fit only when it agrees with protected code/schema/tests, preserves non-guarantees, keeps active-branch evidence out of shipped claims, and tells an operator or reviewer enough to use, verify, recover, or reject the relevant behavior safely. - -The tenant lifecycle material reconstructs protected behavior rather than creating a new tenant/RLS contract. `README.md`, `ARCHITECTURE.md`, `docs/remote-batch-lifecycle.md`, ADR 0002, `docs/doctoring/tenant-scoped-lifecycle.md`, and `CHANGELOG.md` remain companion authorities for trusted tenant selection, `NOSUPERUSER NOBYPASSRLS`, transaction-local forced RLS, arbitrary-SQL limits, legacy-to-`standalone` migration, and rollback constraints. - -Protected main also contains bounded recovery-evidence primitives integrated through #205, #206, and #207, the tenant-qualified session advisory single-flight seam integrated through #191, and the bounded direct custom-format logical restore executor integrated through #212. These are deliberately narrower than end-to-end recovery. Logical `pg_dump`, evidence binding/re-inspection, authenticated target isolation, post-restore application readiness, physical/WAL/PITR execution, external key custody, and measured RPO/RTO/HA/DR remain separate capability families. +Protected main contains the tenant lifecycle/RLS contract, bounded reconciliation, tenant-qualified transient session single-flight integrated through #191, bounded recovery-evidence primitives integrated through #205/#206/#207, bounded direct logical restore integrated through #212, and bounded restore-target name+cluster-identity verification integrated through merged #228. These are narrower than a complete worker or recovery product. ## Current fitness matrix | Documentation surface | Status | Fitness assessment | Required next action | | --- | --- | --- | --- | -| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Public entry point for standalone/embedded operation and tenant lifecycle. It is not the sole architecture or recovery authority. | Change only through its live owner when protected behavior changes. | -| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Covers principal runtime boundaries but is separately owned by the active root-documentation lane. | Keep #229 out of this path; reconcile through the current owner. | -| `docs/product/PRD.md` | ACTIVE-PR | Canonical product contract now records #191 single-flight and #212 logical restore at their integrated bounded scope, while leaving broader worker/recovery guarantees unshipped. | Revalidate after each protected integration before changing status. | -| `docs/product/TRD.md` | ACTIVE-PR | Technical contract now separates transient session exclusion from durable leasing and integrated logical restore from backup, target authentication, catalog/application acceptance, and PITR. | Keep source/test authority stronger than prose. | -| ADR set | IMPLEMENTED-ON-PROTECTED-MAIN / record-local | Existing ADRs retain their own decision status. The restore-seek decision integrated with #212 is protected history; ADR status must not be inferred merely from neighboring active work. | Preserve record-local status and avoid number collisions. | -| `docs/adr/README.md` | ACTIVE-PR | Provides navigation and separates ADR decision status from implementation status. | Keep the index synchronized without embedding exact heads. | -| `docs/result-streaming.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Describes bounded result streaming/checkpoint behavior, not end-to-end exactly-once application. | Update only with integrated result-application changes. | -| `docs/remote-batch-lifecycle.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Operator authority for trusted tenant scope, standalone compatibility, forced RLS, direct-SQL limits, migration, and rollback. | Do not duplicate this contract into a competing operator guide. | -| PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | Receipt, artifact, and packaged-schema evidence are bounded content-free identity/integrity primitives. | Never promote hashes/receipts into restorability, target-isolation, PITR, or RPO/RTO claims. | -| PostgreSQL logical backup | ACTIVE-PR | #208 remains a bounded `pg_dump` candidate. | Keep unshipped until normal integration and final-head evidence. | -| PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | The logical restore executor is protected-main behavior through merged #212. Closed #209 remains historical defect evidence because its EOF-consumption postcondition was invalid for seekable custom-format archives. | Preserve caller-owned source trust, constrained libpq environment, transactional failure, metadata verification, target-isolation and post-restore acceptance gaps; do not imply RPO/RTO/PITR. | -| Recovery evidence binding and live re-inspection | ACTIVE-PR | Candidate seams compose or re-inspect bounded evidence; success is not provenance, restorability, or target isolation. | Keep branch evidence distinct from shipped truth. | -| Post-restore catalog/application acceptance | ACTIVE-PR | Catalog/application readiness must reject same-name decoys and prove the actual live PostgreSQL authority it claims. #296 remains a Draft branch candidate. | Promote only after protected integration of unchanged source and tests. | -| Permanent live PostgreSQL integration acceptance | ACTIVE-PR | #341 owns the hosted `pytest -m integration` lane. Its current branch and child #296 have branch-level GREEN evidence, not protected-main authority. | Preserve the permanent lane through protected integration; do not substitute deselected or mocked tests. | -| Physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | Current branches record bounded evidence and intent; they do not prove actual replay, promotion, or achieved objectives. | Require deployment-specific execution and measured acceptance before RPO/RTO claims. | -| Restore-target isolation | PARTIAL | Configuration/service-name separation is not authenticated cluster identity. Closed #225 is historical lineage only, not live authority. | Require authenticated target proof before production restore-safety claims. | -| Existing-volume legacy PostgreSQL retirement | ACTIVE-PR | Migration/operator work remains separate from already shipped tenant lifecycle. | Do not duplicate its README/architecture/operability surface here. | -| OpenTelemetry installation/operation documentation | ACTIVE-PR | Packaging-extra work remains an overlay until exact lock/install/release evidence integrates. | Keep base installs dependency-light. | -| Durable reconciliation candidate discovery | ACTIVE-PR | Discovery remains unshipped even though the bounded reconciliation primitive and transient session single-flight are protected behavior. | Preserve bounded deterministic tenant-qualified discovery requirements. | -| Tenant-qualified reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | #191 integrated the transient PostgreSQL session advisory-lock seam. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | Keep those non-goals explicit. | -| Atomic durable result application | ACTIVE-PR / end-to-end PARTIAL | Existing checkpoint/stream primitives do not prove complete exactly-once application; #194 remains active candidate work. | Require same-transaction local authority and preserve external-effect limits. | -| Runtime config/schema provisioning and secret policy | ACTIVE-PR / protected compatibility baseline | Protected main permits `SecretStore(require_encryption=False)` and compatibility rows with `is_encrypted = FALSE`; optional Fernet is supported, not mandated. #210 remains an active stricter runtime/operator-contract candidate. | Do not claim mandatory encryption, historical-row migration, rotation/recovery, or external key custody until those contracts integrate. | -| Canonical traceability | ACTIVE-PR | This overlay is the current canonical documentation landing vehicle. #226 and superseded #214 are historical documentation predecessors, not live authority. | Keep stable implementation/test/doc references and no exact heads. | -| Threat model | ACTIVE-PR | `docs/THREAT_MODEL.md` records assets, boundaries, attacker preconditions, mitigations, residual risk, and APA 7th NIST references without claiming certification. | Promote only through normal merge; update residual risk when runtime authority changes. | -| Data governance | ACTIVE-PR | `docs/DATA_GOVERNANCE.md` maps data classes, owners, tenant authority, retention/deletion limits, authorized-content fidelity, and optional Fernet compatibility. | Do not turn evidence readiness into a records-program certification. | -| UML/component/sequence views | ACTIVE-PR | `docs/uml/component-and-sequence.md` shows standalone/embedded composition and tenant-validation sequence. | Keep active-only components off shipped diagrams until integrated. | -| ERD / schema model | ACTIVE-PR | `docs/erd/package-owned-schema.md` maps packaged tables and migration-owned checkpoint identity. | SQL remains stronger authority; refresh only after integrated schema identity changes. | -| General standalone operator guide | PARTIAL | Operator guidance exists across README and topic authorities but no single omnibus `docs/OPERABILITY.md` is protected authority. | Consolidate only after checking adjacent writers. | -| Release governance | PARTIAL | Release-evidence code/workflows exist, but publication remains valid only from a fully accepted exact protected head. | Tie version, CHANGELOG, package, SBOM, provenance, reproducibility, rollback, tag and publication verification together through the release owner. | -| Licensing / third-party notices | PARTIAL | Apache-2.0 source licensing and SBOM evidence exist; acquisition diligence still needs a concise third-party notice process. | Add evidence without making legal-certification claims. | +| `README.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Public entry point for standalone/embedded operation. | Change through its live owner when protected behavior changes. | +| `ARCHITECTURE.md` | IMPLEMENTED-ON-PROTECTED-MAIN | Root architecture is separately owned by the active root-documentation lane. | Keep this PR out of that path. | +| `docs/product/PRD.md` | ACTIVE-PR | Canonical product contract records merged #191, #212, and #228 only at their bounded protected scope. | Revalidate from protected source after every integration. | +| `docs/product/TRD.md` | ACTIVE-PR | Separates transient session exclusion from durable leasing; restore execution from backup/application/PITR; and cluster-identity comparison from connection provenance/authorization. | Keep source/test authority stronger than prose. | +| ADR set | IMPLEMENTED-ON-PROTECTED-MAIN / record-local | ADR 0016 governs custom-format restore seek semantics; ADR 0022 governs restore-target name+cluster identity separation. Other ADRs retain their own status. | Preserve record-local status and collision-free identifiers. | +| `docs/adr/README.md` | ACTIVE-PR | Navigation/status index without exact-head authority. | Keep synchronized with protected ADR files. | +| Tenant lifecycle operator material | IMPLEMENTED-ON-PROTECTED-MAIN | Trusted tenant selection, standalone compatibility, forced RLS, direct-SQL limits, migration, and rollback are documented. | Do not duplicate into competing operator guides. | +| PostgreSQL recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | Receipt/artifact/schema evidence is bounded content-free identity/integrity evidence. | Do not infer restorability, provenance, PITR, or RPO/RTO. | +| PostgreSQL logical backup | ACTIVE-PR | #208 remains a `pg_dump` candidate. | Keep unshipped until normal integration. | +| PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | The logical restore executor is protected-main behavior through merged #212; #209 is historical EOF-defect evidence. | Preserve source trust, environment, transaction, metadata, target, and application-readiness boundaries. | +| PostgreSQL restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | Merged #228 supplies exact service-name plus caller-owned `system_identifier` separation. Same-cluster aliases fail closed. The package does not open/authenticate the connections, execute restore, or prove application/PITR/RPO-RTO readiness. Closed #225 is predecessor lineage only. | Treat the verifier as a bounded precondition, not end-to-end restore authorization. | +| Recovery evidence binding / live reinspection | ACTIVE-PR | Candidate composition/reinspection is not provenance or restore proof. | Keep branch evidence distinct from shipped truth. | +| Post-restore catalog/application acceptance | ACTIVE-PR | #296 is an application-readiness candidate. | Require protected integration before shipped claims. | +| Permanent live PostgreSQL integration acceptance | ACTIVE-PR | #341 owns the branch-level full integration-marker lane and currently tests #296 as a child. | Preserve the lane through normal integration; no mocks/deselection substitution. | +| Physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | Intent/evidence does not prove replay/promotion or achieved objectives. | Require deployment-specific execution and measurement. | +| Existing-volume legacy extension retirement | ACTIVE-PR | Separate migration/operator work. | Do not conflate with tenant lifecycle. | +| Durable reconciliation discovery | ACTIVE-PR | Discovery remains unshipped. | Keep tenant-qualified/bounded/deterministic authority. | +| Tenant-qualified reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | #191 is transient PostgreSQL session advisory locking only. | Never call it a scheduler, durable lease, result-app transaction, terminal-retirement authority, or distributed exactly-once mechanism. | +| Atomic durable result application | ACTIVE-PR / end-to-end PARTIAL | Checkpoint/stream primitives do not prove complete result application. | Keep external-effect limits explicit. | +| Runtime config/schema provisioning and secret policy | ACTIVE-PR / protected compatibility baseline | Protected main permits optional Fernet and `is_encrypted = FALSE` compatibility rows; #210 is stricter active work. | Do not claim mandatory encryption, historical-row migration, rotation/recovery, or external custody. | +| Canonical traceability | ACTIVE-PR | This overlay is the current canonical documentation landing vehicle; #226 and superseded #214 are historical predecessors. | Use stable implementation/test/doc authorities, not exact heads. | +| Threat model | ACTIVE-PR | Assets, boundaries, mitigations, residual risk, and NIST evidence are documented without certification claims. | Keep residual risk synchronized with protected authority. | +| Data governance | ACTIVE-PR | Data classes, owners, retention/deletion, content fidelity, and optional Fernet compatibility are explicit. | Do not turn evidence readiness into certification. | +| UML/component/sequence views | ACTIVE-PR | Standalone/embedded and tenant-validation views exist. | Keep branch-only components off shipped diagrams. | +| ERD / schema model | ACTIVE-PR | Packaged schema and migration-owned checkpoint identity are mapped. | SQL remains stronger authority. | +| Release governance | PARTIAL | Release evidence exists; immutable publication requires the exact accepted protected head. | Tie version, CHANGELOG, package, SBOM, provenance, rollback, tag, and publication verification together through release ownership. | ## Non-negotiable documentation invariants - Protected-main behavior is shipped authority; active PRs and historical branches are not. -- Exact contributor/protected heads, generated merge commits, run IDs, and queue state belong in PR/review evidence, not durable product documents. -- Standalone operation and modular embedding remain co-equal boundaries; no CWL host repository is a hidden runtime dependency. -- Tenant scope comes only from a trusted authenticated/authorized host selection. RLS is defense in depth, not authentication, SQL-injection prevention, or correct identity mapping. -- The standalone `DurableBatchAPIClient` retains its four-argument lifecycle-recorder seam and explicit `standalone` scope unless a reviewed compatibility change integrates. -- Provider/model content never becomes tenant, credential, endpoint, filesystem, or database authority. -- #191 proves only tenant-qualified transient session advisory single-flight; it does not prove a durable lease, scheduler, result-application transaction, terminal retirement, or distributed exactly-once semantics. -- #212 proves the bounded direct logical restore executor and corrected custom-format seek semantics; #209 remains historical EOF-defect evidence. The integrated executor does not prove backup creation, authenticated target isolation, post-restore catalog/application readiness, PITR, or RPO/RTO/HA/DR. -- Protected secret storage supports optional Fernet plus an explicit compatibility mode. Mandatory encrypted-at-rest policy, migration of compatibility rows, key rotation/recovery, and external custody are not inferred. -- Content-fidelity constraints do not prove end-to-end result application. -- Recovery receipts and hashes are evidence primitives, not restoration success. -- Security, privacy, SOC 2, and CSAP material is evidence readiness unless an external certification actually exists. -- Owned coverage, supported Python versions, packaging, SBOM/provenance, rollback, release and bounded-diagnostic requirements remain synchronized with live governance. - -## Fitness gate for future canonical changes - -Before changing a canonical surface, refetch protected main, open PRs, non-default branches, affected source/schema/test authorities, and adjacent documentation writers. Repair the earliest stale authority boundary without widening writer ownership. After a capability merges, update status only after reading the resulting protected tree; after a capability is superseded, keep historical lineage only where it explains a current constraint. Every changed documentation head must reacquire exact-head quality/security/release evidence and qualifying review under the then-live ruleset. +- Exact SHAs, generated merge commits, run IDs, and queue state stay in PR/review evidence. +- Standalone and modular embedding remain co-equal boundaries. +- `tenant_scope` comes from a trusted authenticated/authorized host; RLS is defense in depth, not authentication. +- #191 proves transient tenant-qualified session single-flight, not durable leasing or exactly-once. +- #212 proves bounded direct logical restore with corrected custom-format seek semantics, not backup, application readiness, PITR, or RPO/RTO. +- #228 proves only that supplied exact service names and caller-owned PostgreSQL `system_identifier` values differ. It does not authenticate the connections or collector, execute restore, or prove post-restore application readiness. +- Optional Fernet plus explicit compatibility mode is protected behavior; mandatory encryption/migration/rotation/custody is not inferred. +- Recovery evidence and command success are not equivalent to recovery success. +- SOC 2/CSAP/security/privacy material remains evidence readiness absent external certification. + +## Fitness gate + +Before changing a canonical surface, refetch protected main, open PRs, affected source/schema/tests, current ADRs, and adjacent writers. Repair the earliest stale authority boundary without widening ownership. After a merge, refresh status only from the resulting protected tree; after supersession, retain predecessor context only where it explains a live constraint. Every changed documentation head must reacquire then-required exact-head quality/security/release evidence and qualifying review. From 7400c29464767524b8eeb383b6a3118bb3f0c66e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:44:00 +0900 Subject: [PATCH 49/58] docs(trace): promote merged restore-target cluster verifier --- docs/TRACEABILITY.md | 135 +++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 69 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index a01bee09b..a146530aa 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -2,93 +2,90 @@ ## Purpose and authority -This map ties canonical PRD/TRD requirements to durable protected-main implementation, tests, ADRs, and operator evidence. It intentionally avoids workflow-run IDs, exact commit SHAs, generated merge commits, and transient review/check state. Rows marked **ACTIVE-PR** or **PARTIAL** are not shipped implementation claims. +This map ties canonical PRD/TRD requirements to durable protected-main implementation, tests, ADRs, and operator evidence. It avoids workflow-run IDs, exact SHAs, generated merge commits, and transient review/check state. **ACTIVE-PR** and **PARTIAL** rows are not shipped claims. ## Product-to-technical traceability -| Requirement | Status | Primary protected-main implementation authority | Durable verification/documentation authority | Known gap or active overlay | +| Requirement | Status | Protected-main authority | Durable evidence | Residual boundary / active overlay | | --- | --- | --- | --- | --- | -| FR-1 deterministic bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/orchestrator.py`, `pg_llm_batch/token_counter.py`, package schema | preparation/token tests; `docs/idempotent-preparation.md`; `docs/schema-integrity.md` | No gap claimed by the canonical product contract. | -| FR-2 validated bounded provider interaction | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/batch_api_client.py` | provider URL/resource/retry/response-budget tests; `docs/batch-endpoints.md`; `docs/resource-identifiers.md`; ADR 0015 | Provider-specific widening requires a separately reviewed contract. | -| FR-3 standalone + tenant-qualified durable lifecycle | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/durable_client.py`, `pg_llm_batch/db.py`, schema/RLS objects | tenant lifecycle/integration tests; `ARCHITECTURE.md`; `docs/remote-batch-lifecycle.md`; ADR 0002 | Arbitrary SQL, superuser, and BYPASSRLS remain outside the isolation guarantee. | -| FR-4 scheduler-independent bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation.py` | reconciliation tests and protected-main release gates | Durable candidate discovery remains ACTIVE-PR; autonomous worker semantics remain PARTIAL. | -| FR-4 durable reconciliation candidate discovery | ACTIVE-PR | existing lifecycle/read primitives only | active discovery branch evidence | Candidate selection must remain tenant-qualified, bounded, deterministic, and database-authoritative before integration. | -| FR-4 tenant-qualified cross-process single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/reconciliation_single_flight.py` | focused single-flight exact-type/traceback tests; merged #191 is historical integration evidence | Protected behavior is a transient PostgreSQL session advisory lock only. It is not a scheduler, durable lease, result-application transaction, terminal-work-retirement mechanism, or distributed exactly-once guarantee. | -| FR-4 durable result application + checkpoint coupling | PARTIAL | `pg_llm_batch/result_streaming.py`, `pg_llm_batch/checkpoint_store.py` provide streaming/checkpoint primitives | ADR 0006; ADR 0007; checkpoint/result-streaming tests; `docs/result-streaming.md` | #194 remains ACTIVE-PR same-transaction local work; protected main still does not claim end-to-end or distributed exactly-once application. | -| FR-5 package persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/db.py`, `pg_llm_batch/schema.sql`, Docker schema mirror | schema-integrity, payload, lifecycle, checkpoint migration tests | Existing-volume legacy-extension retirement remains separately active. | -| FR-5 bounded PostgreSQL recovery evidence primitives | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | focused receipt/artifact/schema evidence tests; merged #205/#206/#207 are historical integration evidence | Evidence identifies bounded bytes/metadata; it does not prove backup execution, restorability, live-schema parity, target isolation, PITR, or RPO/RTO/HA/DR. | -| FR-5 executable PostgreSQL logical backup | ACTIVE-PR | no protected-main `pg_dump` executor | #208 branch evidence only | A backup candidate exists but protected main must not be described as creating a restorable backup. | -| FR-5 executable PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/postgres_logical_restore.py` | logical-restore tests and integrated restore-seek ADR/docs; merged #212 is historical integration evidence; closed #209 is predecessor defect evidence | The bounded direct executor accepts custom-format random-access seek behavior and verifies archive metadata instead of final EOF. It does not provide `pg_dump`, authenticated target isolation, post-restore catalog/application readiness, PITR, or RPO/RTO/HA/DR. | -| FR-5 recovery evidence binding and live re-verification | ACTIVE-PR | protected main exposes the underlying receipt/schema/artifact evidence primitives only | active binding/reinspection branch evidence | Bind-time composition and later re-inspection are not provenance, restore proof, or target isolation. | -| FR-5 post-restore catalog/application acceptance | ACTIVE-PR | protected schema/recovery/restore primitives only | active catalog work plus #296 application-readiness candidate | Same-name decoys, key order, constraints, language/function identity, current-role privileges, and live PostgreSQL behavior must fail closed before this can become shipped acceptance. | -| FR-5 permanent live PostgreSQL integration acceptance | ACTIVE-PR | protected main has existing CI but not the #341 permanent integration lane | #341 branch executes `pytest -m integration`; #296 is its active child | Branch-level GREEN does not make the workflow or #296 specimen protected-main truth. | -| FR-5 physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | bounded protected evidence only | active physical/WAL/PITR branch tests and ADR evidence | Intent/evidence does not prove `pg_basebackup`, WAL archive/replay, promotion, or achieved recovery objectives. | -| FR-5 restore-target isolation | PARTIAL | no authenticated target-isolation proof exists on protected main | current recovery acceptance requirements | Distinct service/configuration labels are not proof that two names resolve to different clusters. | -| FR-5 end-to-end PostgreSQL recovery readiness | PARTIAL | bounded evidence primitives plus bounded logical restore executor | issue-level recovery acceptance plus protected recovery tests | No protected isolated restore drill yet proves schema/RLS/constraint/extension parity, migration compatibility, external key/config custody, physical/WAL/PITR recovery, or measured RPO/RTO/HA/DR. | -| FR-5 legacy `http` / `pg_cron` retirement on existing volumes | ACTIVE-PR | protected main does not yet contain the complete retirement migration contract | active migration/smoke/operator evidence | Keep separate from already-shipped tenant lifecycle migration. | -| FR-6 PostgreSQL-backed configuration/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/config.py`, schema | config/secret/bootstrap tests | Protected main supports optional Fernet and explicit compatibility mode. `SecretStore(require_encryption=False)` can persist `is_encrypted = FALSE`; this is not a mandatory encryption-at-rest claim. | -| FR-6 production secret-at-rest policy lifecycle | PARTIAL | callers can opt into `require_encryption=True` with usable Fernet configuration | config/secret/bootstrap tests; #210 active stricter runtime/operator-contract work | Historical compatibility-row migration, key rotation/recovery, external custody, and a mandatory default are not protected guarantees. | -| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/health.py`, bounded error surfaces | health/confidentiality tests and architecture requirements | Broader generic rejected-value confidentiality remains active work. | -| FR-7 generic validation rejected-value confidentiality | ACTIVE-PR | protected `ValidationError` compatibility baseline | active privacy/compatibility branch evidence | Intended safe-default redaction remains unshipped until exact source/governance evidence integrates. | -| FR-7 opt-in OpenTelemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `pg_llm_batch/observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR. | -| FR-8 standalone + modular MSA deployment | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container composition; injectable host seams | `README.md`, `ARCHITECTURE.md`, package/container tests | CWL host repositories are optional integrations, not package runtime dependencies. | -| Exact owned 100% statement/branch coverage | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI configuration and owned production code | coverage gate/tests | Must be re-proven on every changed exact head; predecessor evidence never transfers. | -| Python 3.10/3.12/3.14 validation | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | package metadata/workflow matrix | exact-head repository CI | Queued/skipped/infrastructure-failed jobs are not proof. | -| Reproducible release evidence | IMPLEMENTED-ON-PROTECTED-MAIN | `pg_llm_batch/release_evidence.py` and release workflows | ADR 0003; ADR 0004; release-evidence/artifact-identity tests | Publication itself occurs only from a fully accepted integrated protected head. | -| SBOM/provenance/artifact identity | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | release workflows/evidence helpers | release acceptance and artifact verification tests | Repository evidence does not imply external certification. | -| SOC 2 / CSAP evidence readiness | PARTIAL | security, tenancy, logging, release and governance controls | PRD/TRD/security tests/ADRs | Evidence readiness only; no certification is claimed. | +| FR-1 bounded batch preparation | IMPLEMENTED-ON-PROTECTED-MAIN | `orchestrator.py`, `token_counter.py`, package schema | preparation/token/schema tests | No additional shipped claim inferred. | +| FR-2 bounded provider interaction | IMPLEMENTED-ON-PROTECTED-MAIN | `batch_api_client.py` | endpoint/resource/retry/response-budget tests; ADR 0015 | Provider-specific widening requires review. | +| FR-3 durable lifecycle and tenancy | IMPLEMENTED-ON-PROTECTED-MAIN | `durable_client.py`, `db.py`, schema/RLS | tenant lifecycle/live PostgreSQL tests; ADR 0002 | Arbitrary SQL, `SUPERUSER`, and `BYPASSRLS` remain outside tenant isolation. | +| FR-4 bounded reconciliation | IMPLEMENTED-ON-PROTECTED-MAIN | `reconciliation.py` | reconciliation tests | Durable candidate discovery remains ACTIVE-PR. | +| FR-4 tenant-qualified cross-process single-flight | IMPLEMENTED-ON-PROTECTED-MAIN | `reconciliation_single_flight.py` | focused exact-type/lock/traceback tests; merged #191 is historical integration evidence | Session advisory lock only: not scheduler, durable lease, result application, terminal retirement, or distributed exactly-once. | +| FR-4 durable result application | PARTIAL | `result_streaming.py`, `checkpoint_store.py` primitives | ADR 0006/0007 and tests | #194 remains active; no end-to-end exactly-once claim. | +| FR-5 persistence integrity | IMPLEMENTED-ON-PROTECTED-MAIN | `db.py`, `schema.sql`, Docker schema mirror | schema/payload/lifecycle/checkpoint tests | Existing-volume legacy-extension retirement remains active. | +| FR-5 bounded recovery evidence | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, `postgres_schema_evidence.py` | focused evidence tests; merged #205/#206/#207 are historical integration evidence | Identity/integrity only; not backup execution, provenance, restorability, live parity, PITR, or RPO/RTO. | +| FR-5 executable PostgreSQL logical backup | ACTIVE-PR | no protected `pg_dump` executor | #208 branch evidence | Protected main must not be described as creating a restorable backup. | +| FR-5 executable PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_logical_restore.py` | logical-restore regressions; ADR 0016; merged #212 historical integration evidence; #209 predecessor defect evidence | Custom-format seek + metadata verification is protected. No backup, target-authentication, application-readiness, PITR, or RPO/RTO guarantee. | +| FR-5 restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_restore_target.py` | focused service-name/system-identifier tests; ADR 0022; merged #228 historical integration evidence | Requires distinct exact service names and caller-owned `pg_control_system().system_identifier` values. It does not open/authenticate connections, accept DSNs, execute restore, or prove catalog/application/PITR/RPO-RTO readiness. | +| FR-5 recovery evidence binding/reinspection | ACTIVE-PR | underlying protected evidence primitives only | active binding/reinspection branches | Composition/reinspection is not provenance or restore proof. | +| FR-5 post-restore catalog/application acceptance | ACTIVE-PR | protected schema/recovery/restore/target primitives only | active catalog work and #296 application-readiness branch | Exact catalog/function/privilege/live behavior must integrate before becoming shipped acceptance. | +| FR-5 permanent live PostgreSQL integration lane | ACTIVE-PR | current protected CI does not yet contain #341 lane | #341 branch executes the complete integration marker; #296 is its tested child | Branch GREEN is not protected-main workflow authority. | +| FR-5 physical/WAL/PITR recovery | ACTIVE-PR / PARTIAL | bounded protected evidence only | active physical/WAL/PITR branch evidence | Does not prove basebackup, WAL replay, promotion, or achieved objectives. | +| FR-5 end-to-end recovery readiness | PARTIAL | evidence primitives + logical restore + target cluster-identity verifier | protected focused tests plus active acceptance work | Still missing integrated backup execution, connection provenance/authorization, application/catalog parity, migration/key custody, physical/WAL/PITR, and measured RPO/RTO/HA/DR. | +| FR-6 PostgreSQL-backed config/secrets | IMPLEMENTED-ON-PROTECTED-MAIN | `config.py`, schema | config/secret/bootstrap tests | Optional Fernet + base64 compatibility are protected; mandatory policy is not. | +| FR-6 production secret-at-rest lifecycle | PARTIAL | opt-in `require_encryption=True` path | config/secret tests; #210 active work | Compatibility-row migration, rotation/recovery, external key custody, and mandatory default remain unshipped. | +| FR-7 bounded diagnostics/readiness | IMPLEMENTED-ON-PROTECTED-MAIN | `health.py`, bounded error surfaces | health/confidentiality tests | Broader rejected-value confidentiality remains active work. | +| FR-7 opt-in telemetry | IMPLEMENTED-ON-PROTECTED-MAIN / packaging PARTIAL | `observability.py` | observability tests | First-class locked installation extra remains ACTIVE-PR. | +| FR-8 standalone + modular embedding | IMPLEMENTED-ON-PROTECTED-MAIN | package/CLI/container seams | package/container/docs tests | CWL hosts are optional integrations. | +| Exact owned production coverage/docstrings | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | repository CI | exact-head coverage/docstring gates | Re-prove on every changed head. | +| Python 3.10/3.12/3.14 | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | package/workflow matrix | exact-head CI | Queued/skipped/infrastructure failure is not proof. | +| Reproducible release + SBOM/provenance | IMPLEMENTED-ON-PROTECTED-MAIN governance contract | release-evidence code/workflows | release acceptance/artifact tests | Publication is authoritative only from an accepted protected head. | +| SOC 2 / CSAP evidence readiness | PARTIAL | tenancy/security/logging/release controls | PRD/TRD/security/ADR evidence | No external certification claim. | ## Security and privacy traceability -| Control objective | Protected-main authority | Verification evidence | Residual boundary | +| Control objective | Protected-main authority | Verification | Residual boundary | | --- | --- | --- | --- | -| Trusted tenant selection | `AGENTS.md`, `ARCHITECTURE.md`, tenant validation in DB/durable-client paths | tenant-scope/RLS tests | Host authentication/authorization remains external. | -| RLS defense in depth | tenant-qualified schema and transaction-local scope binding | live PostgreSQL isolation/migration tests | Superuser/BYPASSRLS/arbitrary SQL are administrative bypasses. | -| Provider destination validation | `batch_api_client.py` | endpoint/URL tests | Host/network infrastructure TLS policy is external. | -| Bounded provider input | provider client + result streaming | response/download/JSONL/resource-budget tests | Provider authenticity is not established by payload validation. | -| Reconciliation exclusion | `reconciliation_single_flight.py` | exact-type, lock/release and traceback regressions | Session lifetime is not a durable lease; scheduler and terminal retirement remain separate. | -| Secret/config boundary | `config.py`, bootstrap contract | config/secret/bootstrap tests | Optional Fernet plus compatibility mode are protected behavior; mandatory encryption, compatibility-row migration, rotation/recovery, and external key custody are not. | -| Diagnostic confidentiality | health/error/logging contracts | traceback/health/redaction tests | Generic rejected-value confidentiality remains incomplete on protected main. | -| Checkpoint concurrency/integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not extend to external systems. | -| Recovery evidence confidentiality/integrity | recovery receipt/artifact/schema modules | focused recovery evidence regressions | Evidence does not authenticate an operator, prove target isolation, or prove restore semantics. | -| Logical restore execution | `postgres_logical_restore.py` | custom-format seek, metadata, environment and transactional regressions | Command execution does not prove target identity, application readiness, PITR, or achieved RPO/RTO. | -| Release artifact integrity | `release_evidence.py` + release contracts | descriptor/dirfd/reproducibility tests | Publication credentials and external registry availability remain operational dependencies. | +| Trusted tenant selection | tenant validation + host-boundary docs | tenant/RLS tests | Host authentication/authorization remains external. | +| RLS defense in depth | forced RLS + transaction-local scope | live PostgreSQL isolation/migration tests | Administrative SQL identities bypass the guarantee. | +| Provider destination/input bounds | `batch_api_client.py` | URL/resource/response/download tests | Payload validation does not prove provider authenticity. | +| Reconciliation exclusion | `reconciliation_single_flight.py` | lock/release/exact-type/traceback tests | Session lifetime is not durable leasing. | +| Secret/config boundary | `config.py` | config/secret/bootstrap tests | Optional Fernet does not imply mandatory encryption, rotation, or custody. | +| Diagnostic confidentiality | health/error/logging contracts | health/redaction/traceback tests | Broader generic validation hardening remains active. | +| Checkpoint integrity | `checkpoint_store.py` | CAS/concurrency/RLS/rollback tests | PostgreSQL atomicity does not span external systems. | +| Recovery evidence integrity | receipt/artifact/schema modules | focused evidence tests | No operator authentication, target authority, or restorability proof. | +| Logical restore execution | `postgres_logical_restore.py` | seek/metadata/environment/transaction tests | Command success is not application/PITR/RPO-RTO proof. | +| Restore-target cluster separation | `postgres_restore_target.py` | exact service-name/system-identifier tests | Caller supplies identities from already-opened connections; the package does not authenticate connection provenance or authorize restore. | +| Release artifact integrity | release-evidence contracts | reproducibility/artifact identity | Publication credentials/registry availability remain operational dependencies. | ## Data and persistence traceability -| Data family | Durable identity / authority | Principal protected-main documents | Recovery / non-guarantee | +| Data family | Durable identity / authority | Principal docs | Non-guarantee | | --- | --- | --- | --- | -| Tenant lifecycle state | `(tenant_scope, endpoint_alias, remote_batch_id)` | `ARCHITECTURE.md`, ADR 0002, `docs/remote-batch-lifecycle.md` | Tenant scope must come from trusted host authorization; direct SQL bypass is out of scope. | -| Result checkpoints | `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | ADR 0006, ADR 0007, `docs/result-streaming.md` | Prefix checkpoint is not provider authentication or whole-stream immutability; cross-system exactly-once is not claimed. | -| Package JSONL/payload state | package-owned schema identities and virtual payload references | PRD/TRD, schema-integrity and payload docs/tests | Persisted package data is canonical, not a disposable cache. | -| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD and config tests | Compatibility mode can persist `is_encrypted = FALSE`; optional Fernet support is not a mandatory policy. Migration, key rotation/recovery, and external custody remain separate. | -| PostgreSQL recovery evidence | bounded receipt metadata plus backup/schema SHA-256 and byte-size evidence | protected recovery evidence modules/tests; canonical PRD/TRD | Evidence does not persist a backup, execute backup, prove isolated target parity, or establish PITR/RPO/RTO/HA/DR. | -| Release evidence | descriptor/artifact identity contracts | ADR 0003, ADR 0004 | Evidence proves reviewed artifact identity, not organizational certification. | +| Tenant lifecycle | `(tenant_scope, endpoint_alias, remote_batch_id)` | ADR 0002; lifecycle docs | Host must select tenant authority. | +| Result checkpoint | `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | ADR 0006/0007 | Prefix evidence is not provider authentication or exactly-once. | +| Package payload state | package schema identities | PRD/TRD/schema docs | Canonical persisted business state, not disposable cache. | +| Configuration/secrets | `com_config`, `com_secrets` | PRD/TRD/config tests | Compatibility mode can persist `is_encrypted = FALSE`; optional Fernet is not mandatory policy. | +| Recovery evidence | bounded receipt/hash/size values | recovery modules/tests | Does not persist backups or establish restore/PITR/RPO-RTO. | +| Restore-target identity evidence | exact service names + caller-owned `system_identifier` values | ADR 0022; target module/tests | Difference proves bounded name/cluster separation only, not connection provenance, authorization, or application readiness. | +| Release evidence | descriptor/artifact identity | ADR 0003/0004 | Does not establish organizational certification. | ## Active overlay register -The following open pull requests are represented only as overlays. Their existence does not make their behavior protected-main truth, and this register intentionally avoids volatile Draft/Ready/check-state labels: +The following open PRs are overlays only; their existence does not make behavior protected-main truth: -- **#175** — OpenTelemetry packaging extra; dependency-lock/materialization and final package evidence remain outside protected-main truth. -- **#184** — existing-volume legacy PostgreSQL extension retirement; migration/operator behavior remains active until merged. -- **#190** — durable reconciliation candidate discovery; not protected-main truth. -- **#194** — atomic local result-effect/checkpoint application; same-transaction behavior remains active and is not end-to-end exactly-once proof. -- **#202** — compatibility-aware rejected-value confidentiality hardening; current candidate evidence does not transfer into shipped behavior. -- **#208** — bounded logical PostgreSQL backup executor using `pg_dump`; active source only and not evidence that protected main can create a restorable backup. -- **#210** — configuration/secrets runtime/operator contract successor; least-privilege readiness and stricter policy work remain unshipped until normal integration. -- **#215** — recovery receipt evidence-binding candidate; object composition must not be mistaken for inspection provenance. -- **#219** — physical/WAL/PITR recovery-profile candidate; records caller-owned intent/objectives but does not prove recovery execution. -- **#221** — recovery-receipt live re-inspection candidate; integrity agreement remains time-bound and does not prove restore success or target isolation. -- **#222** — read-only workflow-registry audit candidate; governance tooling remains an overlay until normal integration. -- **#223** — live PostgreSQL restore-catalog acceptance candidate; catalog/index semantics remain unshipped. -- **#229** — current canonical documentation landing vehicle. It repairs stale capability classification without taking ownership of root `ARCHITECTURE.md`, `CHANGELOG.md`, or product-gap-baseline paths. -- **#296** — isolated restore application-readiness candidate; branch evidence proves bounded catalog/language/privilege checks but not end-to-end recovery readiness. -- **#341** — permanent live PostgreSQL integration-lane candidate; current branch evidence executes the full integration marker and carries #296 as a tested child, but the workflow is not protected-main authority until normal integration. +- **#175** — first-class OpenTelemetry packaging extra. +- **#184** — existing-volume legacy PostgreSQL extension retirement. +- **#190** — durable reconciliation candidate discovery. +- **#194** — atomic local result-effect/checkpoint application. +- **#202** — generic rejected-value confidentiality hardening. +- **#208** — bounded logical PostgreSQL backup executor using `pg_dump`. +- **#210** — stricter configuration/secrets runtime/operator contract. +- **#215** — recovery receipt evidence binding. +- **#219** — physical/WAL/PITR recovery profile. +- **#221** — recovery receipt live reinspection. +- **#222** — read-only workflow-registry audit. +- **#223** — live PostgreSQL restore-catalog acceptance. +- **#229** — current canonical documentation landing vehicle; it does not own root `ARCHITECTURE.md`, `CHANGELOG.md`, or the product-gap baseline. +- **#296** — isolated restore application-readiness candidate. +- **#341** — permanent live PostgreSQL integration-lane candidate. -Merged #191 and #212 are protected-main history, not active overlays. Closed documentation predecessors #214 and #226 are superseded historical lineage; they explain why this overlay avoids transient PR-state instructions but are not current authority. Closed recovery predecessors including #209 remain historical defect evidence only where they explain a current safety invariant. +Merged #191, #212, and #228 are protected-main history rather than active overlays. Closed #225 is superseded restore-target predecessor lineage; closed #209 remains defect evidence for the invalid EOF restore postcondition. Closed documentation predecessors #214 and #226 are superseded historical lineage only. -This register is descriptive, not a substitute for refetching GitHub. Before changing a status, verify the PR still exists, its current contributor head, live protected-main ancestry, reviews/threads, exact-head gates, and resulting protected integration. +This register is descriptive, not a substitute for refetching live GitHub state. ## Change-control rule -When a capability merges, update the PRD/TRD status and this traceability map only after reading the new protected-main tree. When a capability is abandoned or superseded, retain historical context only where it explains a live constraint. New requirements must identify an intended implementation authority and deterministic verification authority before they can be called acquisition-ready. +After a capability merges, change canonical status only after reading the resulting protected tree. After abandonment or supersession, retain predecessor context only where it explains a current constraint. New requirements need an intended implementation authority and deterministic verification authority before they are acquisition-ready. From 39a290220fd4d87b82d05e83a21f593447a4a38b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:44:15 +0900 Subject: [PATCH 50/58] docs(adr): index integrated restore-target decision --- docs/adr/README.md | 46 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index 446e3e044..0089183a7 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -2,51 +2,35 @@ ## Authority -This index is a navigation and status aid for architecture decision records present on the protected default branch. The decision record itself remains normative for its context, decision, consequences, security boundary, and supersession rules. - -The index intentionally does not embed an exact protected commit SHA. Pull requests, historical branches, generated merge commits, workflow runs, and review comments are evidence rather than durable architecture authority. +This index is a navigation/status aid for ADRs present on the protected default branch. Each ADR remains normative for its own context, decision, consequences, security boundary, and supersession rules. Exact protected/contributor SHAs, workflow runs, generated merge commits, and review comments are intentionally excluded from durable architecture authority. ## Protected-main decisions | ADR | Decision | Document status | Protected-main applicability | | --- | --- | --- | --- | -| [0002](0002-tenant-scoped-lifecycle.md) | Tenant-scoped durable lifecycle state | Accepted | Defines trusted host-selected `tenant_scope`, tenant-qualified lifecycle identity, transaction-local RLS binding, and standalone compatibility. | -| [0003](0003-reproducible-release-evidence.md) | Reproducible release evidence before publication | Proposed | Records the reproducibility/evidence design while retaining the ADR's own `Proposed` status. Related implementation does not silently promote the decision status. | -| [0004](0004-descriptor-pinned-release-artifact-verification.md) | Descriptor-pinned release artifact verification | Proposed | Records descriptor-pinned TOCTOU hardening while retaining the record-local `Proposed` status. | -| [0006](0006-resumable-result-checkpoints.md) | Resumable provider-result checkpoints | Accepted | Defines immutable prefix checkpoint evidence and its prefix-only, non-authentication, non-whole-stream boundary. | -| [0007](0007-durable-result-checkpoint-store.md) | Durable tenant-isolated result checkpoint store | Accepted | Adds PostgreSQL persistence, tenant isolation, compare-and-swap concurrency, and a caller-owned transaction seam without a distributed exactly-once claim. | -| [0015](0015-http-425-too-early-retry.md) | HTTP 425 retry for bounded idempotent GETs | Accepted for the bounded retry slice | Keeps the default GET retry-status set closed, side-effecting POSTs single-attempt, and TLS/certificate/fingerprint failures outside automatic retry. | -| [0016](0016-postgres-logical-restore-seek.md) | PostgreSQL custom-format logical restore seek semantics | Accepted for the bounded direct-restore slice | Integrated with #212. Final descriptor EOF is not a completion invariant for random-access custom archives; archive metadata verification and transactional failure handling remain bounded by the executor contract. This decision does not establish backup creation, authenticated target isolation, post-restore application readiness, PITR, or RPO/RTO/HA/DR. | +| [0002](0002-tenant-scoped-lifecycle.md) | Tenant-scoped durable lifecycle state | Accepted | Trusted host-selected `tenant_scope`, tenant-qualified identity, transaction-local RLS binding, and standalone compatibility. | +| [0003](0003-reproducible-release-evidence.md) | Reproducible release evidence before publication | Proposed | Retains record-local `Proposed` status even where related implementation exists. | +| [0004](0004-descriptor-pinned-release-artifact-verification.md) | Descriptor-pinned release artifact verification | Proposed | Retains record-local `Proposed` status; implementation presence does not silently accept the decision. | +| [0006](0006-resumable-result-checkpoints.md) | Resumable provider-result checkpoints | Accepted | Immutable prefix checkpoint evidence; not provider authentication or whole-stream immutability. | +| [0007](0007-durable-result-checkpoint-store.md) | Durable tenant-isolated result checkpoint store | Accepted | PostgreSQL persistence, tenant isolation, CAS concurrency, and caller-owned transaction seam without distributed exactly-once. | +| [0015](0015-http-425-too-early-retry.md) | HTTP 425 retry for bounded idempotent GETs | Accepted for the bounded retry slice | Keeps the automatic GET retry set closed and side-effecting POSTs single-attempt. | +| [0016](0016-postgres-logical-restore-seek.md) | PostgreSQL custom-format logical restore seek semantics | Accepted for the bounded direct-restore slice | Integrated with #212. Final descriptor EOF is not a valid completion invariant for random-access custom archives; metadata verification and transactional failure semantics remain bounded by the executor. No backup, target-authentication, application-readiness, PITR, or RPO/RTO/HA/DR guarantee follows. | +| [0022](0022-postgres-restore-target-isolation.md) | Restore-target service-name and PostgreSQL cluster-identity separation | Accepted for the bounded restore-target identity seam | Integrated with merged #228. Exact live/restore service names and caller-owned `pg_control_system().system_identifier` values must differ. The package does not open/authenticate connections, accept DSNs/passwords, execute restore, or prove application/PITR/RPO-RTO readiness. | -Protected main also contains bounded PostgreSQL recovery-evidence primitives in `postgres_recovery_receipt.py`, `postgres_backup_evidence.py`, and `postgres_schema_evidence.py`. Their integration did not create an implicit ADR. They remain implementation/evidence contracts recorded by the PRD/TRD/traceability map. The direct logical-restore executor is separately governed by ADR 0016; executable logical backup and end-to-end recovery remain active/partial work. +Protected main also contains bounded recovery-receipt/artifact/schema evidence primitives. Their integration does not create implicit ADRs. Direct logical restore is governed by ADR 0016; bounded restore-target cluster separation is governed by ADR 0022. Logical backup, post-restore application acceptance, physical/WAL/PITR recovery, external key custody, and end-to-end recovery remain separately governed capabilities. ## Numbering and missing identifiers -ADR numbers are stable identifiers, not a promise of contiguous numbering. A missing number does not establish that a decision is rejected, accepted elsewhere, or safe to reconstruct from an old branch. Gaps may reflect historical work, superseded proposals, unmerged branches, or reserved identifiers. Only a reviewed protected-main document may establish the status of a missing number. - -New ADRs should use a repository-approved stable identifier rather than renumbering existing records. Renaming an integrated ADR changes external references and is an architecture-governance migration, not cosmetic cleanup. +ADR numbers are stable identifiers, not a promise of contiguous numbering. Missing numbers may reflect historical work, superseded proposals, unmerged branches, or reserved identifiers. A gap does not authorize reconstruction from an old branch. New records use a repository-approved stable identifier; renaming an integrated ADR is an architecture-governance migration rather than cosmetic cleanup. ## Decision status versus implementation status -ADR status answers whether an architectural decision is accepted, proposed, deprecated, or superseded. It is not interchangeable with product implementation status. - -The canonical product/technical documents use `IMPLEMENTED-ON-PROTECTED-MAIN`, `ACTIVE-PR`, `PARTIAL`, `PLANNED`, and `SUPERSEDED` for implementation truth. A `Proposed` ADR can coexist with related code on protected main, and an `Accepted` ADR can describe a bounded decision whose larger product capability remains partial. Do not infer one status system from the other. - -When an ADR and protected-main implementation appear inconsistent, treat the inconsistency as a defect to reconcile explicitly rather than editing the index to hide it. +ADR status is not product implementation status. Canonical product documents use `IMPLEMENTED-ON-PROTECTED-MAIN`, `ACTIVE-PR`, `PARTIAL`, `PLANNED`, and `SUPERSEDED`. A `Proposed` ADR may coexist with code on protected main, while an `Accepted` ADR may govern only a bounded slice of a larger partial capability. When ADR and protected implementation appear inconsistent, reconcile the defect explicitly rather than hiding it in the index. ## Supersession and amendments -A decision is superseded only when a reviewed record or amendment says so explicitly. A later implementation, issue, pull request, or historical branch does not implicitly supersede an ADR. - -For a material architecture change: - -1. refetch protected main and source/documentation writers touching the decision boundary; -2. identify existing ADRs and product/technical requirements that constrain the change; -3. record the decision or explicit amendment, including rejected alternatives and material operational/security consequences; -4. keep active/unmerged behavior classified as an overlay rather than protected-main truth; -5. update traceability after the capability reaches protected main; and -6. preserve standalone operation and modular MSA embedding unless a separately accepted decision changes that product contract. +A decision is superseded only by an explicit reviewed record/amendment. Later code, issues, PRs, or historical branches do not implicitly supersede it. Material changes require a fresh read of protected source and adjacent writers, explicit alternatives/rejected reasons/consequences, correct active-vs-shipped classification, and traceability refresh after integration. -## Non-guarantees that must remain visible +## Non-guarantees -The current ADR set does not establish authentication from PostgreSQL RLS alone, provider authenticity from result checkpointing, full-stream immutability from a prefix checkpoint, distributed exactly-once processing, retry permission for arbitrary HTTP failures, backup restorability or PITR/RPO/RTO/HA/DR from recovery evidence or direct restore execution alone, or organizational security/compliance certification. Those boundaries must not be weakened by summaries, operator docs, marketing material, or future ADR titles. +The ADR set does not establish authentication from RLS, provider authenticity from checkpointing, distributed exactly-once processing, arbitrary HTTP retry permission, backup restorability, authenticated connection provenance, post-restore application readiness, PITR/RPO/RTO/HA/DR from recovery evidence/direct restore/`system_identifier` comparison alone, or organizational certification. From 314c8b5dcbd197a71e02404fd9ccbd4dc1828faf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:44:42 +0900 Subject: [PATCH 51/58] docs(security): model bounded restore-target identity trust --- docs/THREAT_MODEL.md | 139 +++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 84 deletions(-) diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md index 5924b931f..9a97657d7 100644 --- a/docs/THREAT_MODEL.md +++ b/docs/THREAT_MODEL.md @@ -2,113 +2,84 @@ ## Authority -This model describes protected-main `pg-llm-batch` assets, trust boundaries, -attacker capabilities, package mitigations, and residual risk. It is evidence -readiness for SOC 2 / CSAP preparation. It is not a certification, a penetration -test, or a claim that a deployment is authorized for production. - -Use it to decide the next host control, not to infer that PostgreSQL row-level -security, recovery receipts, redacted diagnostics, or optional Fernet support -have already closed a business risk. - -The methodology follows data-centric threat modeling (Scarfone & Souppaya, -2016/2016 IPD) and the NIST risk-assessment process (Joint Task Force, 2012): -identify the data, the system where it lives, the relevant threat sources, the -preconditions those sources need, and the residual risk after package controls. -Control families are aligned to NIST SP 800-53 Revision 5 (Joint Task Force, -2020). - -## What to do next - -1. Keep tenant selection behind your authenticated and authorized host boundary. -2. Do not grant arbitrary SQL, `SUPERUSER`, or `BYPASSRLS` to the application - role that runs this package. -3. Preserve authorized business payloads. Do not add blanket PII masking on - prompts, JSONL, or provider results; that would change token counts, replay, - and downstream decisions. -4. Treat recovery receipts and artifact hashes as identity evidence only. They - do not prove a backup is restorable or that a restore target is isolated. -5. Treat Fernet as an optional protected-main mechanism, not a mandatory - encryption-at-rest guarantee. Compatibility mode can persist - `is_encrypted = FALSE`; production policy, migration, key rotation/recovery, - and external key custody remain deployment responsibilities unless a later - integrated contract changes that boundary. -6. Run `standalone` when you are a single-tenant operator. Use - `TenantDurableBatchAPIClient` only after your host has already chosen - `tenant_scope`. +This model describes protected-main `pg-llm-batch` assets, trust boundaries, attacker capabilities, mitigations, and residual risk. It is evidence readiness for SOC 2 / CSAP preparation, not certification, penetration-test evidence, or production authorization. + +The methodology follows data-centric threat modeling and NIST risk assessment: identify data, systems, threat sources, preconditions, controls, and residual risk. Controls are aligned to NIST SP 800-53 Revision 5. + +## What operators must do + +1. Select `tenant_scope` only behind an authenticated and authorized host boundary. +2. Do not grant arbitrary SQL, `SUPERUSER`, or `BYPASSRLS` to ordinary application roles. +3. Preserve authorized business payloads unless an explicit host policy transforms them with provenance and acceptance tests. +4. Treat recovery receipt/hash evidence as identity/integrity metadata, not restorability. +5. Treat Fernet as optional protected-main behavior. Compatibility mode can persist `is_encrypted = FALSE`; production encryption policy, migration, rotation/recovery, and external key custody remain separate responsibilities. +6. Before logical restore, obtain live and restore `system_identifier` values from caller-opened connections and use the protected restore-target verifier. Do not treat that comparison as authentication of the connections or as post-restore application readiness. ## Assets -| Asset | Where it lives | Why a buyer cares | +| Asset | Location | Buyer relevance | | --- | --- | --- | -| Authorized prompts, JSONL payloads, and provider results | `llm_requests`, `llm_batch_file_payloads`, `llm_jsonl_lines`, provider files | Business meaning. Silent masking or truncation invalidates accounting. | -| Durable remote lifecycle identity | `llm_remote_batch_jobs` keyed by `(tenant_scope, endpoint_alias, remote_batch_id)` | Prevents one tenant from observing or advancing another tenant's batch. | -| Result-stream checkpoints | `llm_result_stream_checkpoints` keyed by `(tenant_scope, checkpoint_consumer_name, endpoint_alias, remote_batch_id)` | Prefix resume only. Not provider authenticity or whole-stream immutability. | -| Standalone secrets and configuration | `com_secrets`, `com_config` | Bootstrap transport. Optional Fernet is supported; compatibility mode can still persist `is_encrypted = FALSE`. | -| Provider credentials | Host-injected credential provider or standalone secret store | Never a tenant-selected authority and never a telemetry attribute. | -| Recovery evidence | In-memory receipts plus caller-owned backup/schema bytes | Content-free hash/size identity. Not restorability. | +| Authorized prompts, JSONL, provider results | package payload/request tables and provider files | Business meaning; silent transformation invalidates accounting/replay. | +| Durable lifecycle identity | `(tenant_scope, endpoint_alias, remote_batch_id)` | Cross-tenant lifecycle isolation. | +| Result checkpoints | tenant + consumer + provider identity | Resumable prefix evidence; not whole-stream authenticity. | +| Standalone config/secrets | `com_config`, `com_secrets` | Optional Fernet plus explicit base64 compatibility mode. | +| Provider credentials | host credential provider or standalone store | Never tenant-selected authority or telemetry content. | +| Recovery evidence | receipts/hashes/schema evidence | Content-free identity/integrity, not restore success. | +| Restore target identity | exact libpq service names + caller-owned PostgreSQL `system_identifier` values | Detects same-name and same-cluster aliasing before a host proceeds. | ## Trust boundaries ```text [Caller / operator] - | host authentication and authorization (out of package) + | authentication + authorization + connection provenance (host-owned) v -[Host control plane] -- selects tenant_scope, credentials, DSN, restore target - | package Python API / CLI only +[Host control plane] -- chooses tenant, credentials, DSN/service, recovery target + | package Python API / CLI v -[pg-llm-batch] -- validates, bounds I/O, binds transaction-local set_config - | parameterized SQL +[pg-llm-batch] -- validates and bounds inputs/effects + | parameterized SQL / bounded subprocess seams v -[PostgreSQL] -- forced RLS for lifecycle and checkpoint tables +[PostgreSQL] -- forced tenant RLS + caller-opened recovery connections | - +--> [Provider Batch API] untrusted statuses, IDs, JSON, JSONL - +--> [Caller-owned backup/restore tools] authority bounded by integrated contracts + +--> [Provider Batch API] untrusted external data + +--> [Caller-owned backup/WAL/key infrastructure] ``` -The package does not authenticate callers. `tenant_scope` is routing context -written with parameterized `set_config('pg_llm_batch.tenant_scope', ..., true)`. -A role that can execute arbitrary SQL can choose any scope. RLS is defense in -depth after that trusted write. +`tenant_scope` is routing context written through parameterized transaction-local `set_config`; it is not a credential. A role with arbitrary SQL can choose a custom-setting value. RLS therefore augments, rather than replaces, host authentication/authorization and SQL-injection prevention. -## Threat sources and package mitigations +The restore-target verifier has a similarly bounded trust model. `postgres_restore_target.py` does not open either database connection. The caller supplies service names and `PostgresRestoreTargetIdentity(system_identifier=...)` values collected from already-opened connections. Distinct exact names and identifiers reject obvious same-cluster aliases, but the package does not authenticate the collector, the connection setup, or the mapping from a service name to the supplied identifier. -| Threat source | Needed precondition | Package mitigation on protected main | Residual risk | +## Threat sources and controls + +| Threat source | Needed precondition | Protected-main mitigation | Residual risk | | --- | --- | --- | --- | -| Confused-deputy tenant selection | Host accepts provider IDs, headers, or model output as tenant authority | Tenant clients reject that path; scope is validated before reservation, credentials, provider I/O, or lifecycle SQL | Host mapping bugs remain outside the package. | -| Cross-tenant lifecycle read/write | Application role plus missing or wrong transaction-local scope | Forced RLS default-deny; tenant-qualified unique key and status index | `SUPERUSER` / `BYPASSRLS` / arbitrary SQL bypass the guarantee. | -| SQL injection or generic tenant SQL | Application role exposed through a SQL console | Parameterized statements; documented prohibition on generic SQL | The custom setting is not a credential. Do not grant arbitrary SQL. | -| Provider spoofing or oversized bodies | Network path to an unvalidated URL or unbounded parser | HTTPS production destinations, finite decoded-byte budgets, closed GET retry set `{408, 425, 429, 502, 503, 504}` | Provider authenticity is not proved by payload validation. HTTP 500 and POST stay single-attempt. | -| Secret reflection or weak at-rest policy | Diagnostics expose values, or an operator mistakes compatibility mode for encryption | Bounded error vocabularies; public readiness omits lower-layer text; Fernet can be explicitly required by callers | The default compatibility path is not a production confidentiality guarantee; migration, rotation/recovery, and key custody remain external. | -| Unsafe restore | Operator points restore at the live cluster or treats command success as application readiness | Bounded direct logical restore keeps source trust, environment, transaction, and archive metadata constraints explicit | Authenticated target isolation, application/catalog acceptance, PITR, and achieved RPO/RTO remain separate. | -| Checkpoint fork or replay | Concurrent consumers advance the same identity | CAS `SELECT ... FOR UPDATE` with exact previous checkpoint | PostgreSQL atomicity does not extend to provider or network effects. | -| Content-fidelity sabotage | A privacy filter rewrites authorized payloads | Package paths preserve authorized content unless a reviewed host policy says otherwise | A host that transforms content must keep provenance and acceptance tests. | +| Confused-deputy tenant selection | Host accepts provider/model/transport data as tenant authority | Tenant clients validate host-selected scope before credentials/provider/DB effects | Host identity-mapping bugs remain external. | +| Cross-tenant lifecycle access | Missing/wrong transaction-local scope | Forced RLS, tenant-qualified keys/indexes | Administrative SQL roles bypass the guarantee. | +| SQL injection / generic tenant SQL | Application exposes arbitrary SQL | Parameterized package SQL; generic SQL is outside supported tenant boundary | Host must prevent injection and generic SQL authority. | +| Provider spoofing / oversized input | Untrusted network/provider response | HTTPS production destination policy, finite decode/download budgets, closed reviewed GET retry set | Payload validation does not prove provider authenticity. | +| Secret reflection / weak at-rest policy | Diagnostics expose values or operator mistakes compatibility mode for encryption | Bounded diagnostics; optional Fernet can be explicitly required | Default compatibility rows are not encrypted-at-rest proof; migration/rotation/custody remain external. | +| Restore into live cluster through alias | Different service labels resolve to same PostgreSQL cluster | Merged #228 verifier requires distinct exact service names and distinct caller-owned `pg_control_system().system_identifier` values | Caller may collect/misassociate identity evidence incorrectly; package does not authenticate the connection or authorize restore. | +| Unsafe or semantically incomplete restore | Command succeeds but target/catalog/application is wrong | Merged #212 bounds direct restore execution and archive metadata semantics; #228 bounds target cluster separation | Backup provenance, application/catalog acceptance, migration/key/WAL/PITR and RPO/RTO remain separate. | +| Checkpoint fork/replay | Concurrent consumers mutate same identity | PostgreSQL CAS/locking semantics | DB atomicity does not extend to provider/network effects. | +| Reconciliation overlap | Concurrent workers target same bounded identity | Tenant-qualified transient session advisory single-flight | Session lock is not durable leasing, scheduling, terminal retirement, or exactly-once. | +| Content-fidelity sabotage | Privacy layer silently rewrites authorized payload | Package paths preserve authorized content absent explicit policy | Host transformations require provenance and acceptance tests. | ## Explicit non-guarantees -- This document does not claim SOC 2, CSAP, ISO/IEC 27001, or any other - certification. -- RLS does not replace authentication, authorization, or SQL-injection - prevention. -- Optional Fernet support and redacted diagnostics do not prove that all stored - secrets are encrypted at rest or that key rotation/recovery/custody is solved. -- A recovery receipt, schema hash, backup-artifact hash, or successful bounded - restore command does not prove restorability, authenticated target identity, - application readiness, live-cluster parity, PITR, RPO, RTO, HA, or DR. -- A prefix checkpoint is not a distributed exactly-once claim. -- `standalone` is an explicit single-tenant scope, not an anonymous public mode. +- No SOC 2, CSAP, ISO/IEC 27001, or other certification is claimed. +- RLS does not replace authentication, authorization, or SQL-injection prevention. +- Optional Fernet and redacted diagnostics do not prove all persisted secrets are encrypted or that key lifecycle/custody is solved. +- A receipt/hash does not prove backup provenance or restorability. +- A successful direct restore does not prove application readiness, PITR, or achieved recovery objectives. +- Distinct service names and `system_identifier` values prove only the bounded evidence supplied to the verifier differs; they do not authenticate connection provenance or authorize destructive recovery. +- Prefix checkpoints and session advisory locks are not distributed exactly-once guarantees. ## References -Joint Task Force. (2012). *Guide for conducting risk assessments* (NIST Special -Publication 800-30, Revision 1). National Institute of Standards and Technology. -https://doi.org/10.6028/NIST.SP.800-30r1 +Joint Task Force. (2012). *Guide for conducting risk assessments* (NIST Special Publication 800-30, Revision 1). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-30r1 + +Joint Task Force. (2020). *Security and privacy controls for information systems and organizations* (NIST Special Publication 800-53, Revision 5). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-53r5 -Joint Task Force. (2020). *Security and privacy controls for information systems -and organizations* (NIST Special Publication 800-53, Revision 5). National -Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-53r5 +Scarfone, K., & Souppaya, M. (2016). *Guide to data-centric system threat modeling* (NIST Special Publication 800-154, Initial Public Draft). National Institute of Standards and Technology. https://csrc.nist.gov/pubs/sp/800/154/ipd -Scarfone, K., & Souppaya, M. (2016). *Guide to data-centric system threat -modeling* (NIST Special Publication 800-154, Initial Public Draft). National -Institute of Standards and Technology. -https://csrc.nist.gov/pubs/sp/800/154/ipd +Swanson, M., Bowen, P., Phillips, A., Gallup, D., & Lynes, D. (2010). *Contingency planning guide for federal information systems* (NIST Special Publication 800-34 Rev. 1). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-34r1 From 7f3acbd8b71a2a4d41d282f9b8a488c0b6468a55 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:47:06 +0900 Subject: [PATCH 52/58] test(docs): align historical lineage and capability assertions --- tests/test_canonical_status_vocabulary.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_canonical_status_vocabulary.py b/tests/test_canonical_status_vocabulary.py index 00fb6d059..5a9528b2a 100644 --- a/tests/test_canonical_status_vocabulary.py +++ b/tests/test_canonical_status_vocabulary.py @@ -77,7 +77,7 @@ def test_product_contract_records_integrated_single_flight_without_lease_claim() traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") assert "| Cross-process reconciliation single-flight | IMPLEMENTED-ON-PROTECTED-MAIN |" in prd - assert "tenant-qualified session advisory single-flight is protected-main behavior" in trd + assert "session advisory single-flight" in trd assert "| FR-4 tenant-qualified cross-process single-flight | IMPLEMENTED-ON-PROTECTED-MAIN |" in traceability for document in (prd, trd, traceability): lowered = document.lower() @@ -149,7 +149,7 @@ def test_product_contract_names_active_recovery_capability_families() -> None: def test_canonical_overlay_register_preserves_superseded_lineage_without_live_status() -> None: - """Historical documentation predecessors may be named without becoming active overlays.""" + """Historical predecessors may remain as lineage without becoming active overlays.""" traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") @@ -158,7 +158,8 @@ def test_canonical_overlay_register_preserves_superseded_lineage_without_live_st assert "superseded" in traceability.lower() assert "keep it Draft" not in traceability assert "keep it Ready" not in traceability - assert "#225" not in traceability + assert "#225" in traceability + assert "superseded restore-target predecessor" in traceability assert "#226" in fitness assert "superseded #214" in fitness assert "current canonical documentation landing vehicle" in traceability From ced97afb1917406eb9c4c2b818653f1b788c10cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:47:27 +0900 Subject: [PATCH 53/58] docs: preserve owned overlay path fitness contracts --- docs/DOCUMENTATION_FITNESS.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 23ab16e30..704009ccc 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -33,10 +33,10 @@ Protected main contains the tenant lifecycle/RLS contract, bounded reconciliatio | Atomic durable result application | ACTIVE-PR / end-to-end PARTIAL | Checkpoint/stream primitives do not prove complete result application. | Keep external-effect limits explicit. | | Runtime config/schema provisioning and secret policy | ACTIVE-PR / protected compatibility baseline | Protected main permits optional Fernet and `is_encrypted = FALSE` compatibility rows; #210 is stricter active work. | Do not claim mandatory encryption, historical-row migration, rotation/recovery, or external custody. | | Canonical traceability | ACTIVE-PR | This overlay is the current canonical documentation landing vehicle; #226 and superseded #214 are historical predecessors. | Use stable implementation/test/doc authorities, not exact heads. | -| Threat model | ACTIVE-PR | Assets, boundaries, mitigations, residual risk, and NIST evidence are documented without certification claims. | Keep residual risk synchronized with protected authority. | -| Data governance | ACTIVE-PR | Data classes, owners, retention/deletion, content fidelity, and optional Fernet compatibility are explicit. | Do not turn evidence readiness into certification. | -| UML/component/sequence views | ACTIVE-PR | Standalone/embedded and tenant-validation views exist. | Keep branch-only components off shipped diagrams. | -| ERD / schema model | ACTIVE-PR | Packaged schema and migration-owned checkpoint identity are mapped. | SQL remains stronger authority. | +| `docs/THREAT_MODEL.md` | ACTIVE-PR | Assets, boundaries, mitigations, residual risk, and NIST evidence are documented without certification claims. | Keep residual risk synchronized with protected authority. | +| `docs/DATA_GOVERNANCE.md` | ACTIVE-PR | Data classes, owners, retention/deletion, content fidelity, and optional Fernet compatibility are explicit. | Do not turn evidence readiness into certification. | +| `docs/uml/component-and-sequence.md` | ACTIVE-PR | Standalone/embedded and tenant-validation views exist. | Keep branch-only components off shipped diagrams. | +| `docs/erd/package-owned-schema.md` | ACTIVE-PR | Packaged schema and migration-owned checkpoint identity are mapped. | SQL remains stronger authority. | | Release governance | PARTIAL | Release evidence exists; immutable publication requires the exact accepted protected head. | Tie version, CHANGELOG, package, SBOM, provenance, rollback, tag, and publication verification together through release ownership. | ## Non-negotiable documentation invariants From c7b32be9615862c27ea82536e3a7004f8d4afb98 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 08:47:49 +0900 Subject: [PATCH 54/58] docs(security): restore tested asset identifiers and standalone action --- docs/THREAT_MODEL.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md index 9a97657d7..36666a2e5 100644 --- a/docs/THREAT_MODEL.md +++ b/docs/THREAT_MODEL.md @@ -14,14 +14,15 @@ The methodology follows data-centric threat modeling and NIST risk assessment: i 4. Treat recovery receipt/hash evidence as identity/integrity metadata, not restorability. 5. Treat Fernet as optional protected-main behavior. Compatibility mode can persist `is_encrypted = FALSE`; production encryption policy, migration, rotation/recovery, and external key custody remain separate responsibilities. 6. Before logical restore, obtain live and restore `system_identifier` values from caller-opened connections and use the protected restore-target verifier. Do not treat that comparison as authentication of the connections or as post-restore application readiness. +7. Use the explicit `standalone` scope for a single-tenant operator; do not reinterpret it as anonymous public tenancy. ## Assets | Asset | Location | Buyer relevance | | --- | --- | --- | | Authorized prompts, JSONL, provider results | package payload/request tables and provider files | Business meaning; silent transformation invalidates accounting/replay. | -| Durable lifecycle identity | `(tenant_scope, endpoint_alias, remote_batch_id)` | Cross-tenant lifecycle isolation. | -| Result checkpoints | tenant + consumer + provider identity | Resumable prefix evidence; not whole-stream authenticity. | +| Durable lifecycle identity | `llm_remote_batch_jobs`, keyed by `(tenant_scope, endpoint_alias, remote_batch_id)` | Cross-tenant lifecycle isolation. | +| Result checkpoints | `llm_result_stream_checkpoints`, keyed by tenant + consumer + provider identity | Resumable prefix evidence; not whole-stream authenticity. | | Standalone config/secrets | `com_config`, `com_secrets` | Optional Fernet plus explicit base64 compatibility mode. | | Provider credentials | host credential provider or standalone store | Never tenant-selected authority or telemetry content. | | Recovery evidence | receipts/hashes/schema evidence | Content-free identity/integrity, not restore success. | @@ -66,7 +67,7 @@ The restore-target verifier has a similarly bounded trust model. `postgres_resto ## Explicit non-guarantees -- No SOC 2, CSAP, ISO/IEC 27001, or other certification is claimed. +- This document does not claim SOC 2, CSAP, ISO/IEC 27001, or another certification. - RLS does not replace authentication, authorization, or SQL-injection prevention. - Optional Fernet and redacted diagnostics do not prove all persisted secrets are encrypted or that key lifecycle/custody is solved. - A receipt/hash does not prove backup provenance or restorability. From 792c24eb713a6201761bd453adebf5f29a2c4eb1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 11:05:21 +0900 Subject: [PATCH 55/58] docs(recovery): record PITR target observation boundary --- docs/DOCUMENTATION_FITNESS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 704009ccc..c6a46d464 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -23,6 +23,7 @@ Protected main contains the tenant lifecycle/RLS contract, bounded reconciliatio | PostgreSQL logical backup | ACTIVE-PR | #208 remains a `pg_dump` candidate. | Keep unshipped until normal integration. | | PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | The logical restore executor is protected-main behavior through merged #212; #209 is historical EOF-defect evidence. | Preserve source trust, environment, transaction, metadata, target, and application-readiness boundaries. | | PostgreSQL restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN / end-to-end PARTIAL | Merged #228 supplies exact service-name plus caller-owned `system_identifier` separation. Same-cluster aliases fail closed. The package does not open/authenticate the connections, execute restore, or prove application/PITR/RPO-RTO readiness. Closed #225 is predecessor lineage only. | Treat the verifier as a bounded precondition, not end-to-end restore authorization. | +| Effective PITR target configuration observation | ACTIVE-PR | #299 reads exactly eight PostgreSQL recovery-target settings plus `pg_is_in_recovery()` from a caller-owned isolated target and compares them with reviewed target authority. The functions remain module-scoped rather than root-package exports. | Keep fixed-query, timeout-ownership, public-surface, README/CHANGELOG/ADR/doctoring work with their live owners; do not promote branch evidence to shipped PITR proof. | | Recovery evidence binding / live reinspection | ACTIVE-PR | Candidate composition/reinspection is not provenance or restore proof. | Keep branch evidence distinct from shipped truth. | | Post-restore catalog/application acceptance | ACTIVE-PR | #296 is an application-readiness candidate. | Require protected integration before shipped claims. | | Permanent live PostgreSQL integration acceptance | ACTIVE-PR | #341 owns the branch-level full integration-marker lane and currently tests #296 as a child. | Preserve the lane through normal integration; no mocks/deselection substitution. | @@ -48,6 +49,7 @@ Protected main contains the tenant lifecycle/RLS contract, bounded reconciliatio - #191 proves transient tenant-qualified session single-flight, not durable leasing or exactly-once. - #212 proves bounded direct logical restore with corrected custom-format seek semantics, not backup, application readiness, PITR, or RPO/RTO. - #228 proves only that supplied exact service names and caller-owned PostgreSQL `system_identifier` values differ. It does not authenticate the connections or collector, execute restore, or prove post-restore application readiness. +- #299 is an ACTIVE-PR fixed-query observation of effective recovery-target settings on a caller-owned isolated target. Its functions are module-scoped, it owns no connection timeout, and it does not prove WAL completeness, target attainment, promotion, application readiness, PITR success, or achieved RPO/RTO. - Optional Fernet plus explicit compatibility mode is protected behavior; mandatory encryption/migration/rotation/custody is not inferred. - Recovery evidence and command success are not equivalent to recovery success. - SOC 2/CSAP/security/privacy material remains evidence readiness absent external certification. From 221fd5219ec39b0d3cb1bf91e7e95e3a07809213 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 11:05:49 +0900 Subject: [PATCH 56/58] docs(traceability): track recovery target observation overlay --- docs/TRACEABILITY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index a146530aa..8022da58a 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -19,6 +19,7 @@ This map ties canonical PRD/TRD requirements to durable protected-main implement | FR-5 executable PostgreSQL logical backup | ACTIVE-PR | no protected `pg_dump` executor | #208 branch evidence | Protected main must not be described as creating a restorable backup. | | FR-5 executable PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_logical_restore.py` | logical-restore regressions; ADR 0016; merged #212 historical integration evidence; #209 predecessor defect evidence | Custom-format seek + metadata verification is protected. No backup, target-authentication, application-readiness, PITR, or RPO/RTO guarantee. | | FR-5 restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_restore_target.py` | focused service-name/system-identifier tests; ADR 0022; merged #228 historical integration evidence | Requires distinct exact service names and caller-owned `pg_control_system().system_identifier` values. It does not open/authenticate connections, accept DSNs, execute restore, or prove catalog/application/PITR/RPO-RTO readiness. | +| FR-5 effective PITR target configuration observation | ACTIVE-PR | no protected recovery-target configuration observer | #299 fixed-query source/tests plus canonical documentation overlay | Exactly eight reviewed recovery-target settings plus `pg_is_in_recovery()` are observed from a caller-owned isolated target. The APIs remain module-scoped; no connection timeout is imposed; no WAL completeness, target attainment, promotion, application readiness, PITR success, or achieved RPO/RTO is proved. | | FR-5 recovery evidence binding/reinspection | ACTIVE-PR | underlying protected evidence primitives only | active binding/reinspection branches | Composition/reinspection is not provenance or restore proof. | | FR-5 post-restore catalog/application acceptance | ACTIVE-PR | protected schema/recovery/restore/target primitives only | active catalog work and #296 application-readiness branch | Exact catalog/function/privilege/live behavior must integrate before becoming shipped acceptance. | | FR-5 permanent live PostgreSQL integration lane | ACTIVE-PR | current protected CI does not yet contain #341 lane | #341 branch executes the complete integration marker; #296 is its tested child | Branch GREEN is not protected-main workflow authority. | @@ -48,6 +49,7 @@ This map ties canonical PRD/TRD requirements to durable protected-main implement | Recovery evidence integrity | receipt/artifact/schema modules | focused evidence tests | No operator authentication, target authority, or restorability proof. | | Logical restore execution | `postgres_logical_restore.py` | seek/metadata/environment/transaction tests | Command success is not application/PITR/RPO-RTO proof. | | Restore-target cluster separation | `postgres_restore_target.py` | exact service-name/system-identifier tests | Caller supplies identities from already-opened connections; the package does not authenticate connection provenance or authorize restore. | +| Recovery-target configuration observation | no protected-main implementation | #299 fixed-query branch tests and canonical docs | Caller owns connection/timeouts. Module-scoped branch APIs do not prove WAL completeness, exact stop semantics, promotion, application readiness, PITR success, or achieved RPO/RTO. | | Release artifact integrity | release-evidence contracts | reproducibility/artifact identity | Publication credentials/registry availability remain operational dependencies. | ## Data and persistence traceability @@ -80,6 +82,7 @@ The following open PRs are overlays only; their existence does not make behavior - **#223** — live PostgreSQL restore-catalog acceptance. - **#229** — current canonical documentation landing vehicle; it does not own root `ARCHITECTURE.md`, `CHANGELOG.md`, or the product-gap baseline. - **#296** — isolated restore application-readiness candidate. +- **#299** — effective recovery-target configuration observation on a caller-owned isolated target; functions remain module-scoped pending explicit public-surface decision. - **#341** — permanent live PostgreSQL integration-lane candidate. Merged #191, #212, and #228 are protected-main history rather than active overlays. Closed #225 is superseded restore-target predecessor lineage; closed #209 remains defect evidence for the invalid EOF restore postcondition. Closed documentation predecessors #214 and #226 are superseded historical lineage only. From 045e42b3db7fa47e3e29d3fdbe7531d9e96d6d62 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 11:06:16 +0900 Subject: [PATCH 57/58] test(docs): pin PITR observation documentation boundary --- tests/test_canonical_status_vocabulary.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_canonical_status_vocabulary.py b/tests/test_canonical_status_vocabulary.py index 5a9528b2a..8d62eb13b 100644 --- a/tests/test_canonical_status_vocabulary.py +++ b/tests/test_canonical_status_vocabulary.py @@ -132,6 +132,7 @@ def test_active_overlay_register_excludes_merged_or_closed_recovery_predecessors assert 225 not in active_numbers assert 228 not in active_numbers assert 296 in active_numbers + assert 299 in active_numbers assert 341 in active_numbers @@ -163,3 +164,20 @@ def test_canonical_overlay_register_preserves_superseded_lineage_without_live_st assert "#226" in fitness assert "superseded #214" in fitness assert "current canonical documentation landing vehicle" in traceability + + +def test_recovery_target_configuration_overlay_stays_bounded_and_module_scoped() -> None: + """The #299 overlay must record fixed-query limits without inventing a public API.""" + fitness = _read(REPOSITORY_ROOT / "docs" / "DOCUMENTATION_FITNESS.md") + traceability = _read(REPOSITORY_ROOT / "docs" / "TRACEABILITY.md") + package_init = _read(REPOSITORY_ROOT / "pg_llm_batch" / "__init__.py") + + for document in (fitness, traceability): + assert "#299" in document + assert "eight PostgreSQL recovery-target settings" in document + assert "pg_is_in_recovery()" in document + assert "module-scoped" in document + assert "RPO/RTO" in document + + assert "observe_postgres_recovery_target_configuration" not in package_init + assert "postgres_recovery_target_configuration_was_observed" not in package_init From bf6dd65d716a7324cf3ac1291dcedfae556fe666 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 11 Sep 2026 11:09:04 +0900 Subject: [PATCH 58/58] fix(docs): align PITR observation traceability contract --- docs/TRACEABILITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 8022da58a..2dd42737a 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -19,7 +19,7 @@ This map ties canonical PRD/TRD requirements to durable protected-main implement | FR-5 executable PostgreSQL logical backup | ACTIVE-PR | no protected `pg_dump` executor | #208 branch evidence | Protected main must not be described as creating a restorable backup. | | FR-5 executable PostgreSQL logical restore | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_logical_restore.py` | logical-restore regressions; ADR 0016; merged #212 historical integration evidence; #209 predecessor defect evidence | Custom-format seek + metadata verification is protected. No backup, target-authentication, application-readiness, PITR, or RPO/RTO guarantee. | | FR-5 restore-target cluster identity verification | IMPLEMENTED-ON-PROTECTED-MAIN | `postgres_restore_target.py` | focused service-name/system-identifier tests; ADR 0022; merged #228 historical integration evidence | Requires distinct exact service names and caller-owned `pg_control_system().system_identifier` values. It does not open/authenticate connections, accept DSNs, execute restore, or prove catalog/application/PITR/RPO-RTO readiness. | -| FR-5 effective PITR target configuration observation | ACTIVE-PR | no protected recovery-target configuration observer | #299 fixed-query source/tests plus canonical documentation overlay | Exactly eight reviewed recovery-target settings plus `pg_is_in_recovery()` are observed from a caller-owned isolated target. The APIs remain module-scoped; no connection timeout is imposed; no WAL completeness, target attainment, promotion, application readiness, PITR success, or achieved RPO/RTO is proved. | +| FR-5 effective PITR target configuration observation | ACTIVE-PR | no protected recovery-target configuration observer | #299 fixed-query source/tests plus canonical documentation overlay | Exactly eight PostgreSQL recovery-target settings plus `pg_is_in_recovery()` are observed from a caller-owned isolated target. The APIs remain module-scoped; no connection timeout is imposed; no WAL completeness, target attainment, promotion, application readiness, PITR success, or achieved RPO/RTO is proved. | | FR-5 recovery evidence binding/reinspection | ACTIVE-PR | underlying protected evidence primitives only | active binding/reinspection branches | Composition/reinspection is not provenance or restore proof. | | FR-5 post-restore catalog/application acceptance | ACTIVE-PR | protected schema/recovery/restore/target primitives only | active catalog work and #296 application-readiness branch | Exact catalog/function/privilege/live behavior must integrate before becoming shipped acceptance. | | FR-5 permanent live PostgreSQL integration lane | ACTIVE-PR | current protected CI does not yet contain #341 lane | #341 branch executes the complete integration marker; #296 is its tested child | Branch GREEN is not protected-main workflow authority. |