Files
james.maesandClaude Opus 5.5 4f850c2cf3
maven / build (push) Failing after 9s
build / maven (push) Failing after 9s
build(deps): align with Gitea registry (parent 2.2.1, QQQ 4.1.0-RC.26)
bridges/printing/pom.xml: qqq.version: 4.1.0-RC.22 -> 4.1.0-RC.26
bridges/printing/pom.xml: qbit-record-files.version: 0.1.0-RC.1 -> 0.4.0-RC.1
bridges/printing/pom.xml: qbit-printing.version: 1.0.0 -> 1.2.0-RC.1
bridges/record-files/pom.xml: qqq.version: 4.1.0-RC.22 -> 4.1.0-RC.26
bridges/record-files/pom.xml: qbit-record-files.version: 0.1.0-RC.1 -> 0.4.0-RC.1
bridges/scripting/pom.xml: qqq.version: 4.1.0-RC.22 -> 4.1.0-RC.26
bridges/scripting/pom.xml: qbit-scripting.version: 1.0.0 -> 1.1.0-RC.3
foundation/pom.xml: qqq.version: 4.1.0-RC.22 -> 4.1.0-RC.26
pom.xml: parent -> 2.2.1
pom.xml: added qqq.version=4.1.0-RC.26 (parent BOM import)
pom.xml: revision -> 1.1.0-SNAPSHOT

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 18:59:01 +00:00
..

Optional Document Generation / Printing bridge

This optional artifact composes public Generation, Record Files and Printing APIs. None of those foundations depends on this module or on another foundation through it. There is no new queue, schema, REST route or retained-byte store.

var source = new RecordFilesPrintSource();
printingConfig.withRetainedSourceAuthority(source);
generationConfig.withPrinting(new PrintingDispatch(source));
recordFilesConfig.withPrintObservationAuthority(new QCodeReference(PrintingObservationAuthority.class));

destination is the native printing_printer row ID, not a device name or a raw printer identifier. Printing rechecks its current tenant, job, printer and device permission and availability. The generation port carries no free-form print options: this bridge submits the fixed title Generated document and options {}, or exactly {"mediaProfile":{"id","revision"}} when the request selects a media profile. A request for more than one copy adds "copies":N (1 through 100) to those options on the same single submission; one copy adds nothing, so earlier requests keep their exact options. The committed options must carry exactly the requested count (an absent count matches only one copy), and supportsCopies() is true; this needs a Printing owner whose retained facade honors options.copies. A selected profile is refused before any intent, byte read or job unless the Printing owner's enforcement is explicitly adopted with PrintingDispatch.withMediaCapability(...) (default UNSUPPORTED; the existing retained facade persists options but does not enforce media). The capability is evaluated per request and applies to both submit and read-only lookup. It does not invent unsupported delivery settings.

Owner contract. This bridge declares qbit-printing ${qbit-printing.version} (0.4.0-SNAPSHOT, Printing main 64c9ebf; there is no 0.4 release yet) as its minimum: RetainedPrintFacade.Acceptance carries title and optionsJson, and PrintingService refuses a selected mediaProfile id/revision that is not among the printer's current profiles (HTTP 409, before admission or spool). The owner exposes no capability query, so hosts linked to that owner adopt enforcement explicitly with PrintingDispatch.forOwnerMediaEnforcement(source); the plain constructor stays default-deny and must not be combined with an older Printing artifact. The bridge verifies the committed title and options.mediaProfile equal what was requested, and turns the owner's unchecked PrintingException into a checked QException carrying the HTTP status and the owner's user-facing text. Enforcement is against the printer's last inventoried profiles, not a live device query, and says nothing about original-actor delivery policy.

Every submission requires the current native actor to equal the generation actor. It compares the generation logical file ID, exact version-row ID, parent table/record, hash, length, durable and available flags to a freshly authorized owner reference. The Printing locator is record-files:<version-row-id>. Its resolved opaque identity is a bounded, canonical versioned JSON tuple containing all eleven RetainedContentReference fields, including original actor, owner attachment and correlation. The tuple is metadata, never a credential. Reads go only through RetainedContentReader, with current owner authorization and a 20 MiB ceiling; the bridge independently verifies returned bytes and identity.

The stable generation request ID is passed unchanged to Printing's native idempotent acceptance transaction. A return is accepted only with the exact actor/source/destination, nonempty job/acceptance-event/tenant/device/printer identifiers and committed timestamp. Owner authorization is rechecked afterward. Failure after acceptance may mean a job already exists: retry the same request and destination, never fabricate a new ID. Printing performs replay/conflict reconciliation. A returned job ID means queue acceptance, never physical output.

Device observations are separate. PrintingObservationAuthority asks the native facade for an exact committed DEVICE_OBSERVATION event, never latest job state or the queue-acceptance event. The source callback requires the current reporter's record-files.observe-print permission and EVENT credential/channel write ceiling; Printing independently requires current tenant/job/device/printer authority. The original actor is retained in the proof, never impersonated. Later content-read revocation does not erase a historical observation. Only the six explicit device protocol states map to VerifiedPrintObservation.Delivery; there is no physical-output conversion.

Call the existing TrustedPrintObservationService.record(printIntentId, eventId) as the legitimately authenticated reporter. It independently compares the complete immutable RF row and durably records/replays the full receipt. The adapter alone does not append audit events or register a new endpoint. Missing proof, mismatches and outages remain explicit; failed audit is not success. The native Printing default remains denied when no owner observation adapter is configured. No owner content-read permission or old initiating session is substituted for reporting authority.

Verification and source reactor

Nine tests passed with Checkstyle in the local native source reactor (October 31, 2026). The first two attempts exposed unit-fixture initialization/metadata defects; those failed logs remain preserved, and production source was unchanged by their correction. Five test exact identity, callback/current authority, integrity, receipt mismatch and post-acceptance refusal. Two exercise the actual public Printing service, producer and facade on synthetic H2: committed acceptance/replay/lookup and native destination/tenant/current-permission denial, using an explicit fixed-byte reader fixture. Two additional owner integration tests use the existing RF file-H2/attachment lifecycle fixture and real retained intake/release/read services, plus native Printing acceptance and synthetic committed device events. They test separate reporters, original actor preservation, delivery-only completion, actual durable RF audit/replay and audit failure/retry. Object storage and failure controls remain trusted fixtures. These are not hardware tests or production storage qualification; no operating-system spool or physical output occurs.

After the isolated Printing facade is frozen, root can use a new copied merged Maven cache and this standalone reactor, without installation:

# Run from qbit-document-generation (existing checkstyle header convention).
# The reactor builds the Printing owner from ../qbit-printing-wt-echo-catalog (source-identical to main 64c9ebf).
.\mvnw.cmd -o -f bridges/printing/acceptance/pom.xml '-Dmaven.repo.local=C:/Users/james/.cache/qqq-generation-printing-m2-20261031' '-Dtest=PrintingBridgeTest,PrintingOwnerIntegrationTest' '-Dsurefire.failIfNoSpecifiedTests=false' package

The cache must include the already qualified core/RDBMS pair, canonical Collaboration owner and ordinary release dependencies, plus Printing's existing cached dependencies. The reactor compiles current Printing/RF/Generation and this bridge coherently; it does not overwrite a consumed same-GAV dependency or publish/install any artifact. Existing sealed evidence remains unchanged. Broader foundation provider gates, current-printing facade gate and hardware evidence remain separate.