WIP: feat(station): a print station authenticates as its own identity (printing_station, station enrollment code) #37
Draft
james.maes
wants to merge 1 commits from
feat/station-identity-20261110 into feat/multi-node-realtime-20261110
pull from: feat/station-identity-20261110
merge into: QRun-IO:feat/multi-node-realtime-20261110
QRun-IO:main
QRun-IO:fix/delete-refusal-under-lock
QRun-IO:feat/delete-stations-printers-20261111
QRun-IO:fix/print-job-created-date-time
QRun-IO:feat/multi-node-realtime-20261110
QRun-IO:wip/native-auth-pins-20261107
QRun-IO:docs/release-1.1.2-20261106
QRun-IO:ci/gitea-registry-rc22-20261106
QRun-IO:docs/release-1.1.1-20261106
QRun-IO:fix/realtime-header-case-20261106
QRun-IO:docs/release-1.1.0-20261105
QRun-IO:feat/remove-printers-devices-main-20261105
QRun-IO:feat/printer-approval-20261105
QRun-IO:feat/remove-printers-devices-20261105
QRun-IO:docs/printing-release-closeout-20261104
QRun-IO:release/printing-1.0.0-20261103
QRun-IO:release/printing-cohort-20261101
QRun-IO:dependabot/maven/org.codehaus.mojo-exec-maven-plugin-3.6.4
QRun-IO:dependabot/maven/org.apache.maven.plugins-maven-surefire-plugin-3.6.1
QRun-IO:dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.6.0
QRun-IO:migration/cutoff-cf06815f30e1-b9a717
QRun-IO:migration/cutoff-7bedb1016fa9-a854c1
QRun-IO:migration/cutoff-5f74c0c69a55-38f8f8
QRun-IO:dependabot/maven/com.puppycrawl.tools-checkstyle-14.3.0
QRun-IO:dependabot/maven/com.kingsrook-qbit-build-parent-2.1.2
QRun-IO:dependabot/github_actions/github/codeql-action/upload-sarif-4.39.1
QRun-IO:dependabot/github_actions/github/codeql-action/init-4.39.1
QRun-IO:dependabot/github_actions/astral-sh/setup-uv-10.3.2
QRun-IO:dependabot/github_actions/KofTwentyTwo/standards/dot-github/workflows/pr.yml-1.2.1
QRun-IO:dependabot/github_actions/actions/setup-java-6.1.0
QRun-IO:chore/printing-quality-integration-20261101
QRun-IO:feat/small-label-tests-20261101
QRun-IO:archive/qrun-github-cutover-20261101/e08b3ef9c817/dependabot/github_actions/github/codeql-action/init-4.39.1
QRun-IO:migration/cutoff-e08b3ef9c817-b21637
QRun-IO:archive/qrun-github-cutover-20261101/de286e7eb67b/dependabot/github_actions/github/codeql-action/upload-sarif-4.39.1
QRun-IO:migration/cutoff-de286e7eb67b-06d241
QRun-IO:archive/qrun-github-cutover-20261101/cc4dc3dc2700/dependabot/github_actions/astral-sh/setup-uv-10.3.2
QRun-IO:migration/cutoff-cc4dc3dc2700-4e3528
QRun-IO:archive/qrun-github-cutover-20261101/2cec82bf4aa9/dependabot/github_actions/actions/setup-java-6.1.0
QRun-IO:migration/cutoff-2cec82bf4aa9-68d7f8
QRun-IO:archive/qrun-github-cutover-20261101/2a2eedc89f64/dependabot/github_actions/KofTwentyTwo/standards/dot-github/workflows/pr.yml-1.2.1
QRun-IO:migration/cutoff-2a2eedc89f64-2894f0
QRun-IO:archive/qrun-github-cutover-20261101/088692e3aefa/main
QRun-IO:archive/qrun-github-cutover-20261101/7bedb1016fa9/dependabot/maven/org.apache.maven.plugins-maven-surefire-plugin-3.6.1
QRun-IO:archive/qrun-github-cutover-20261101/5f74c0c69a55/dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.6.0
QRun-IO:archive/qrun-github-cutover-20261101/1db6a1163d5e/dependabot/github_actions/actions/setup-java-6.1.0
QRun-IO:archive/qrun-github-cutover-20261101/c8f8e016cf29/dependabot/maven/com.kingsrook-qbit-build-parent-2.1.2
QRun-IO:migration/cutoff-c8f8e016cf29-8a552b
QRun-IO:archive/qrun-github-cutover-20261101/cf06815f30e1/dependabot/maven/org.codehaus.mojo-exec-maven-plugin-3.6.4
QRun-IO:archive/qrun-github-cutover-20261101/985acc06d7e9/dependabot/maven/com.puppycrawl.tools-checkstyle-14.3.0
QRun-IO:migration/cutoff-985acc06d7e9-7f35cb
QRun-IO:archive/qrun-github-cutover-20261101/1a0964ef233d/main
QRun-IO:chore/server-source-standards-20261101
QRun-IO:archive/qrun-github-cutover-20261101/02b922aa11fa/main
QRun-IO:archive/qrun-github-cutover-20261101/4f962f7fbfd8/dependabot/maven/com.kingsrook-qbit-build-parent-2.1.2
QRun-IO:archive/qrun-github-cutover-20261101/8460edb60d58/dependabot/maven/org.apache.maven.plugins-maven-surefire-plugin-3.6.1
QRun-IO:archive/qrun-github-cutover-20261101/05c83067e182/dependabot/maven/com.puppycrawl.tools-checkstyle-14.3.0
QRun-IO:archive/qrun-github-cutover-20261101/b1b8f3b065b8/dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.6.0
QRun-IO:archive/qrun-github-cutover-20261101/e0ff82392398/dependabot/maven/org.codehaus.mojo-exec-maven-plugin-3.6.4
QRun-IO:feat/print-anything
QRun-IO:feat/record-printing
QRun-IO:archive/qrun-github-cutover-20261101/9128133f5cdd/dependabot/github_actions/actions/setup-java-6.1.0
QRun-IO:docs/installed-native-020-20261031
QRun-IO:dependabot/github_actions/KofTwentyTwo/standards/dot-github/workflows/codeql.yml-1.2.1
QRun-IO:dependabot/github_actions/actions/download-artifact-8.0.2
No Reviewers
Labels
Clear labels
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
java
question
secuurity
wontfix
Something isn't working
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Pull requests that update GitHub Actions code
Good for newcomers
Extra attention is needed
This doesn't seem right
Pull requests that update java code
Further information is requested
This will not be worked on
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: QRun-IO/qbit-printing#37
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Draft. Stacked on #36 (
feat/multi-node-realtime-20261110): this branch starts at its head and the base of this pull request is that branch, so the diff is only the station change. Retarget tomainafter #36 merges.Why
A print station is a computer beside a printer with nobody signed in. Today it runs under the session of the person who paired it and renews that session every five minutes. Hosts are adopting automatic logoff (15 minutes without a real user action, 12 hours at most; QQQ
feat/session-user-activity). A station never has a user action to report, so it would be signed out 15 minutes after every sign-in, and inactivity logoff cannot be switched on while stations use people's sessions. It is also hard to defend a named person's session running unattended around the clock.What changes
A station can authenticate as its own identity, issued by the host's identity provider. Full description, guarantees, the host contract, what the other repositories need, the release order and the dev runbook:
docs/STATION-IDENTITY.md.printing_station. Alone it opens nothing. On the device routes, after the request proves the one device bound to the station's identity, the station may heartbeat, report printers, claim, download and acknowledge its own jobs and answer control commands. Every row it reads must belong to that device. Processes (so test print, retry, cancel, enrollment, device actions) and the administrative, operator and generic table routes stay closed.printingEnrollStation(printing administrators) creates a one-use, 15-minute code.POST /qqq/v1/qbit/printing/stations/enrollredeems it with no session: the code is the authority. The answer carries the device proof and the identity's credential once. A station code cannot pair a person; a person's code cannot create a station.PrintingStationIdentities(issue,revoke), set withPrintingService.withStationIdentities. Without it no station code can be created or redeemed (503). Revoking or removing a station's device revokes its identity too; a provider failure answers 502 and the action can be repeated.Authorization: Bearer. It is verified again on every frame.printing_enrollment.station_nameandprinting_device.station_name.Print devicesshows the station name.The claim and acknowledgement rules of #36 are untouched: the readiness gate, the guarded
QUEUED→CLAIMEDupdate, at-least-once delivery with no second hand-out of a received job, and the connection record owned by the connection it names.Tests
PrintingStationTest(5 tests, real QQQ, H2, HTTP and WebSocket):RECEIVEDover HTTP andSPOOLEDover the socket with a bearer credential and no cookie; the administrative, pairing, operator and generic table routes refuse it; a person's bearer never holds the realtime channel; revocation stops it.Gate
./mvnw -B -Pui-demo verifyon this head (254f6fd), run locally on 2026-11-10 with no skip flags: BUILD SUCCESS, 220 tests, 0 failures, 0 errors, 1 skipped (PrintingWorkloadTest, not touched here). Checkstyle ran at validate;PrintingClaimPostgresTest(4, PostgreSQL 17 in Docker) andPrintingMultiNodeTest(5) ran. The run used a settings file that only names the QRun-IO Gitea Maven registry, because this workstation's default settings resolve Central only. Hosted CI has not run on this head.Not in this pull request
The host wiring (gg-forge), the identity account API (qbit-authentik), the Authentik declarations and the Windows client are specified in
docs/STATION-IDENTITY.mdsection 6 and are not built. No release, tag or deployment.🤖 Generated with Claude Code
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.