110 lines
3.4 KiB
Markdown
110 lines
3.4 KiB
Markdown
|
|
---
|
|||
|
|
name: scanner-correctness-polish
|
|||
|
|
classification: infra-only
|
|||
|
|
success_metric: |
|
|||
|
|
Mark-Owned is idempotent (in-flight lock per queue row); bulk toolbar no
|
|||
|
|
longer uses setTimeout(..., 100); pages/scanner.js imports lib/use-auth
|
|||
|
|
not legacy auth-context; POST /api/collections/[identifier]/cards calls
|
|||
|
|
logCollectionActivity('card_added', …).
|
|||
|
|
skip:
|
|||
|
|
- ia
|
|||
|
|
- ux
|
|||
|
|
- visual
|
|||
|
|
- a11y
|
|||
|
|
- design
|
|||
|
|
status: open
|
|||
|
|
created: 2026-05-27
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Convoy: scanner-correctness-polish
|
|||
|
|
|
|||
|
|
Fix scanner-page correctness bugs without changing UX or visual design.
|
|||
|
|
|
|||
|
|
## Why
|
|||
|
|
|
|||
|
|
The scanner audit surfaced non-security bugs that cause duplicate adds,
|
|||
|
|
racey bulk actions, a stale auth import, and missing activity logs. These
|
|||
|
|
are small fixes with high reliability impact during bulk scanning sessions.
|
|||
|
|
|
|||
|
|
## Scope
|
|||
|
|
|
|||
|
|
### In scope
|
|||
|
|
|
|||
|
|
- **`pages/scanner.js`**
|
|||
|
|
- Line 8: change import from legacy `lib/auth-context` to `lib/use-auth`
|
|||
|
|
(should have been swept by `single-auth-provider`; scanner was missed or
|
|||
|
|
regressed).
|
|||
|
|
- **Mark-Owned idempotency** — in-flight lock per queue row so double-tap
|
|||
|
|
/ double-click cannot duplicate POSTs.
|
|||
|
|
- **Bulk toolbar** — remove `setTimeout(..., 100)` race; await or use
|
|||
|
|
proper batch completion signal.
|
|||
|
|
- **`pages/api/collections/[identifier]/cards.js`** — POST handler calls
|
|||
|
|
`logCollectionActivity(collectionId, userId, 'card_added', details)` per
|
|||
|
|
AGENTS.md convention.
|
|||
|
|
|
|||
|
|
### Out of scope
|
|||
|
|
|
|||
|
|
- **Scanner UX redesign** — convoy `redesign-scanner-flow` (#4).
|
|||
|
|
- **Copy / vocabulary** — convoy `rename-collections-vocabulary` (#5).
|
|||
|
|
- **OCR / identify pipeline** — convoys #2–#3.
|
|||
|
|
- **Visual or a11y changes** — none intended; diff should be behavior-only.
|
|||
|
|
|
|||
|
|
## Roles invoked
|
|||
|
|
|
|||
|
|
1. `role-architect` — single brief (lightweight; may be parent-owned given
|
|||
|
|
infra-only classification).
|
|||
|
|
2. `role-implementer` — one brief.
|
|||
|
|
3. `role-reviewer` — post-PR only (design + a11y skipped).
|
|||
|
|
|
|||
|
|
## Todos
|
|||
|
|
|
|||
|
|
- [ ] Architect: brief-1 with exact line targets
|
|||
|
|
- [ ] Fix use-auth import on scanner page
|
|||
|
|
- [ ] Add per-row in-flight lock for Mark-Owned
|
|||
|
|
- [ ] Replace setTimeout bulk-toolbar pattern
|
|||
|
|
- [ ] Wire logCollectionActivity on collection card POST
|
|||
|
|
|
|||
|
|
## Operator action required
|
|||
|
|
|
|||
|
|
**None.**
|
|||
|
|
|
|||
|
|
## Multitask dispatch
|
|||
|
|
|
|||
|
|
Single brief — no implementer fan-out.
|
|||
|
|
|
|||
|
|
**Cross-convoy parallelism:** after #1 merges, run alongside **#2 Brief 1**
|
|||
|
|
and **#5 Brief 1** — disjoint files (`pages/scanner.js` vs migrations vs
|
|||
|
|
copy sweep). Coordinate if both #6 and #5 touch `pages/scanner.js` (IA
|
|||
|
|
should sequence copy sweep after correctness or split files in briefs).
|
|||
|
|
|
|||
|
|
Post-PR audit:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
/multitask role-reviewer
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Group id: `audit-scanner-correctness-polish-<pr>`.
|
|||
|
|
|
|||
|
|
## CI impact
|
|||
|
|
|
|||
|
|
| Workflow / job | Behavior |
|
|||
|
|
| --- | --- |
|
|||
|
|
| `ci.yml` | Standard lint + vitest; no new gates. |
|
|||
|
|
| `preview-smoke.yml` | Fires. |
|
|||
|
|
| `visual-diff.yml` | **May fire** if `pages/scanner.js` changes — behavior-only diff should not move pixels; baseline swallow if triggered. |
|
|||
|
|
|
|||
|
|
## Known constraints
|
|||
|
|
|
|||
|
|
- **`logCollectionActivity` import** — use existing helper from
|
|||
|
|
permission-middleware or documented activity module; match sibling handlers.
|
|||
|
|
- **No UX copy changes** — button labels stay as-is until #5 (or avoid
|
|||
|
|
overlapping scanner.js edits between #5 and #6).
|
|||
|
|
|
|||
|
|
## Acceptance criteria
|
|||
|
|
|
|||
|
|
1. `pages/scanner.js` imports from `lib/use-auth` only.
|
|||
|
|
2. Double-click Mark-Owned produces one POST.
|
|||
|
|
3. Bulk toolbar actions complete without setTimeout race.
|
|||
|
|
4. Collection card POST emits activity log row.
|
|||
|
|
5. Vitest 21/21; lint baseline preserved.
|