Files
james.maesandClaude Fable 5.2 cfbf0744f9
maven / build (push) Successful in 6m14s
build / maven (push) Successful in 6m14s
fix(postgres): accept full_page_writes off on Amazon Aurora PostgreSQL only
Generation qualification refused every Amazon Aurora PostgreSQL server:
Aurora always reports full_page_writes = off and has no parameter to change
it, because its storage layer does not write torn pages.

The settings query now also returns
to_regprocedure('aurora_version()') IS NOT NULL (true on Aurora, false on
stock PostgreSQL, never an error). full_page_writes = off is accepted only
when that is true. Stock PostgreSQL must still report it on, and fsync on,
synchronous_commit on or remote_apply and every other check are unchanged
on both. The refusal text now says full-page writes are not required on
Aurora.

Tests run on a real postgres:17 engine whose settings are really changed;
only Aurora is simulated, by creating a function named aurora_version() in
the test database.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-09 20:25:55 -06:00

7.6 KiB
Raw Permalink Blame History

Durable generation queue and native actions

Development implementation; qualification and the verification result below govern release readiness.

GenerationQueue.enqueue commits a bounded explicit selection atomically. It records the initiating actor, canonical source IDs, ordered selection hash, immutable published revision, complete revision hash and exact published scripting artifact reference. A retry with the same actor/key returns the same selection; changed intent fails. A backend-wide cap of 10,000 untouched queued items is checked under the same claim lock; completed history remains retained. Publishing a newer draft does not repin an existing queue.

advance(queueId) processes at most one untouched item under the initiating user's current authenticated QQQ session. It does not create a service session, impersonate an actor or run a background daemon. The host must invoke it through an authenticated job runner or the native “Process next queued document” action. Per-record source access is rechecked before context preparation, rendering, retention and printing. The exact bounded pure-data context is committed with SHA-256 before rendering. Its body and the lease token are excluded from native reads. Enforced native reads reject private-field filters, ordering, second operands, projections, joins and functions before backend execution; merely hiding result fields is insufficient. Hosts must enable core permission enforcement or use enforcing QQQ entrypoints, as for other protected native tables.

Each advance commits its lease before work. A backend-wide row lock serializes claims and aggregate admission across threads/JVMs, with operator concurrency/deadline settings frozen on first claim. Default admission is one invocation with a fixed five-minute deadline; explicit constructor limits are1–16 invocations and30–600seconds. Renderer/process limits are independently enforced by their adapters. Every cross-process host sharing one rendering daemon also needs coordinated worker capacity allocation.

Expired RUNNING items become RECONCILIATION_REQUIRED. They never become QUEUED again. Their admission reservation remains until the exact old invocation returns, or the configured GenerationPorts.AttemptTermination verifier supplies trusted evidence that the invocation and its children can no longer act. The default verifier refuses recovery. Expiry is not termination evidence, and neither is an operator-supplied Boolean. No concrete application supervisor verifier is bundled yet; integrating the host's real process owner is a release/deployment prerequisite for automatic crash recovery.

After confirmed termination, only a known generation request/retained version can be reconciled. Missing retained identity stays unknown: the queue never treats a missing local row as proof that the owner did not store a file. Known versions use DocumentGenerationService.reconcile, the owner inspect facade, and the original print operation identity. No re-render or duplicate upload occurs. Owner reservation/storage-journal status is a separate pending integration.

Cancellation commits a batch flag and cancels untouched items. Running attempts stop at their next checkpoint. A storage or print call already in progress may finish; its durable receipt remains visible and the item requires reconciliation. Cancellation never claims to undo an external action or physical printing.

Status uses an ordinal cursor and returns at most50 items. Each exposed parent is authorized again. A partial/failed item is reported individually; there is no blanket success result for a partially processed selection.

Native QQQ processes

Configure .withSourceTables(List.of("orders", "purchaseOrders")) before producing the QBit. Those existing source tables receive “Generate document” and “Queue documents” actions. User-authored table bindings and published templates still determine supported document types/formats. Generation requests receive status, exact-original download, reprint and reconciliation actions. Queue rows receive cursor status, advance, cancel, termination verification and item reconciliation actions. Forms use standard QQQ process metadata; no custom client dependency is introduced.

Submitted records provide only IDs. The source body is always fetched afresh through enforced QQQ permissions. Process selections and source/format/stock/output constraints are revalidated at execution. Forms expose published template ID and PDF/ZPL format; richer template pickers/editor/preview workflows are separate remaining UX work.

GenerationDownloadService delegates through the optional DownloadAccess owner facade. Its HTTPS grant binds the exact immutable version and current initiating session. The owner must commit link-issuance authorization before signing a URL. A returned URL is LINK_ISSUED, never proof of DOWNLOADED. Physical download/print observations remain separate owner/device events.

Database/deployment constraints

The durable queue supports file-backed H2 with configured and actual WRITE_DELAY=0, or native MySQL 8.4 under the live checks in MYSQL.md, or native PostgreSQL 17 under the equivalent live checks in GenerationPostgres. Both require fresh independent writable connections and the owned tables on one backend. Ambient QQQ transactions are refused. Native mapping drift and unqualified physical targets are denied. Owned statements have five-second JDBC deadlines; MySQL row/metadata lock waits must each be 1–5 seconds. H2 tests pin 2.5.252 and close all connection providers before a cold reopen. Actual pinned MySQL 8.4.13 tests cover concurrent claims/edits, physical pooled isolation restoration, weakened durability/settings, index/engine/mapping drift, bounded lock contention and server restart. Amazon Aurora PostgreSQL 17 passes through the same PostgreSQL checks with one difference: Aurora always runs with full_page_writes off and has no parameter to change it, because its storage layer does not write torn pages, so GenerationPostgres accepts that value when the server resolves aurora_version() (to_regprocedure('aurora_version()') IS NOT NULL, evaluated in the settings query). Stock PostgreSQL must still report full_page_writes on, and fsync, synchronous_commit and every other check are unchanged on Aurora. The test for this rule runs on a real postgres:17 engine with a simulated aurora_version() function; no test in this repository runs on Aurora itself. Aurora MySQL is not qualified (see MYSQL.md). Schema changes are operator migrations; metadata registration does not execute DDL. Host power-loss and volume/backup restoration remain deployment acceptance work.

No queue/render/file/script code is executed through a trusted host JavaScript VM. The renderer and scripting integrations continue to require qualified Linux/runsc; this workstation has no runsc runtime, so hostile execution remains unavailable. The queue does not weaken those gates.

Verification

2026-10-30 21:37CDT: native process/default memory checks passed22 tests (18 existing orchestration regressions plus4 new native-process/download cases), Checkstyle clean. The subsequent full foundation install passed 45 tests at 21:40:44 CDT. Independent review then identified a private-field query oracle and semantic mutation-ceiling bypass; both were corrected. The security snapshot full install passed 50 tests at 21:49:57 CDT, including actual native QueryAction rejection and real JDBC queue/audit read-only credential tests, with Checkstyle and coverage gates. Logs: target/queue-security-full-verification.log. These tests do not qualify hostile worker isolation or production database/volume durability.