Skip to content

feat: operator print station (locked print-only mode with scanner input) - #6

Merged
glenntosco merged 4 commits into
mainfrom
claude/project-thread-5e0lug-print-station
Oct 24, 2026
Merged

glenntosco merged 4 commits into
mainfrom
claude/project-thread-5e0lug-print-station

Conversation

@glenntosco

Copy link
Copy Markdown
Collaborator

Requested by Glenn · project thread

What changed and why

Assessment item 9. Stacks on #5 (printer status): merge #5 first and GitHub retargets this to main.

A print station: a locked, print-only screen for warehouse operators, opened with Rotula.exe --station <folder | station.json | label> or File > Open print station.... Labels appear as large tiles with search; the label's prompts become large fields that take keyboard-wedge scanner input; printing goes through the existing IPrintService path with the ~HS status check; the result is shown in large plain words. No menus, design tools or file dialogs. Leaving needs a PIN when one is set.

  • Configuration (Rotula.Files.Station): StationConfigLoader reads station.json from a folder, a given file, next to a single label, or %ProgramData%\Rotula\station.json (--station with no path). Allowed labels and scan keys, named printers (Windows queue or TCP), printer per label or default, copy defaults and limits, data merge on/off, kept values, print on last scan, scan to select, full screen. Unknown settings are rejected; every problem is a StationConfig.* message key with setting and line.
  • Exit PIN: StationPin stores a PBKDF2-SHA256 hash (600,000 iterations, random salt), constant-time check, framework only. Created with File > Create print station PIN... or Rotula.exe --station-pin. Five wrong PINs lock the box for 30 seconds.
  • Scanner: UI-free ScanSequencer. Enter/Tab validates against the prompt rules (required, length, pattern) and advances, Shift+Tab goes back, the last scan prints or moves to Print. Scanning a label's key opens that label.
  • Station window: tiles with thumbnails from the preview cache, prompt fields, quantity, live preview, big Print button; status shows ready / held back with reason / printed and verified / not confirmed / problem. Prompts reset after printing, keeping configured values. Optional "Print all records" for labels with saved data.
  • 70 strings in en + es; docs/print-station.md (full station.json schema), decisions entry, README (en/es), CHANGELOG.

How it was tested

  • StationConfigTests: loading, defaults, overrides, every validation key, resx coverage of the keys.
  • StationScanTests: PIN hash/verify, scan sequencing, scan-to-select.
  • AppStationTests: view-model flow with a fake print service (advance and print, reset with kept fields, refused scan, held back, verified, not verified, fault, copy limit, no printer, data merge on/off, PIN-gated exit with lockout, command-line parsing, designer menu, PIN tool).
  • Solution builds with 0 warnings. Config/scanner tests also ran in a Linux scratch harness; App tests run on Windows CI.

Checklist

  • Build passes; tests run on Windows CI
  • New behavior has tests
  • XML docs and "why" comments
  • New text in both Strings.en.resx and Strings.es.resx
  • No telemetry; light theme only
  • No new dependencies
  • CHANGELOG.md updated
  • Hygiene check passes

Notes

  • The PIN stops an operator leaving by accident; it is not a security boundary (anyone who can edit station.json can remove it, and Windows key / Ctrl+Alt+Del are not blocked). For a fully locked PC, use Windows Assigned Access with Rotula.exe --station; the docs say so.
  • The status check is on by default for every station printer; "checkStatus": false turns it off per printer.
  • The live preview treats the answers as a data record, so a prompt that overrides a record shows its default in the preview only; the printed label is correct.
  • Scanner input relies on the Enter/Tab terminator; telling scans from typing by speed was left out on purpose (see decisions.md).

Generated by Claude Code

…cing

Add StationConfigLoader (station.json next to the labels, a folder, a
single label or the ProgramData policy file), validated with
StationConfig.* message keys; StationPin (PBKDF2-SHA256 hash and
constant-time verify); and the UI-free ScanSequencer that turns Enter,
Tab and Shift+Tab into field moves, print and label selection.
A locked, print-only station window with label tiles and search, large
prompt fields with scanner input, quantity limits, live preview and a
big plain-words printer status. Printing goes through IPrintService with
the status check on, then the prompts reset keeping the configured
values. Exit is PIN-gated with a lockout. Entry points: --station,
--station-pin and two File menu items. Strings in en and es.
Add docs/print-station.md (entry points, station.json schema, problem
keys, status meanings, PIN), a decisions entry, the README feature rows
and sections in English and Spanish, and the changelog entry.

Copy link
Copy Markdown
Collaborator Author

CI note: the one failure on deeed47 is VarCounterTests.ALockHeldByAnotherProgram_IsRespected_UntilThatProgramEnds ("the helper process did not start", 30 s timeout). That test and the counter-lock code are untouched by this PR, and the same code passed the full suite in the stacked CI run (#11, 4,267 tests). It looks like the runner was slow to start the helper process, so I re-ran the failed job once.


Generated by Claude Code

@glenntosco
glenntosco merged commit 0db8297 into main Oct 24, 2026
7 of 8 checks passed
glenntosco added a commit that referenced this pull request Oct 27, 2026
feat: operator print station (locked print-only mode with scanner input)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants