docs: close out printing 1.0 setup and release guidance #24

Merged
james.maes merged 1 commits from docs/printing-release-closeout-20261104 into main 2026-11-04 15:48:59 +00:00
18 changed files with 196 additions and 108 deletions

No files matched your search

+4 -4
View File
@@ -1,14 +1,14 @@
# Contributing
Use Java 21 and the checked-in Maven 3.9.11 wrapper. Clone `QRun-IO/qqq-print-protocol` as a sibling and check out the protocol commit pinned in `.github/workflows/ci.yml`. See README for the Windows and Unix build commands.
Use Java 21 and the checked-in Maven 3.9.11 wrapper. Clone `QRun-IO/qqq-print-protocol` as a sibling and check out the protocol commit pinned in `.gitea/workflows/qrun-release.yaml`. See README for the Windows and Unix build commands.
Run `./mvnw verify` (`.\mvnw.cmd verify` on Windows). The validate phase enforces the repository Checkstyle configuration; tests cover real H2 persistence, native QQQ metadata/processes and the public loopback HTTP contract. Add focused coverage for changed behavior. Do not replace spooler acceptance with a physical-print assertion.
Run `bash ./mvnw -Pui-demo verify` (`.\mvnw.cmd -Pui-demo verify` on Windows), matching the primary CI profile. The validate phase enforces the repository Checkstyle configuration; tests cover real H2 persistence, native QQQ metadata/processes and the public loopback HTTP contract. Add focused coverage for changed behavior. Do not replace spooler acceptance with a physical-print assertion.
Changes belong in a pull request with a concise behavior description and actual validation results. Update README, changelog, relevant tests and shared contract together when changing the wire interface. Use Conventional Commit subjects. Do not include local databases, logs, device credentials, customer documents or machine-specific printer information.
Changes belong in a pull request on [the primary Gitea repository](https://git.kof22.com/QRun-IO/qbit-printing) with a concise behavior description and actual validation results. Update README, changelog, relevant tests and shared contract together when changing the wire interface. Use Conventional Commit subjects. Do not include local databases, logs, device credentials, customer documents or machine-specific printer information.
Keep the QBit compatible with QQQ 4.1+ and resolve runtime services through the current QQQ instance. Preserve tenant/device isolation and the distinction between local exposure (`available`) and server approval (`enabled`). Application callers must authorize destinations before submitting or emitting an effect.
Maintainers create reviewed version tags. CI produces JAR/POM/checksum assets and publishes GitHub prereleases for hyphenated versions. Maven Central publication, deployment and physical printer tests are separate operations; this workflow does not perform them.
Maintainers publish reviewed versions through the primary Gitea CI and trusted Maven publisher, then attach the verified JAR/POM/checksums to a Gitea release. Follow [release operations](docs/RELEASES.md). GitHub is a shadow/archive; its Actions are retired for this repository. Historical `.github` scripts remain available as local quality checks. Deployment and physical printer acceptance are separate from library publication.
## Script quality
+28 -22
View File
@@ -2,11 +2,13 @@
Cloud printing for QQQ 4.1+, paired with the [Windows AppKit connector](https://git.kof22.com/QRun-IO/qqq-print-agent) 1.0.1 and the [shared protocol](https://git.kof22.com/QRun-IO/qqq-print-protocol) 1.0.0. The Windows connector opens an outbound, authenticated two-way WebSocket; documents download separately over HTTPS. The cloud needs no inbound route into the facility. Version **1.0.0** supports native printing **2.3**, wire payload v1, real-time jobs and controls, and native browser sign-in through QQQ. Upgrade the server before the matching Windows connector.
**Current dependency:** QQQ **4.1.0-RC.21**, published on Maven Central with native session login, and Java 21. See the [printing releases](https://git.kof22.com/QRun-IO/qbit-printing/releases) for downloads. The optional native UI demo uses QQQ frontend **1.0.0-RC.37**. GitHub releases provide a library JAR, POM and SHA-256 checksums, with build attestations for all three assets. Verify the exact downloaded release; publication does not establish installed or physical-output acceptance. This repository does not claim Maven Central publication or provide a standalone executable/fat JAR.
**Released:** [QQQ Printing 1.0.0](https://git.kof22.com/QRun-IO/qbit-printing/releases/tag/v1.0.0), with a library JAR, matching POM and `SHA256SUMS`. The same JAR/POM are published in the QRun-IO Gitea Maven registry. Gitea requires sign-in for downloads. The QBit itself is not published to Maven Central and is not a standalone executable/fat JAR. See [installation and release access](docs/RELEASES.md).
**Runtime:** Java 21 and QQQ **4.1.0-RC.21**, published on Maven Central with native session login. The optional native UI demo uses QQQ frontend **1.0.0-RC.37**. Product version 1.0.0, native extension 2.3.0 and wire payload v1 are separate version contracts.
Implemented: single-use enrollment, device credentials, inventory/approval, PDF/ZPL submission, durable JDBC queue, idempotency, claim/content/events, native QQQ setup/test-print processes, read-only device/printer/job tables and a durable enqueue effect target.
The 0.2.0-rc.1 source adds native record/selection actions, per-device printers/jobs/queue/history, desired versus observed status and standard-session authentication at the discovered `/qqq/v1/qbit/printing` extension. Device credentials become secondary identity proof alongside the current QQQ user's permissions. Upgrade the server before the 0.2.0 Windows client, then explicitly associate an existing unbound pairing during sign-in. These changes are included in the published release above. See the [authentication contract](https://github.com/QRun-IO/qqq-print-protocol/blob/main/docs/QQQ-AUTHENTICATION.md); bound devices cannot fall back to legacy `/printing/v1` authentication.
Native record/selection actions expose per-device printers, jobs, queue and history, with desired versus observed status. The discovered `/qqq/v1/qbit/printing` extension uses standard QQQ session authentication. Device credentials are secondary identity proof alongside the current QQQ user's permissions. Existing unbound pairings require explicit association during sign-in. See the [authentication contract](https://git.kof22.com/QRun-IO/qqq-print-protocol/src/branch/main/docs/QQQ-AUTHENTICATION.md); bound devices cannot fall back to legacy `/printing/v1` authentication.
```mermaid
flowchart LR
@@ -27,14 +29,14 @@ Java/.NET WebSocket jobs and S3 checks without an installed connector or printer
## Build and verify
Install Java 21. Clone this repository and `qqq-print-protocol` as siblings. This source pins protocol commit `42c0d249f81395f00408ec0f92638dcbbf5deb03` (the integrated contract under Gitea PR 2; the same ref CI checks out); use that commit for reproducible compatibility tests. Use the checked-in wrapper (Maven 3.9.11).
Install Java 21. Clone this repository and `qqq-print-protocol` as siblings from Gitea. Check out protocol commit `42c0d249f81395f00408ec0f92638dcbbf5deb03`, the immutable fixture ref in `.gitea/workflows/qrun-release.yaml`. Use the checked-in wrapper (Maven 3.9.11).
```powershell
.\mvnw.cmd verify
.\mvnw.cmd -Pui-demo verify
.\mvnw.cmd dependency:build-classpath '-Dmdep.outputFile=target/runtime-classpath.txt' '-DincludeScope=runtime'
```
On Linux/macOS use `bash ./mvnw verify` and the corresponding wrapper commands. First builds download dependencies; `-o` is only appropriate after they are cached.
On Linux/macOS use `bash ./mvnw -Pui-demo verify` and the corresponding wrapper commands. First builds download dependencies; `-o` is only appropriate after they are cached.
Checkstyle runs during validate. Tests exercise real H2 persistence, native QQQ metadata/processes and real loopback HTTP through Javalin, including the shared fixtures and withdrawal of a locally exposed printer. Keep `../qqq-print-protocol` checked out or pass `-Dprinting.protocol.fixtures=<fixture-directory>`.
@@ -70,14 +72,14 @@ Open `http://127.0.0.1:18082`. On Linux/macOS use `:` as the classpath separator
The protocol-only `PrintingDemo` and synthetic, mock-authenticated `PrintingUiDemo` remain separate. Do not point the synthetic demo at real paired printer data. The local host retains database document storage until an actual dedicated S3 binding is configured in a deployment-owned application; it does not claim a remote cloud deployment.
Local native deployment is accepted with authentication and access-denial checks, preserved pairing/history, connector reconnection and 365-day retention. The previously accepted 0.1.4-rc.1 release passed 73 tests and zero Checkstyle violations; the user confirmed all three Query diagnostic outputs good. Production S3/IAM and remote deployment remain separate qualification work. The 0.2.0 controls/authentication release passed 25 real client/native QQQ interoperability checks; the user later confirmed installed Letter PDF and Zebra ZPL output, the Connected footer and both printers. These results do not qualify installed or physical behavior for 0.3.
The local setup uses the same native authorization and transport paths as an integrated application. Production authentication mappings, S3/IAM and database operation belong to the deploying host; the local fixture does not certify those settings. Dated test evidence is retained in [qualification notes](docs/QUALIFICATION-2026-11-01.md).
## Add to a QQQ application
For a source checkout, `mvnw.cmd install` (or `bash ./mvnw install`) installs the verified library into your local Maven repository. For a GitHub release, download the JAR, matching POM and `SHA256SUMS`, verify the checksums, then install those artifacts locally or through your organization's artifact repository. Example using the release files in the current directory:
Use the [authenticated Gitea Maven registry](docs/RELEASES.md#use-the-maven-registry), or download the release JAR, matching POM and `SHA256SUMS` and verify both files. For a local installation of the downloaded artifacts:
```powershell
.\mvnw.cmd install:install-file '-Dfile=qbit-printing-0.3.0-rc.1.jar' '-DpomFile=qbit-printing-0.3.0-rc.1.pom'
.\mvnw.cmd install:install-file '-Dfile=qbit-printing-1.0.0.jar' '-DpomFile=qbit-printing-1.0.0.pom'
```
After the artifact is available in your configured repository, add:
@@ -86,7 +88,7 @@ After the artifact is available in your configured repository, add:
<dependency>
<groupId>com.kingsrook.qbits</groupId>
<artifactId>qbit-printing</artifactId>
<version>0.3.0-rc.1</version>
<version>1.0.0</version>
</dependency>
```
@@ -106,12 +108,12 @@ new PrintingQBitProducer().withConfig(new PrintingQBitConfig()
.withStorageTableName("printing_documents") // existing dedicated S3 storage table
.withSchedulerName("appScheduler") // existing host scheduler
.withService(printing)).produce(qInstance, "printing");
server.withAdditionalRouteProviders(List.of(new PrintingRoutes(printing, context -> hostPrintingAdminGuard(context))));
server.withAdditionalRouteProviders(List.of(new PrintingRealtimeRoutes(printing)));
```
`hostPrintingAdminGuard` is the host's own authenticated administrator policy, not a supplied library method. The service is bound to one tenant; use a separate host service instance for each tenant. Device token verification and job ownership are enforced on every device operation. Management service methods are intended for trusted application code; enforce user/facility authorization before calling them.
The producer registers the native printing API; the additional provider supplies its WebSocket transport. Preserve any other host route providers and close the printing provider during shutdown. The same service instance must be used for metadata and transport. The service is bound to one tenant; use a separate host service instance for each tenant. Device token verification and job ownership are enforced on every device operation. Management service methods are intended for trusted application code; enforce user/facility authorization before calling them. See [real-time integration](docs/REALTIME.md).
The storage/scheduler options above are included in 0.1.4-rc.1. Configure a dedicated private printing bucket for the customer/environment through existing QQQ S3 metadata; no bucket credentials belong in printing forms. Admin retention defaults to 365 days after successful completion. Scheduled cleanup handles bounded batches every five minutes and preserves active, failed and uncertain work plus all receipts/history. Without a configured storage binding, legacy database documents remain supported; without a host scheduler, automatic cleanup does not run. Review [storage configuration, bucket isolation and S3 versioning](docs/STORAGE-AND-RETENTION.md) before deployment.
Configure a dedicated private printing bucket for the customer/environment through existing QQQ S3 metadata; no bucket credentials belong in printing forms. Admin retention defaults to 365 days after successful completion. Scheduled cleanup handles bounded batches every five minutes and preserves active, failed and uncertain work plus all receipts/history. Without a configured storage binding, legacy database documents remain supported; without a host scheduler, automatic cleanup does not run. Review [storage configuration, bucket isolation and S3 versioning](docs/STORAGE-AND-RETENTION.md) before deployment.
Enrollment uses a named facility selector. Set `withFacilityPossibleValueSourceName("your_existing_facility_source")` to reuse an already registered host source and its record security. Without it, the standalone choice is **Default facility**. The backend validates the selection under the current user's permissions before issuing an enrollment code; typing or forging an unknown/foreign-tenant ID cannot bypass that check. Existing stored facility IDs are preserved; configure their original source to resolve their names.
@@ -143,31 +145,35 @@ String printJobId = job.getString("jobId");
For terminal and web clients the QBit also offers ready-made print processes: `PrintingRecordProcesses.registerAll(instance)` (after all host tables are added) puts **Print** on every readable table, rendering a record sheet from the table's sections and child lists; `printingPrintTableList` prints a grid of any table (columns, filter, sort, page or all rows, paper and orientation); `printingPrintText` prints text such as a screen capture. Opt a table out with `PrintingTableSettings().withPrintable(false)`. Each returns the queued job id in `printingJobIds`. `printingRenderToPdf` (extension 2.2.0) renders the same documents to a PDF download for the caller instead ("Save as PDF"), and every document carries the app header and footer the client sends (`headerApp`, `headerTitle`, `headerServer`, `headerUser`, `headerPrintedAt`, `footerLeft`, `footerNote`).
The returned ID identifies durable queue acceptance. Check job status asynchronously. The [protocol v1 specification](https://github.com/QRun-IO/qqq-print-protocol/blob/f977bd01b62ceb7539190fd2861809537fcf504c/README.md) defines HTTP endpoints, JSON fields, integrity checks and lifecycle semantics.
The returned ID identifies durable queue acceptance. Check job status asynchronously. The [protocol v1 specification](https://git.kof22.com/QRun-IO/qqq-print-protocol/src/branch/main/README.md) defines HTTP endpoints, JSON fields, integrity checks and lifecycle semantics.
For durable QQQ jobs register `PrintEnqueueEffectTarget` as an `IDEMPOTENT_EXTERNAL` target in `DurableJobsMetaData`, then emit the submit-request payload. The target replaces the payload idempotency key with the durable effect key. Its SENT result means accepted into the queue, not physical output. This implementation uses its own JDBC transaction; do not register it as LOCAL_TX. Authorize the destination in the emitting process before writing the effect. QQQ's durable dispatcher runs with a `QSystemUserSession` and does not propagate the user's tenant keys. For that trusted outbox path only, the target resolves the service configured on the dispatcher's current QQQ instance; that service fixes the tenant and rejects devices belonging to another tenant. The payload cannot choose a service or tenant. A cached target resolves the current instance on every call. Inline user calls retain the `printing_tenant` scope check, and native management processes (including enrollment) still require both administrator permission and matching tenant scope. Do not expose direct effect emission through an arbitrary user-supplied target/payload endpoint.
## Deliberate first-version limits
## Deployment boundaries
The implemented path targets an explicit device/printer. Logical destination bindings, cancellation, reprint workflow, automatic reconciliation, clustered throughput optimization, retention and alerts are follow-ups. Documents are durably stored as base64 in the database for this first path; object-storage integration is deferred. Job paper (`paperWidthMm` and `paperHeightMm`, both positive, at most 2000, never with `mediaProfile`) is accepted; the built-in 4 x 1 and 4 x 2 in PDF test labels use it (101.6 x 25.4 / 50.8 mm) so Windows does not feed 4 x 6 stock. Only a client from the same unreleased 0.4 cohort applies it; older clients reject the job. Other jobs follow the Windows queue default. Received/submitting jobs are not automatically offered again. The queue records SPOOLED honestly and does not assert physical delivery.
Jobs target an explicit device/printer. Logical destination routing and a distributed real-time bus belong to the integrating host. The release includes cancellation of queued jobs, explicit reprints, owned spool-cancellation commands, durable receipt reconciliation, S3 delivery storage and scheduled retention. Received/submitting jobs are not automatically offered again; `SPOOLED` never asserts physical delivery.
The protocol demo and synthetic native UI preview are separate local hosts. Attaching the QBit to a deployed application and its real authentication/facility policy remains a host integration task. PostgreSQL behavior, production deployment, upgrades, cancellation/reprint and broad printer-driver coverage are not certified by the initial H2/laser tests.
Job paper (`paperWidthMm` and `paperHeightMm`, both positive and at most 2000, never combined with `mediaProfile`) is supported by the matching Windows 1.0.1 connector. The built-in 4 × 1 and 4 × 2 PDF tests use 101.6 × 25.4 / 50.8 mm. Without explicit paper or a reported media selection, jobs follow the Windows queue default. See [media selection](docs/OPERATOR-CATALOG.md).
## Verified initial path
The protocol demo and synthetic native UI preview are separate local hosts. Attaching the QBit to a deployed application requires that host's real authentication, facility policy, database, storage and supervision. PostgreSQL and multiple QQQ nodes are not qualified by the local H2/MinIO fixture.
On 2026-10-29, both the development Windows connector and the installed LocalSystem service printed a PDF to a local laser printer. The user confirmed both physical pages. MSI installation/start and temporary uninstall passed. Zebra hardware testing is deferred until a Zebra is connected. A SPOOLED status alone is never used as proof of physical output.
## Physical output
The user confirmed physical laser PDF and Zebra ZPL/PDF output during development, including a 4 × 1 test. A configured stock profile does not prove a physical result on another printer or stock; inspect the first output after changing media. Historical acceptance records remain in [session history](docs/SESSION-STATE.md).
## CI and releases
Pull requests and `main` pushes run Java 21/Maven wrapper verification with the immutable sibling protocol checkout. A tag matching the POM version runs build/tests and the secrets, workflow, dependency and malicious-package security gates before publishing the tested JAR, POM and `SHA256SUMS` as GitHub release assets. Build verification enables the `ui-demo` profile used by the local host. Maven generates its selected compile/runtime graph as a CycloneDX SBOM, including frontend assets. Trivy and OSV scan that graph; a guard rejects missing or different package versions, missing frontend assets, and empty inventories. CI retains the resolved graph and scanner evidence. OSV uses `--all-packages`; its pinned 2.6.0 reporter [omits Maven groups](https://github.com/google/osv-scanner/issues/3099), so the guard checks every reported artifact/version and rejects ambiguous names while the verified input retains full package URLs. Hyphenated versions create prereleases. The packaged JAR includes the repository LICENSE and NOTICE under `META-INF`, alongside the existing font license and diagnostic assets. The workflow does not publish to Maven Central, deploy a QQQ application or print to hardware. The [0.1.0-rc.1 release](https://github.com/QRun-IO/qbit-printing/releases/tag/v0.1.0-rc.1) passed these hosted gates.
Gitea is the source, pull-request, CI and release authority. The thin `.gitea/workflows/qrun-release.yaml` delegates to the protected `qrun-release-v1` channel with Java 21, the Maven wrapper, `ui-demo` and the immutable protocol fixture checkout. Required verify, secrets and gate checks precede merge; successful main builds capture the tested Maven reactor for the trusted registry publisher. Maintainers publish the corresponding tagged Gitea release from those verified bytes. See [release operations](docs/RELEASES.md#maintainer-release-path).
GitHub is a shadow/archive. Its Actions were retired for this repository on 2026-11-04; checked-in `.github` workflows describe the former pipeline and do not publish current printing releases. The separate Windows repository retains its signing/update-feed workflow. The 1.0.0 server release does not claim GitHub attestations or Maven Central publication. The JAR includes LICENSE, NOTICE and font/diagnostic asset licenses; publication does not deploy a QQQ host or print to hardware.
## Printing home
The admin-only Printing home uses stock QQQ widgets: a purpose/scope/help header, actionable exceptions, four health tiles, and a full-width pending/recent work list. Counts and record links use QQQ queries under the viewer's tenant. Device disconnection means no heartbeat for 90 seconds; job failure tiles cover jobs created in the past 24 hours. Older failures remain in Print jobs. An empty installation explains enrollment and printer setup.
This RC implements the happy path of the [QQQ dashboard standard](https://github.com/QRun-IO/qqq/blob/main/docs/DASHBOARD-STANDARD.md), with explicit remaining gaps: RC.20 carries role/priority hints in widget default values; attention uses scoped database queries and 60-second refresh rather than the core live attention feed; dismiss/snooze, interactive URL-backed page scope, and stale/retry presentation depend on further core/frontend integration. It has not passed the standard's full responsive/accessibility audit. No custom frontend or HTML dashboard is used.
The home uses the standard QQQ frontend widgets and scoped queries. Its timed dashboard refresh updates the visible summary; job delivery uses the independent real-time WebSocket and does not wait for a dashboard refresh. No custom frontend or HTML dashboard is required.
### Operator actions (0.1.1-rc.1)
### Operator actions
The Windows companion can request test prints and explicit reprints through device-scoped authenticated routes. The same printer approval/exposure rules apply. Upgrade the QBit and connector together for these additive protocol features. Reprints create a new job; uncertain/spooled originals require duplicate-output consent and remain unchanged.
@@ -177,6 +183,6 @@ QQQ's **Print jobs** table and records expose **Print again** and **Cancel queue
All built-in printer test actions share `PrintingTestDocuments`: QQQ branding, the official [Query dog mascot](https://qrun.io/query), large warehouse-style identifiers and embedded JetBrains Mono Bold with a dotted zero and distinct 1/I/l. Query's original artwork and aspect ratio are preserved in PDF and thermal output; [asset provenance](src/main/resources/com/kingsrook/qbits/printing/images/README.md) ships with the resource. The font is included under SIL OFL 1.1; its license and provenance ship in the JAR. PDF embeds a font subset. ZPL renders the same glyphs into document-local, row-aligned graphics below Zebra's 99,999-byte per-field limit; it does not download or save a printer font.
Native record and selected-table actions expose a possible-value stock/resolution selector. Letter and A4 are PDF-only. Label profiles are 4 × 6 inches at 203, 300 or 600 dpi; PDF label output is always 101.6 × 152.4 mm. Select matching stock and printer resolution. Bulk actions apply the chosen profile to every selected destination, so group compatible printers. The document does not reconfigure Windows stock, calibrate the printer or save device configuration; ZPL width/length are transient format settings.
Native record and selected-table actions expose a possible-value stock/resolution selector. Letter and A4 are PDF-only. Label profiles cover 4 × 1, 4 × 2 and 4 × 6 inches at 203, 300 or 600 dpi, with corresponding PDF dimensions of 101.6 × 25.4, 50.8 or 152.4 mm. Select matching loaded stock and printer resolution. Bulk actions apply the chosen profile to every selected destination, so group compatible printers. The document does not change the Windows queue defaults, calibrate the printer or save device configuration; ZPL width/length are transient format settings. Direct-thermal stock needs the driver's Direct Thermal setting, without a ribbon.
The device test-print API accepts optional `testProfile` with the same choices. Existing clients default to Letter PDF or 203-dpi 4 × 6 ZPL. Invalid profiles fail before enqueueing. Test actions use the ordinary durable queue and existing printer exposure/approval rules; discovery never automatically prints. A ZPL barcode, glyph comparisons and size/alignment marks support physical inspection. Rendering previews and spool acceptance do not prove paper or scanner quality.
+3 -3
View File
@@ -1,9 +1,9 @@
# Security
Report vulnerabilities privately through [GitHub vulnerability reporting](https://github.com/QRun-IO/qbit-printing/security/advisories/new), or `contact@kingsrook.com` if that channel is unavailable. Include affected versions, a minimal synthetic reproduction and expected versus actual authorization behavior. Do not put enrollment codes, bearer credentials, customer documents or exploit details in public issues.
Report vulnerabilities privately through [GitHub vulnerability reporting](https://github.com/QRun-IO/qbit-printing/security/advisories/new), or `contact@kingsrook.com` if that channel is unavailable. Include affected versions, a minimal synthetic reproduction and expected versus actual authorization behavior. Ordinary source changes and pull requests belong in Gitea. Do not put enrollment codes, bearer credentials, customer documents or exploit details in public issues.
The current prerelease targets QQQ 4.1+. Fixes target the current prerelease; older QQQ versions are outside scope.
The supported release line is 1.0.x for QQQ 4.1+, currently built against QQQ 4.1.0-RC.21. Report the exact QBit, QQQ and Windows connector versions. Older QQQ versions are outside scope.
The host must provide authenticated management authorization and the correct tenant/facility context. Native QQQ operations require `printing_admin` and a matching `printing_tenant` session security value. Device credentials only authorize their device's queue/content/status operations. HTTPS is required for remote deployment; the supplied HTTP demos deliberately bind to loopback.
The host must provide authenticated management authorization and the correct tenant/facility context. Native QQQ operations require `printing_admin` and a matching `printing_tenant` session security value. Native device operations require both the current QQQ user session and bound-device proof; a device token alone cannot authorize them. Operator catalog/submission uses `printing_operator` or administration plus native destination/process permissions; it grants no general device administration. See [authorization and controls](docs/OPERATIONS.md#device-controls-and-durable-action-receipts). HTTPS is required for remote deployment; the supplied HTTP demos deliberately bind to loopback.
The UI demonstration uses a fixed mock identity and synthetic data and must remain local. It registers no connector transport routes. RAW ZPL is printer-control input: submit trusted generated labels, not arbitrary untrusted printer commands. Stored documents can contain personal information. See [storage and retention](docs/STORAGE-AND-RETENTION.md) for dedicated bucket boundaries, tenant isolation and the default 365-day policy.
+21 -9
View File
@@ -1,12 +1,24 @@
# Local Authentik reference
Run the optional real-provider checks with Docker Compose and PowerShell 7.4+.
The pinned fixture images use Linux/amd64; other hosts need Docker's corresponding
Linux-container support or emulation:
The released application uses QQQ 4.1.0-RC.21, including the native session-login
grant. A production host configures QQQ's standard OAuth2/Authentik provider,
trusted HTTPS, redirect registration and current user/tenant permissions. The
Windows connector discovers that setup through the QQQ UI/UX API; provider
refresh credentials remain on the server. See [the native authentication
contract](https://git.kof22.com/QRun-IO/qqq-print-protocol/src/branch/main/docs/QQQ-AUTHENTICATION.md).
```powershell
pwsh ./dev/Invoke-Dev.ps1 -Action Test -Authentik
```
## Historical reference fixture compatibility
The optional `Invoke-Dev.ps1 -Action Test -Authentik` diagnostic below was written
for RC.20. `Invoke-Authentik.ps1` explicitly expects API 1.8 without
`nativeSessionLogin`, so that diagnostic is not compatible with the current RC.21
application baseline. Do not interpret its expected-absence assertion as a
production native-authentication failure or use it as a 1.0 release gate. The
separately pinned experimental profile remains available for reproducing its
recorded result. No fixture code or pins were changed during documentation closeout.
The following describes the retained fixture and its recorded scope. It requires
Docker Compose, PowerShell 7.4+ and Linux/amd64 container support.
The command creates a fresh, owned development project, runs the normal QQQ and
MinIO smoke test plus the Authentik reference checks, then removes that project's
@@ -33,7 +45,7 @@ authentication.
S256 capability. A valid state/S256 request with the registered callback
continues to the provider login flow without following it. Changing only that
callback to an unregistered redirect is rejected before any user login.
- The current QQQ RC.20 host advertises UI API 1.8 without `nativeSessionLogin`.
- The historical QQQ RC.20 host advertised UI API 1.8 without `nativeSessionLogin`.
That expected absence is recorded as a native-client prerequisite failure,
not silently replaced by bearer authentication or an unpublished core.
@@ -89,8 +101,8 @@ denials, logout replay rejection, renewal after expiry and provider revocation
with the production Core client. Its synthetic HTTP driver and HTTPS callback
receiver do not qualify the installed Windows browser UI or private URI callback.
Production adoption still requires a compatible published central artifact
tuple. Provider refresh tokens stay on the server. The short lifetime test does
The released application now adopts the compatible QQQ RC.21 tuple; this
historical experimental result does not by itself qualify a different host configuration. Provider refresh tokens stay on the server. The short lifetime test does
not prove months or years of unattended use. Do not route the private Windows
callback to a live companion whose connection must remain intact.
+11 -11
View File
@@ -32,13 +32,13 @@ The host provides native printing screens, settings, a dedicated MinIO document
bucket and scheduled retention. No printer is enrolled automatically in this host.
The test workload uses a separate disposable database and object store.
Add `-Authentik` when creating an environment or running a fresh test to include
real Authentik/PostgreSQL. See [the provider checks and remaining native grant
prerequisite](AUTHENTIK.md). Provider discovery does not establish successful OIDC
user login or refresh; the current QQQ RC.20 API lacks that native-client grant.
The current application dependency is QQQ RC.21, which supplies native session
login. The optional `-Authentik` diagnostic still asserts the older RC.20 API 1.8
absence of that feature; it is a retained historical check, not a current RC.21
login test. See [provider setup and fixture compatibility](AUTHENTIK.md).
Authentik uses PostgreSQL; the printing host itself uses H2, not PostgreSQL or MySQL.
```powershell
pwsh ./dev/Invoke-Dev.ps1 -Action Test -Authentik
pwsh ./dev/Invoke-Dev.ps1 -Action Test -Workload 10000
```
@@ -126,11 +126,11 @@ It is opt-in, Test-only, and does not change the default released QQQ dependency
## Continuous integration
The development workflow runs the Pester and PowerShell analysis checks on
Windows and Ubuntu for every pull request and main-branch push. Ubuntu also runs
the real 40-job/S3 Docker smoke. Both client fixture images also have build-only
jobs on every pull request, including the optional native client; these jobs run
only fake-HTTP discovery checks and do not start a provider.
Primary Gitea CI runs the shared Maven verification with `ui-demo` and the pinned
protocol fixtures. GitHub Actions were retired for this repository on 2026-11-04.
The checked-in `.github/workflows/development.yml` records the former Windows/Linux
Pester, image-build and Docker checks; it is not an active CI guarantee. The
commands above remain available for intentional local development checks.
Maven Checkstyle checks all four Java fixture sources in `dev/java` and
`dev/native-auth/java` during `validate`. They are deliberately **not** Maven
@@ -149,5 +149,5 @@ package dependency were added. For a local build, supply the real pinned Core
DLL through `-p:CoreAssemblyPath=/absolute/path/Qqq.PrintAgent.Core.dll`.
The longer experimental native-auth profile is
an explicit manual workflow option; it is not silently substituted for the
an explicit local command; it is not silently substituted for the
released dependency baseline.
+9 -6
View File
@@ -1,7 +1,9 @@
# Experimental native Authentik qualification
This optional profile tests an **unreleased upstream QQQ candidate**. It does
not replace the default released RC.20 TABLE/MinIO development environment,
This optional profile preserves a **historical upstream candidate** for reproducible
qualification. The normal application now uses published QQQ RC.21 with native
session login; this profile still builds its explicit older source pin. It does
not replace the default TABLE/MinIO development environment,
install a connector, or qualify the Windows browser callback UI.
From the repository root, with Docker and PowerShell 7.4 or later:
@@ -77,9 +79,10 @@ private input/result files, rather than a host home or credential directory.
The QQQ fixture uses fresh standard session, redirect-state and encrypted
refresh-token tables. Its customizer maps the verified provider's synthetic
`printing_admin` group to the existing native permission. It creates no device
pairing, job, print operation or fabricated user session. Released RC.20 lacks
the native-session grant; this experiment must stay opt-in until an appropriate
immutable upstream tuple is published and separately adopted.
pairing, job, print operation or fabricated user session. RC.20 lacked the
native-session grant; RC.21 now supplies it in the ordinary application. This
fixture remains opt-in and pinned to its recorded source rather than silently
substituting a different runtime into historical results.
## Recorded local qualification
@@ -93,4 +96,4 @@ probe compatibility correction also passed all eight checks on 2026-11-01.
All source files matched the pre-run hash manifest through completion, and
independent cleanup again found no owned containers, volumes or networks.
The native image's 12 discovery checks and default workload's nine checks pass.
The unreleased upstream and installed-browser limitations above still apply.
The historical source pin and installed-browser limitations above still apply.
+2 -2
View File
@@ -19,7 +19,7 @@ Run the usual quality gate:
./mvnw -B -ntp -Pui-demo verify
```
CI also runs the bounded compiler-configuration guard:
For a compiler-configuration change, also run the existing bounded guard locally:
```sh
python3 .github/scripts/check-java-compiler.py
@@ -30,7 +30,7 @@ under `target/compiler-guard`. Both main and test sources have a positive
probe and negative probes for NullAway, Error Prone's `DeadException`, and a
deprecated call rejected by warnings-as-errors. A random Maven failure does
not satisfy a negative probe: the expected diagnostic must be present.
Logs and a result manifest are retained in the normal CI test evidence.
Logs and a result manifest are written under `target/compiler-guard`. The former GitHub workflow ran this probe explicitly; primary Gitea verification enforces the POM compiler checks during the Maven build.
No artifact is installed or published. Optional `--maven`, `--settings`,
`--local-repository` and `--offline` arguments support an isolated local cache.
+4 -4
View File
@@ -10,7 +10,7 @@
| `PrintingUiDemo` | Isolated in-memory synthetic data, mock administrator, no device routes | Native UI demonstration only |
| `PrintingLocalHost` | Durable H2 shared by native QQQ and device routes, real password/session authentication | Authenticated local application |
The local host adds its own `printing_admin_user` and `printing_admin_session` tables. It preserves existing printing tables, device credential hashes, receipt history and tenant identity. Physical table/column names are mapped to the existing H2 case convention; it does not rename an uppercase database or change `DATABASE_TO_UPPER`. Every host instance uses a distinct internal backend name to avoid cross-instance provider-cache collisions in QQQ RC20.
The local host adds its own `printing_admin_user` and `printing_admin_session` tables. It preserves existing printing tables, device credential hashes, receipt history and tenant identity. Physical table/column names are mapped to the existing H2 case convention; it does not rename an uppercase database or change `DATABASE_TO_UPPER`. Every host instance uses a distinct internal backend name to avoid cross-instance provider-cache collisions observed during RC.20 development.
## Required configuration
@@ -36,7 +36,7 @@ $dependencies = (Get-Content target/local-host-classpath.txt -Raw).Trim()
& "$env:JAVA_HOME/bin/java.exe" -cp "target/classes;$dependencies" com.kingsrook.qbits.printing.PrintingLocalHost
```
Set the required environment values securely before launch. Maven contract tests require the documented sibling protocol fixture checkout or `printing.protocol.fixtures` override. Browse to `http://localhost:18081/` (or the configured port) and use the native username/password screen. The existing Windows connector continues using the same server origin and device token; it does not receive the browser password or management token.
Set the required environment values securely before launch. Maven contract tests require the documented sibling protocol fixture checkout or `printing.protocol.fixtures` override. Browse to `http://localhost:18081/` (or the configured port) and use the native username/password screen. Configure that origin in the Windows connector Connection settings and sign in through the discovered QQQ authentication flow. Preserve an existing pairing when upgrading; the native path requires the current user session as well as device proof. The connector does not receive the management token.
This command runs the host in the foreground. `QApplicationLauncher` owns graceful HTTP/scheduler shutdown. It does not install an operating-system service or auto-start registration; the deploying operator must provide supervision, protected credential loading, logs and backups for unattended use.
@@ -60,7 +60,7 @@ Existing facility IDs are retained. The standalone enrollment form offers the na
QQQ supplies password verification, failed-sign-in throttling, HttpOnly sessions, session expiry and logout. The local authorization subclass calls native verification first and maps only the configured account to printing permissions. Other valid accounts cannot gain those permissions. Native QQQ permission and tenant checks still apply to every table/process.
The host rejects non-loopback Host headers, cross-origin Origin headers and cross-site browser requests. Cookie-authenticated unsafe requests require an exact same-origin Origin header, including logout and native process actions. Explicit bearer/device API calls without ambient cookies remain usable from the connector. Use one loopback hostname consistently in the browser; `localhost` and `127.0.0.1` are different browser origins. These controls do not turn a local HTTP host into an Internet-facing service.
The host rejects non-loopback Host headers, cross-origin Origin headers and cross-site browser requests. Cookie-authenticated unsafe requests require an exact same-origin Origin header, including logout and native process actions. Explicit API calls without ambient cookies still require their normal route credentials; native bound devices use QQQ session authentication plus device proof. Use one loopback hostname consistently in the browser; `localhost` and `127.0.0.1` are different browser origins. These controls do not turn a local HTTP host into an Internet-facing service.
## Retention, storage and remaining deployment work
@@ -68,4 +68,4 @@ The native Quartz scheduler runs the existing bounded cleanup process every five
This local host deliberately leaves the S3 binding unconfigured. Native settings report legacy database storage. New and existing documents therefore remain in the database; merely running this host does not move documents to S3. A deployed application must supply its existing dedicated `printing_*` S3 table/backend and scheduler configuration, with bucket/IAM/tenant separation described in [storage and retention](STORAGE-AND-RETENTION.md). The host must retain historical storage bindings when changing configuration.
Remote HTTPS deployment, real S3/IAM, production OAuth roles, PostgreSQL and operating-system supervision remain separate qualification work. Record Files source-version/actor integration remains pending its concrete public contract; standalone printing delivery storage must not own or delete canonical attachments.
Remote HTTPS deployment, real S3/IAM, production OAuth roles, PostgreSQL and operating-system supervision remain separate qualification work. The optional [retained-source facade](RETAINED-PRINT-FACADE.md) requires a host-supplied source authority; standalone printing delivery storage must not own or delete canonical attachments.
+12 -8
View File
@@ -24,7 +24,7 @@ Normal progression is QUEUED → CLAIMED → RECEIVED → SUBMITTING → SPOOLED
Use a stable business idempotency key for retries of the same request. A changed target/document/options with the same key is a conflict. A deliberately new print requires a new key. The initial implementation does not automatically reclaim RECEIVED/SUBMITTING jobs or resend ambiguous output; inspect the queue and physical result before deciding to print again.
The pending 0.1.4 implementation stores new documents through the host's configured dedicated QQQ S3 storage table; existing inline database content remains readable. Administration defaults to 365 days after server-observed successful completion, with bounded scheduled cleanup when a host scheduler is configured. Active, failed, uncertain and unknown-completion legacy jobs remain protected. See [storage and retention](STORAGE-AND-RETENTION.md) for bucket separation, recovery and versioning details. No live storage migration or cleanup is implied by a source upgrade.
Version 1.0.0 stores new documents through the host's configured dedicated QQQ S3 storage table; existing inline database content remains readable. Administration defaults to 365 days after server-observed successful completion, with bounded scheduled cleanup when a host scheduler is configured. Active, failed, uncertain and unknown-completion legacy jobs remain protected. See [storage and retention](STORAGE-AND-RETENTION.md) for bucket separation, recovery and versioning details. No live storage migration or cleanup is implied by a source upgrade.
## Admission capacity and inventory history
@@ -49,16 +49,17 @@ Inventory snapshots remain limited to 200 entries. Rotating IDs cannot bypass cu
## Device controls and durable action receipts
The native client API is the registered `printing` extension, semantic version
`1.0.0`, under `/qqq/v1/qbit/printing`. Discover it through QQQ's version endpoint;
`2.3.0`, under `/qqq/v1/qbit/printing`. Discover it through QQQ's version endpoint;
its generated OpenAPI fragment is `src/main/resources/openapi/qqq-v1/printing.yaml`.
The contract test checks this fragment against the registered endpoint specs and
the initial semantic compatibility baseline. Core QQQ session authentication and
credential scopes run before printing operations; the application does not issue
another kind of user login token.
Every native operation requires the authenticated QQQ principal, `printing_admin`,
the configured tenant security key, and applicable native table, process and row
access. Device operations additionally require `X-QQQ-Device-Id` and
Native administration and device operations require the authenticated QQQ principal,
`printing_admin`, the configured tenant security key, and applicable native table,
process and row access. The separate [operator catalog and submission API](OPERATOR-CATALOG.md)
also permits `printing_operator`, with its narrower destination/process checks. Device operations additionally require `X-QQQ-Device-Id` and
`X-QQQ-Device-Token` as secondary proof. Enrollment at `/devices/enroll` validates
the user's facility access before consuming the enrollment code and atomically
binds the device to the core user's stable identity. A legacy unbound device can
@@ -94,7 +95,7 @@ reach that context; printing does not assert that an upstream cached session is
fresh. Cookie-authenticated unsafe calls must also satisfy the host's Origin/CSRF
policy. The local host requires its canonical same-origin authority.
In the qualified QQQ 4.1.0-RC.20 runtime, OAuth2 `sessionStoreEnabled` defaults
In the recorded RC.20 authentication qualification, OAuth2 `sessionStoreEnabled` defaults
to `false`. Ordinary requests and session resume rerun the configured
`QAuthenticationModuleCustomizerInterface` hooks; the host can load current
permissions, tenant keys, and account status from its authoritative directory.
@@ -151,7 +152,8 @@ seven days; an unchanged old request still expires after its receipt is removed.
Remote inventory refresh and owned spool cancellation require advertised agent
capabilities, expire after 15 minutes, and have a limit of 100 pending commands
per device. Polls deliver at most 20 commands. The retained action history is
per device. Control delivery is bounded to 20 commands per batch over the real-time
channel; there is no timed job/control polling fallback. The retained action history is
limited to 1,000 records per device, with one additional reserved revocation;
eligible old terminal records are reclaimed before admission. Capacity returns
429 explicitly. History pages contain at most 200 records and use the preceding
@@ -180,4 +182,6 @@ cancellation request, not that paper was withdrawn or a physical print was undon
## Release qualification
Prior released checks include user-confirmed laser PDF and Zebra ZPL/PDF output with correct machine driver settings. Audit source checks cover H2, native processes, host HTTP registration, synthetic storage and small real connection pools. Follow-up qualification includes live S3/IAM, PostgreSQL, production host authentication, upgrade/migration paths, multiple QQQ nodes, prolonged disconnects and a broader printer/driver set. Current prerelease artifacts must not be described as certifying those scenarios.
The stable 1.0.0 library and its matching release/registry bytes are published; see [release evidence](RELEASES.md). Local checks cover H2 persistence, native QQQ operations, real HTTP/WebSocket transport, S3-compatible storage and bounded job histories. User-confirmed physical output includes laser PDF and Zebra ZPL/PDF.
A deployment still supplies and validates its own database, S3/IAM, authentication mapping, supervision and printer drivers. PostgreSQL and multiple-node operation are not qualified by the local H2/MinIO fixture. The default real-time bus is in-process; consult [host integration](REALTIME.md) before scaling hosts. These are deployment boundaries, not pending 1.0 publication tasks.
+7 -4
View File
@@ -1,7 +1,7 @@
# Operator catalog and queue media
This source adds native printing extension 2.3.0 (2.2.0 is the rendering extension and carries no media negotiation). Publication and Windows media
agent qualification are pending. Existing administrator and device routes keep
QQQ Printing 1.0.0 includes native printing extension 2.3.0, paired with Windows
connector 1.0.1. Extension 2.2.0 introduced rendering; 2.3.0 adds this operator/media API. Existing administrator and device routes keep
their permissions; this is an additive operator API, not a device bearer API.
Hosts grant `printing_operator` and the `printing_tenant` security key. The native
@@ -55,8 +55,11 @@ replays remain accepted. The capable Windows agent rechecks its actual current
default before spooling. Selected-media dispatch requires the current agent
capability `printer-media-v1`, including after reconnect/downgrade. Legacy
inventory without profiles clears stale media facts. Omitted selection preserves
ordinary existing queue behavior. Paper-width/height overrides remain unsupported,
including when a media selection is supplied.
ordinary existing queue behavior. An explicit job paper size instead uses both
`paperWidthMm` and `paperHeightMm` (positive, at most 2000 mm); it cannot be
combined with `mediaProfile`. The matching connector applies that job paper
without changing the machine-wide queue defaults. Select media matching the
loaded stock and calibrate the physical printer after changing label sizes.
Generated/retained source authorization belongs to the configured source owner.
The retained facade shares this operator permission and destination boundary; it
+10 -7
View File
@@ -1,9 +1,10 @@
# Real-time printing host integration
Release candidate [0.3.0-rc.1](https://github.com/QRun-IO/qbit-printing/releases/tag/v0.3.0-rc.1)
implements printing extension **2.0.0** (wire envelope v1). Upgrade the server
before the matching Windows connector; a real-time connector rejects a server that advertises only extension
1.x. There is no timed job/control polling fallback.
[QQQ Printing 1.0.0](https://git.kof22.com/QRun-IO/qbit-printing/releases/tag/v1.0.0)
implements native printing extension **2.3.0** (wire envelope v1), paired with Windows
connector **1.0.1**. Upgrade the server before the connector; a real-time connector
rejects a server that advertises only extension 1.x. There is no timed job/control
polling fallback.
## Connection and authorization
@@ -97,13 +98,15 @@ notifications to one another.
The existing `/printing/v1` routes remain explicit legacy diagnostic compatibility.
They are not a real-time fallback and cannot authorize a native bound device.
The full message and settings contract is in
[the shared protocol](https://github.com/QRun-IO/qqq-print-protocol).
[the shared protocol](https://git.kof22.com/QRun-IO/qqq-print-protocol).
## Printing API major upgrade
The extension is **2.0.0** because native HTTP claims now require a synchronized
Extension **2.0.0** introduced the major-version change because native HTTP claims require a synchronized
WebSocket. A published 1.0 HTTP-only connector no longer meets that precondition;
this is a breaking behavior change even though request bodies remain wire v1.
The QQQ framework API `/qqq/v1`, extension path `/qbit/printing` and WebSocket
subprotocol `qqq-printing.v1` remain unchanged. Upgrade server and client together;
an older client must report upgrade-required instead of using polling fallback.
an incompatible older client must report upgrade-required instead of using polling fallback.
Current extension 2.3.0 retains that requirement and adds operator/media support.
The product/library version is independently 1.0.0.
+48
View File
@@ -0,0 +1,48 @@
# Installation and release operations
The stable server library is [QQQ Printing 1.0.0](https://git.kof22.com/QRun-IO/qbit-printing/releases/tag/v1.0.0), paired with protocol 1.0.0 and Windows connector 1.0.1. It requires Java 21 and the QQQ 4.1.0-RC.21 dependency tuple. Its native printing extension is 2.3.0; the WebSocket subprotocol remains `qqq-printing.v1`.
Gitea is primary for source, pull requests, CI, packages and server releases. This forge requires sign-in even for download links on public repositories. An HTML sign-in page is not an artifact. Use your existing approved forge identity; never commit its token or put it in a command line.
## Use the Maven registry
Configure the consuming application's existing Maven repository setup with repository ID `qrun-io` and URL `https://git.kof22.com/api/packages/QRun-IO/maven`. Enable releases and disable snapshots. Match that ID to a `<server>` entry in your private Maven `settings.xml`, using your existing managed username/token or encrypted Maven credentials. For example, environment references keep literal credentials out of the configuration:
```xml
<servers>
<server>
<id>qrun-io</id>
<username>${env.GITEA_USERNAME}</username>
<password>${env.GITEA_TOKEN}</password>
</server>
</servers>
```
Merge this entry into the existing settings; preserve other servers, mirrors and profiles. Supply the environment through your approved credential loader. The credential needs package read access. Add `com.kingsrook.qbits:qbit-printing:1.0.0` as shown in the [README](../README.md#add-to-a-qqq-application). QQQ's RC.21 dependencies resolve from Maven Central; the printing 1.0.0 library resolves from Gitea.
## Download and verify release files
Sign in to Gitea and download all three assets from the stable release: `qbit-printing-1.0.0.jar`, `qbit-printing-1.0.0.pom` and `SHA256SUMS`. In their download directory:
```powershell
Get-Content ./SHA256SUMS | ForEach-Object {
$hash, $name = $_ -split ' ', 2
if((Get-FileHash -LiteralPath $name -Algorithm SHA256).Hash -ine $hash) {
throw "Checksum mismatch: $name"
}
}
```
On Linux, use `sha256sum -c SHA256SUMS`; on macOS, use `shasum -a 256 -c SHA256SUMS`. Install the verified JAR/POM locally with the README's `install:install-file` command if your application does not consume the registry directly. The library needs its normal Maven runtime dependencies; copying the JAR alone does not deploy a complete host.
## Maintainer release path
1. Update the POM version and active documentation on a branch in Gitea. Keep the immutable protocol fixture ref in `.gitea/workflows/qrun-release.yaml` aligned with the reviewed contract.
2. Open a normal pull request and satisfy required CI checks. The caller delegates to the protected `qrun-release-v1` channel; shared CI changes belong to its owner, not an application-specific bypass.
3. Merge normally and wait for the successful main run. Its `maven-reactor` artifact contains tested JAR/POM bytes, a source commit, manifest and checksums. The trusted publisher verifies that evidence before publishing immutable Maven packages. A passing build alone does not prove registry publication.
4. Verify the exact version's registry JAR/POM against the captured bytes. Create `v<POM version>` at the qualified source without moving an existing tag. Create a draft Gitea release, attach the same JAR/POM and a flat `SHA256SUMS`, read them back with the approved forge identity, then publish. Reconcile identical existing artifacts; never replace different bytes under a released version.
5. Record the source, successful run, artifact, release and verified hashes. Publication is separate from installing a host or accepting physical printer output.
For 1.0.0, source `2906c2bd5049924abd2114c8ef51a0ac9aac325e`, main run `3594`, reactor artifact `2741` and release `1356` were verified. Release assets and registry files matched byte-for-byte on authenticated readback. The JAR SHA-256 is `7ecb00e1f49272d6e885dc5f515bd4832aa52dd84e0613d9b6751f9e235a0961`; the POM SHA-256 is `8be7c30208a7fbb875dcebedb0ba6baf0e172aa0e7cf478a3d2863d1316ddf5f`.
GitHub remains a shadow/archive. GitHub Actions for this server repository and the protocol repository were retired on 2026-11-04. Their checked-in workflows and older release evidence are historical. The Windows repository retains its separate signing/update-feed workflow. Do not restart shadow workflows to publish a server release, claim GitHub attestations for 1.0.0, or imply the QBit was published to Maven Central.
+6 -6
View File
@@ -1,6 +1,6 @@
# Retained print acceptance (additive candidate)
# Retained print acceptance
This optional Java integration preserves the existing native generation print
Included in QQQ Printing 1.0.0, this optional Java integration preserves the existing native generation print
process and the existing printing queue. It adds no device wire fields or REST
routes. It is disabled until the host supplies
`PrintingQBitConfig.withRetainedSourceAuthority`. Current `printing_operator`
@@ -108,7 +108,7 @@ Coverage includes commit-then-throw acknowledgment loss, concurrent exact
replay, held-admission-lock lookup, mutation ceilings, owner observation
refusal, callback revocation, exact content hash/length, configured document
bounds, title upgrade/replay, read-only historical lookup and original-error
preservation when rollback fails. Qualification of this adopted source is
recorded in the session notes; the older peer candidate's test result is not
evidence for this revision. Cross-QBit integration remains a separate gate. No
release, install, shared-cache substitution or runtime migration has occurred.
preservation when rollback fails. The library is released; [release evidence](RELEASES.md) identifies its source
and artifacts. Configuring and qualifying a cross-QBit source authority remains
the integrating host's responsibility. Merely upgrading the library does not
enable an adapter, migrate stored source bindings or grant source access.
+11 -9
View File
@@ -1,14 +1,16 @@
# Session state — 2026-10-31
# Session state — 2026-11-04
## CURRENT checkpoint — 1.0.0 release preparation (2026-11-03)
## Current — 1.0.0 released
The release branch includes the primary head `a583f91` and the prepared 1.0.0 version. Windows connector 1.0.1
and protocol 1.0.0 are published. The QQQ pin is now the published `4.1.0-RC.21` candidate that provides native
session login; its BOM was independently retrieved from Maven Central. The existing `-Pui-demo verify` gate
passed against that dependency on 2026-11-03: 193 tests reported, zero failures or errors, one existing opt-in
workload skip and zero Checkstyle violations. Main and test sources compile under the existing Error Prone,
NullAway and warnings-as-errors checks. Printing 1.0.0 publication remains pending its normal CI and release
process. Every checklist below is historical.
[QQQ Printing 1.0.0](https://git.kof22.com/QRun-IO/qbit-printing/releases/tag/v1.0.0) is published on primary Gitea and its Maven registry. Source `2906c2bd5049924abd2114c8ef51a0ac9aac325e` passed main run `3594`; reactor artifact `2741`, release `1356` and both registry files were verified against the captured bytes by authenticated readback. Gitea requires sign-in. See [release operations and hashes](RELEASES.md).
Windows connector 1.0.1 and protocol 1.0.0 are published. The server uses QQQ 4.1.0-RC.21, native printing 2.3.0, wire v1 and client-initiated WebSocket control with separate HTTPS documents. The release preparation's existing `-Pui-demo verify` reported 193 tests, zero failures/errors, one opt-in workload skip and zero Checkstyle violations; the normal hosted main checks subsequently passed.
GitHub is a shadow/archive; server and protocol Actions were retired on 2026-11-04. Windows signing/update-feed workflows remain separate. Current setup, operator, storage and release documentation now describe this released state. This documentation closeout changes no application code or workflows and performs no new hardware/provider qualification. No server 1.0 publication task remains open.
## Historical checkpoints
The entries below are dated development evidence, including superseded pending tasks and older versions. They are not the current release status; use the section above and [current tasks](TODO.md).
## Standards and small-label release cohort — 2026-11-01
+2 -2
View File
@@ -13,5 +13,5 @@ Only leading language comments count. Copyright text in a string, Python docstri
JSON/schema/fixture/lock data, explicit generated output directories, vendor legal assets and upstream Maven wrappers are excluded with reasons in the policy. Solution/activation/test-runner metadata and `.editorconfig` remain outside this completed pass; their applicable root LICENSE/NOTICE remains authoritative. No broad claim about third-party licensing follows from this check. New owned file types or provenance must be reviewed before changing the allowlist; do not add blanket exclusions to make a failure disappear.
The implementation and its negative tests are intentionally maintained copies across the three printing repositories, with each repository's own copyright/license header and independently reviewed scope. They do not fetch policy or execute source. CI invokes them in existing jobs using the runner's available Python, with no new package or workflow context. Existing native C# IDE0073 and Java Checkstyle conventions remain unchanged.
This repository accepts Kingsrook, LLC / Apache-2.0 for its reviewed source/build/config families. The existing CI verify job runs the guard.
The implementation and its negative tests are intentionally maintained copies across the three printing repositories, with each repository's own copyright/license header and independently reviewed scope. They do not fetch policy or execute source. The former GitHub jobs invoked them using the runner's available Python; the scripts remain usable locally without a new package or workflow context. Existing native C# IDE0073 and Java Checkstyle conventions remain unchanged.
This repository accepts Kingsrook, LLC / Apache-2.0 for its reviewed source/build/config families. Run these checks locally when modifying owned notices; the primary shared CI channel owns its current check selection. The old `.github` workflow invocation is retained as history.
+6 -6
View File
@@ -1,6 +1,6 @@
# Print document storage and retention
Status: audit implementation pending final verification and release. QQQ 4.1+ hosts provide the existing storage and scheduler metadata; this module does not create buckets or copy credentials into printing settings.
Included in the released QQQ Printing 1.0.0 library. QQQ 4.1+ hosts provide the existing storage and scheduler metadata; this module does not create buckets or copy credentials into printing settings.
## Deployment boundary
@@ -10,15 +10,15 @@ Keep access keys, role credentials and endpoint configuration in the host's esta
The code validates the selected S3 metadata, detects conflicting bucket bindings within the QQQ instance and uses tenant-specific object namespaces. Each job retains its storage table, destination identity and exact document reference. Retrieval and cleanup validate those values and fail closed if metadata is retargeted or the reference belongs to another tenant/job. Cleanup deletes exact eligible objects; it never lists and wipes a prefix. Tenant prefixes are an application isolation control, not a substitute for separately scoped IAM roles or separate customer buckets.
Application metadata cannot prove that a bucket is unused by another application or that deployed IAM/bucket policies are correct. Deployment qualification must check those external controls, public-access blocking, transport/encryption policy and the intended customer/environment boundary. No live bucket has been created or changed by the audit.
Application metadata cannot prove that a bucket is unused by another application or that deployed IAM/bucket policies are correct. Deployment qualification must check those external controls, public-access blocking, transport/encryption policy and the intended customer/environment boundary. The QBit does not create or change bucket policies.
## S3 key layout and migration
QQQ filesystem 4.1.0-RC.20 builds S3 keys with the host filesystem separator. With empty base paths, Windows writes two leading backslashes before the logical `printing/<tenant-hash>/<job>.ext` reference; Linux writes the canonical reference. Same-platform object operations have been qualified in isolated S3-compatible storage. The logical reference alone is therefore insufficient for IAM prefix rules or migration between platforms.
The reviewed `qqq-s3-filesystem-v1` layout uses the host filesystem separator; the original platform comparison was recorded against QQQ 4.1.0-RC.20. With empty base paths, Windows writes two leading backslashes before the logical `printing/<tenant-hash>/<job>.ext` reference; Linux writes the canonical reference. Same-platform object operations have been qualified in isolated S3-compatible storage. The logical reference alone is therefore insufficient for IAM prefix rules or migration between platforms.
Printing fingerprints the reviewed `qqq-s3-filesystem-v1` layout and the actual `File.separatorChar` code point (47 or 92), alongside the endpoint, bucket, region, path-style setting and backend/table base paths. Ordered JSON encoding preserves the identity component boundaries, including valid multiline base paths. A different layout rejects historical reads, new retries and cleanup with a destination-mismatch error before accessing those objects. New retries whose source binding is already incompatible fail before reserving another upload; the document loader also rechecks the binding when reading. An already-created retry still returns its idempotent receipt. Cleanup preserves content availability, retained-byte accounting and orphan reservations on mismatch.
This S3 feature is unreleased. Old experimental fingerprints without the layout marker are deliberately rejected, even on their original platform. Startup never rewrites those bindings or moves/deletes their objects. Preserve the original database and objects until an explicitly reviewed migration or disposal; do not replace hashes merely to bypass the guard. Inline database documents remain readable and can be explicitly retried into the configured destination without any automatic storage migration.
The released storage implementation requires this layout marker. Old experimental fingerprints without the layout marker are deliberately rejected, even on their original platform. Startup never rewrites those bindings or moves/deletes their objects. Preserve the original database and objects until an explicitly reviewed migration or disposal; do not replace hashes merely to bypass the guard. Inline database documents remain readable and can be explicitly retried into the configured destination without any automatic storage migration.
This guard does not make QQQ keys portable. The upstream owner must provide portable key construction and legacy-key handling. Adopting that change, including a change on the same operating system, requires an explicit layout-marker review and a migration plan for historical bindings and exact objects. The marker is a reviewed compatibility contract, not automatic detection of dependency implementation changes. Cross-platform migration and production IAM remain separate qualification work.
@@ -26,9 +26,9 @@ This guard does not make QQQ keys portable. The upstream owner must provide port
Record Files owns original versions and attachments; document generation owns rendering. Printing owns a separate delivery payload and queue receipts. Never bind printing cleanup to a Record Files bucket or pass an original's storage key as a printing-owned reference. Printing expiration must not remove a source attachment or weaken its retention policy.
The current independent integration seam accepts bytes and a stable business idempotency key. An authorized immutable-version reader and source/job correlation contract are being coordinated with Record Files; that API is not yet implemented or assumed here. Printing currently checks device/destination authorization at dispatch, not later revocation of the source attachment's permissions. A shared adapter must define that boundary before promising revocation propagation.
Direct submission accepts bytes and a stable business idempotency key. The optional [retained-source facade](RETAINED-PRINT-FACADE.md) additionally binds an authorized immutable source, actor, destination and acceptance receipt. It is disabled until the host supplies its source authority; this repository does not configure a Record Files adapter automatically. Printing checks device/destination authorization at dispatch, not later revocation of the source attachment's permissions. The integrating owner must define that boundary before promising revocation propagation.
The existing `PrintEnqueueEffectTarget` accepts base64 document bytes in the host's durable outbox. That outbox may retain another delivery copy outside this module's S3 cleanup policy. Hosts must manage its retention separately; do not claim that configuring printing S3 moves existing outbox payloads or all upstream copies into the printing bucket. The future retained-version adapter should carry authorized opaque source IDs/hash/length/media type and actor/correlation, not bucket URLs or duplicated document bytes. Direct byte submission stores the printing-owned payload through the configured storage backend without adding this host-outbox copy.
The existing `PrintEnqueueEffectTarget` accepts base64 document bytes in the host's durable outbox. That outbox may retain another delivery copy outside this module's S3 cleanup policy. Hosts must manage its retention separately; do not claim that configuring printing S3 moves existing outbox payloads or all upstream copies into the printing bucket. A host-provided retained-version adapter should carry authorized opaque source IDs/hash/length/media type and actor/correlation, not bucket URLs or duplicated document bytes. Direct byte submission stores the printing-owned payload through the configured storage backend without adding this host-outbox copy.
## Administration and scheduled cleanup
+11 -4
View File
@@ -1,10 +1,17 @@
# Follow-up
## CURRENT — 1.0.0 (everything below this section is historical)
## Current — release closeout (2026-11-04)
- [x] Adopt the published QQQ `4.1.0-RC.21` candidate in `pom.xml` and the active release documentation; the BOM resolves from Maven Central.
- [x] Complete the existing normal verification (`./mvnw -Pui-demo verify`) against RC.21: 193 tests reported, zero failures/errors, one existing opt-in workload skip and zero Checkstyle violations.
- [ ] Complete the existing normal publication of `1.0.0` after its required CI checks.
- [x] Adopt published QQQ 4.1.0-RC.21 and complete the existing local verification.
- [x] Pass normal primary CI, publish qbit-printing 1.0.0 and verify the release/registry bytes.
- [x] Publish protocol 1.0.0 and Windows connector 1.0.1; keep their distinct API/product versions documented.
- [x] Update active setup, operating, security and release documentation for Gitea and the released features.
No server 1.0 release task remains open. Deployment-specific database, IAM/provider policy and optional cross-QBit adapters remain the integrating application's responsibilities, described in the operating guides. The legacy optional Authentik diagnostic is documented as an RC.20-era fixture; updating it is not part of this release closeout.
## Historical checklists
Everything below records earlier development checkpoints. Unchecked historical items do not reopen completed or excluded release work.
## Echo integration candidate
+1 -1
View File
@@ -38,4 +38,4 @@ The Windows companion shows recent jobs and a persistent status footer. **View s
## Preview acceptance and limits
The live preview was inspected with frontend 1.0.0-RC.37: the six operational printer columns, named device relationship, disabled generic write actions, and dashboard-to-filtered-table navigation were observed. Selecting the synthetic Zebra, opening Print a test label, reviewing and submitting completed with one printer processed. No physical printer was connected to this demo. Native process authorization and multi-printer execution are also covered by Java tests. A broad browser/accessibility run and final elevated companion interaction run remain separate acceptance tasks; see the README and the Windows repository's UX review.
The live preview was inspected with frontend 1.0.0-RC.37: the six operational printer columns, named device relationship, disabled generic write actions, and dashboard-to-filtered-table navigation were observed. Selecting the synthetic Zebra, opening Print a test label, reviewing and submitting completed with one printer processed. No physical printer was connected to this demo. Native process authorization and multi-printer execution are also covered by Java tests. These are historical preview observations, not evidence for every browser size or deployed printer driver. Current release status is in the [README](../README.md) and [release guide](RELEASES.md).