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
1 Commits
Author SHA1 Message Date
james.maesandClaude Fable 5.2 254f6fd918 feat(station): a print station authenticates as its own identity
maven / build (push) Successful in 7m38s
build / maven (push) Successful in 7m38s
A print station is a computer beside a printer with nobody signed in. Until
now it ran under the session of the person who paired it and renewed that
session every five minutes. A host that ends sessions after user inactivity
would sign it out 15 minutes after every sign-in, and a named person's
session running unattended is hard to defend.

- printing_station: a permission that alone 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. The proof lives in
  the request's QContext, tied to that session object, never on the session.
  Every row read must belong to that device. Processes and the
  administrative, operator and generic table routes stay closed.
- printingEnrollStation creates a one-use, 15-minute station code.
  POST /qqq/v1/qbit/printing/stations/enroll redeems it with no session and
  answers once with the device proof and the identity's credential. A station
  code cannot pair a person and a person's code cannot create a station.
- PrintingStationIdentities (issue, revoke) is the host's issuer, set with
  PrintingService.withStationIdentities. Without it there is no station
  enrollment (503). An identity issued for an enrollment that then fails is
  revoked. Revoking or removing a station's device revokes its identity; a
  provider failure answers 502 and the action can be repeated.
- The realtime upgrade accepts exactly one credential: a session cookie, or,
  for a station only, a bearer token, verified again on every frame.
- Two additive nullable columns: printing_enrollment.station_name and
  printing_device.station_name. Extension 2.5.0; wire v1 and the subprotocol
  are unchanged, and existing pairings behave as before.

The claim and acknowledgement rules of realtime printing on several nodes are
untouched. docs/STATION-IDENTITY.md describes the flow, the guarantees, the
host contract, what the host, the identity QBit, the provider and the Windows
client still need, the release order and the first enrollment on dev.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-10 17:55:30 -06:00