Stockroom Phase 4 Physical Tracking Plan

Part of the Simple Agility stack. Canonical copy: ~/source/stockroom/docs/superpowers/plans/2026-10-05-stockroom-phase-4-physical-tracking.md (16 test-first tasks with complete code). This page mirrors the decisions for retrieval. It implements StockroomBarcodePhysicalTrackingDesign and follows StockroomPhase3ListingPreparationPlan. Status: written 2026-10-05. Before commit, every task was applied in order to scratch copies of the repo. The backend passed all its gates, with 2,976 unit tests and 136 integration tests. The frontend passed its gate, with 535 tests.

Goal

Barcode-driven physical tracking:

Key decisions

TopicDecision
ContainmentAn explicit table replaces the old rank rule. A room may hold shelves, bins and crates; a shelf may hold bins and crates; bins and crates hold only items.
Crate movesOne component (CrateMoves) moves crates. Each move is locked and logged as a location_event, with notes when the crate has an open pick or an open count.
LabelsPrinted codes are derived from the thing itself, so nothing is stored for them. Stickers live in a registry. An item is marked labeled when a sticker is bound to it or its printed label is confirmed. A labeled copy is never chosen by its ISBN.
Scan resolutionChecked in this order: printed code, then sticker, then product barcode, then typed SKU, then unknown. A product barcode narrows to the crate or place currently being worked in. The Scan page resolves every code first, then decides whether to create a copy.
PrintingA print assigns the queue to a batch, and the PDF opens by navigation (a new tab). A Download fallback exists because the browser viewer is unverified under the app's security policy. Confirming the print marks it printed. Bars land on whole printer dots, and a code too long for its label is refused.
CameraThe browser's native BarcodeDetector where available, otherwise the barcode-detector ponyfill on zxing-wasm. The decoder is served from Stockroom itself, and the security policy gains wasm-unsafe-eval. The camera needs HTTPS.
PicksSources are FBA, buyback, lot and ad hoc. An item is on at most one open pick list. Lines are ordered by location path.
CountsExpected items are snapshotted when a count starts. An item moved elsewhere during the count is reported as moved, not missing. Items not found are flagged missing; scanning a missing item anywhere clears the flag.
Service structureSmall components (CrateMoves, LabelCleanup, OpenPicks) stop services depending on each other in a loop, which would prevent startup.

Tasks

  1. Crates
  2. Labels and the sticker registry
  3. Scan resolution
  4. Placement and undo
  5. The stockroom-labels PDF module
  6. Label queue and printing
  7. Pick lists
  8. Counts and missing items
  9. Frontend foundation
  10. Camera and scan bar
  11. Stock: Place and Find
  12. Stock: Count and Missing
  13. Picks
  14. Labels page, Create crates, label management
  15. Scan page, resolving every code first
  16. Hand-over

Out of scope