From 1f6342e871d7a45590a04b695e2f12f377ab6b14 Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 4 Nov 2026 09:39:13 -0600 Subject: [PATCH] docs: close out printing 1.0 release documentation Update setup, operating and release guidance for the published Gitea artifacts, native API and real-time transport. Preserve historical evidence and scope the older optional Authentik fixture accurately. Co-Authored-By: Codex (GPT-6) --- CONTRIBUTING.md | 8 +++--- README.md | 50 ++++++++++++++++++++--------------- SECURITY.md | 6 ++--- dev/AUTHENTIK.md | 30 ++++++++++++++------- dev/README.md | 22 +++++++-------- dev/native-auth/README.md | 15 ++++++----- docs/JAVA-COMPILER-SAFETY.md | 4 +-- docs/LOCAL-HOST.md | 8 +++--- docs/OPERATIONS.md | 20 ++++++++------ docs/OPERATOR-CATALOG.md | 11 +++++--- docs/REALTIME.md | 17 +++++++----- docs/RELEASES.md | 48 +++++++++++++++++++++++++++++++++ docs/RETAINED-PRINT-FACADE.md | 12 ++++----- docs/SESSION-STATE.md | 20 +++++++------- docs/SOURCE-HEADERS.md | 4 +-- docs/STORAGE-AND-RETENTION.md | 12 ++++----- docs/TODO.md | 15 ++++++++--- docs/UI-WALKTHROUGH.md | 2 +- 18 files changed, 196 insertions(+), 108 deletions(-) create mode 100644 docs/RELEASES.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 044c510..d88a1d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 diff --git a/README.md b/README.md index 3e5630c..a3d51d6 100644 --- a/README.md +++ b/README.md @@ -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=`. @@ -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: com.kingsrook.qbits qbit-printing - 0.3.0-rc.1 + 1.0.0 ``` @@ -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. diff --git a/SECURITY.md b/SECURITY.md index b16f725..32746a6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -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. diff --git a/dev/AUTHENTIK.md b/dev/AUTHENTIK.md index 642f91e..fdd214b 100644 --- a/dev/AUTHENTIK.md +++ b/dev/AUTHENTIK.md @@ -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. diff --git a/dev/README.md b/dev/README.md index cefc678..8b99b81 100644 --- a/dev/README.md +++ b/dev/README.md @@ -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. diff --git a/dev/native-auth/README.md b/dev/native-auth/README.md index 233b116..dad654f 100644 --- a/dev/native-auth/README.md +++ b/dev/native-auth/README.md @@ -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. diff --git a/docs/JAVA-COMPILER-SAFETY.md b/docs/JAVA-COMPILER-SAFETY.md index 9d28532..48da1cb 100644 --- a/docs/JAVA-COMPILER-SAFETY.md +++ b/docs/JAVA-COMPILER-SAFETY.md @@ -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. diff --git a/docs/LOCAL-HOST.md b/docs/LOCAL-HOST.md index 16fdfc1..c1c72ff 100644 --- a/docs/LOCAL-HOST.md +++ b/docs/LOCAL-HOST.md @@ -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. diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index 02d2f15..cc18252 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -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. diff --git a/docs/OPERATOR-CATALOG.md b/docs/OPERATOR-CATALOG.md index 3edd1cf..03c9e0f 100644 --- a/docs/OPERATOR-CATALOG.md +++ b/docs/OPERATOR-CATALOG.md @@ -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 diff --git a/docs/REALTIME.md b/docs/REALTIME.md index ef4cbdb..149c254 100644 --- a/docs/REALTIME.md +++ b/docs/REALTIME.md @@ -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. diff --git a/docs/RELEASES.md b/docs/RELEASES.md new file mode 100644 index 0000000..6557965 --- /dev/null +++ b/docs/RELEASES.md @@ -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 `` 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 + + + qrun-io + ${env.GITEA_USERNAME} + ${env.GITEA_TOKEN} + + +``` + +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` 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. diff --git a/docs/RETAINED-PRINT-FACADE.md b/docs/RETAINED-PRINT-FACADE.md index 68b36af..61ff17e 100644 --- a/docs/RETAINED-PRINT-FACADE.md +++ b/docs/RETAINED-PRINT-FACADE.md @@ -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. diff --git a/docs/SESSION-STATE.md b/docs/SESSION-STATE.md index 03ee8a9..a3f3b1a 100644 --- a/docs/SESSION-STATE.md +++ b/docs/SESSION-STATE.md @@ -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 diff --git a/docs/SOURCE-HEADERS.md b/docs/SOURCE-HEADERS.md index bde6a98..5f5b027 100644 --- a/docs/SOURCE-HEADERS.md +++ b/docs/SOURCE-HEADERS.md @@ -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. diff --git a/docs/STORAGE-AND-RETENTION.md b/docs/STORAGE-AND-RETENTION.md index e4de0b5..58bf8a8 100644 --- a/docs/STORAGE-AND-RETENTION.md +++ b/docs/STORAGE-AND-RETENTION.md @@ -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//.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//.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 diff --git a/docs/TODO.md b/docs/TODO.md index c554d9f..1436bc2 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -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 diff --git a/docs/UI-WALKTHROUGH.md b/docs/UI-WALKTHROUGH.md index 6c4c007..02f4618 100644 --- a/docs/UI-WALKTHROUGH.md +++ b/docs/UI-WALKTHROUGH.md @@ -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). -- 2.54.0