6.2 KiB
TODOS
Design debt and follow-ups surfaced by /plan-design-review of the approval
workflow UX (2026-05-14). Each entry is self-contained: pick one up and read
the Context to understand the motivation without re-running the review.
1. /reviews "Мои" tab — maker visibility ✅ SHIPPED MR !188
Closed via MR !188 (2026-05-14). Final shape: flat mixed timeline (records
- schemas together sorted DESC), filter chips All/Pending/WIP/Decided with per-bucket counts, ReviewDrawer status-aware (read-only decision banner for terminal states, Withdraw for own-pending). 13 unit tests on classifiers + 32 i18n keys. Schema rows link to /dictionaries/$name (existing drawer there); record rows reuse ReviewDrawer with status-gated footer.
2. Interaction state pass — reviews page polish
What. One MR covering five small fixes:
- Records empty state: add description + primary action ("Queue is clear, see
/audit for past decisions"). Current
<EmptyState title={t('reviews.empty')} />is just a heading. - Reject reason inline validation: today
handleRejectdoesif (!comment.trim()) returnsilently. Button click → nothing happens. Show inline error or set the TextArea into error state. - Drawer empty state (
workflow.schemaDraft.empty): distinguish "not loaded", "not found" (deleted), "no permission". Today the same blank message covers all three. - Approve action: drawer closes immediately on success. Add a 500ms success state (or toast) so the reviewer gets visual confirmation. Currently feels like the click might not have registered.
- Post-bulk-result polish: the
bulkResultAlert lists business keys but the failed list shows rawreasoncodes (self_approve_forbidden,draft_not_pending). Map throughextractReviewErroralready in the file.
Why. Pass 2 rated state coverage 5/10. These are the visible gaps. Each is 10-30 LOC; the value is interaction confidence.
Pros. All in one place — reviews.tsx, SchemaDraftDrawer.tsx. Low risk.
Cons. Five different surfaces in one MR means review surface is wider than a single-purpose change. Still worth grouping because they're all "state polish" semantically.
Context. Pass 2 finding. None of these block functionality; they're trust builders. Reject silent fail is the most user-visible — a reviewer clicks the button and nothing happens, then notices the TextArea is empty after a beat.
Depends on / blocked by. Nothing.
5. DESIGN.md for the admin UI
What. Run /design-consultation skill or stub DESIGN.md manually to lock
the implicit design system: drawer-vs-modal usage rules, term glossary
(maker / reviewer / publisher and their Russian counterparts), Badge variant
mapping (CREATE → success, UPDATE → info, CLOSE → warning — already used
consistently but undocumented), code panes pattern (live = bg-line/30,
proposed = bg-accent/4).
Why. Pass 5 rated design system alignment 4/10. The system exists — design tokens are used consistently — but it's tribal knowledge. Next developer building a feature like "Phase 4 webhook approvals" will guess and either match by luck or drift.
Pros. Half-day work. Pays off on every new feature. Source of truth for
/plan-design-review calibration on future plans.
Cons. Documentation has to be maintained or it lies. Mitigated by keeping DESIGN.md to invariants (tokens, primitives, semantic rules), not specific components.
Context. User chose "defer to /design-consultation sprint" instead of stubbing inline. The decision is to do it properly when the sprint happens, not piecemeal during this review.
Depends on / blocked by. Nothing.
6. A11y audit post-deploy via /design-review
What. After the in-flight approval workflow MRs deploy to staging, run
/design-review skill against the live /reviews page + DictionaryEditorDialog
flow. The skill does Lighthouse, axe, screen reader walk-through, contrast
audit, keyboard navigation testing.
Why. Pass 6 rated responsive/a11y 5/10. Specific suspects:
- Button heights not verified at 44px touch target.
text-mutecontrast againstbg-surface— might fail WCAG AA 4.5:1.- Reject reason TextArea has no specified
minHeight. - Bulk action toolbar wrap behavior at 375px.
- Diff
<pre>panes have no aria-label — screen reader reads JSON literally. - Keyboard tab order through long diff panes — reviewer may have to tab 50 times to reach approve buttons.
Pros. Necessary for compliance contexts (gov contracts, accessibility laws). Catches things static review misses (real screen reader, real touch device).
Cons. Requires the in-flight MRs to be deployed first. Cannot do in plan mode.
Context. User chose "defer to /design-review post-deploy". The audit will produce its own punch list with severity ratings.
Depends on / blocked by. MRs !179, !180, !182, !183, !184, !185 deployed to staging.
7. Notifications service: draft decision toast + email
What. Notifications service subscribes to outbox RecordDraftApproved / RecordDraftRejected / RecordDraftWithdrawn events (now fired thanks to
MR !184) and:
- Fires email to maker with reviewer comment.
- Sets a flag (DB or Redis) so on next login the admin UI shows a toast:
"Your draft for
test1/BK-42was approved by reviewer X. The record is now live." - Bell icon in the header gains a badge counter for unread decisions.
Why. Maker has no synchronous feedback. They submit, then either:
- Tab "Мои" → Decided (covered by TODO 1) — but only when they come back
- This TODO — push notification so they know without re-visiting
Pros. Closes the maker feedback loop. Reuses the outbox infra. Mirrors
existing notification flows in ordinis-notifications.
Cons. New email template + new in-app toast surface + bell badge. Half-day to a day of work split between notifications service and admin-ui.
Context. Pass 7 unresolved decision. User chose "in-app toast + email via notifications service" over the lighter "tab badge polling" option. Backend events already fire (MR !184), so the gate is consumer side.
Depends on / blocked by. MR !184 deployed. TODO 1 ("Мои" tab) helps but is not a hard blocker — the toast and email work without that surface.