2 Commits
Author SHA1 Message Date
aarbit 26f41b3d4a Rename Project to Diagram throughout the app
Per organized-ideas.md §8: the storage layer (DiagramRepository etc.) was
already renamed in an earlier phase; this finishes it everywhere else.

- domain/types.ts: Project -> Diagram. domain/project.ts -> domain/diagram.ts
  (createEmptyProject -> createEmptyDiagram, default name "Untitled Diagram").
- domain/compatibility.ts, domain/bom.ts: Project param/type -> Diagram.
- data/exportImport.ts: ProjectImportError -> DiagramImportError,
  projectToJson/downloadProjectFile/readProjectFile/normalizeProject -> their
  Diagram equivalents.
- state/projectStore.ts -> state/diagramStore.ts: useProjectStore ->
  useDiagramStore, the `project` field -> `diagram`, newProject/renameProject/
  importProject/applyRestoredProject -> *Diagram, restoredProjectUpdatedAt ->
  restoredDiagramUpdatedAt.
- Every component updated to match, compiler-guided (tsc -b enumerated each
  remaining call site after the core rename, the same approach used for the
  earlier catalog-parameter refactor).
- README updated for the terminology, and to match the repository class
  names (which had already been renamed but the README hadn't caught up).

No backend/schema changes: the JSON shape stored in diagrams.data never
changed, only TypeScript-side identifiers, so existing diagrams are
unaffected. One SQL comment fixed for accuracy (no migration needed).

Verified: tsc -b and oxlint clean; grepped src/ for any remaining
Project/project reference (none) after the sweep.
2026-09-11 12:10:11 -05:00
aarbit 1f8d49345e Add the Admin review queue
Lets an Admin/Super-Admin review pending catalog submissions and approve
(in place, same id) or reject (with a required reason) them, per
organized-ideas.md §3/§9.

Backend (supabase/migrations/20260910010000_admin_review_queue.sql):
- Per-user pending-submission cap (10), enforced in catalog_submissions'
  insert policy rather than trusted to the client.
- catalog_entity_usage_impact(entity_type, entity_id): a SECURITY DEFINER,
  admin-gated aggregate function answering "how many diagrams reference
  this, and a short sample" by scanning diagrams.data JSONB — never raw
  diagram content, and available to regular Admins even though they don't
  otherwise have diagram visibility (only Super Admins do, per §6).
- catalog_submission_submitters(ids[]): same admin-gated pattern, batched,
  so the queue can show who submitted something without opening general
  profile browsing to regular Admins.
- Follow-up migration: a rejected submission had no way out (the delete
  policy only allowed withdrawing 'pending') — extended to allow 'rejected'
  too, so a submitter can dismiss one they don't intend to revise.
- 12 new pgTAP tests (38/38 total) covering the cap, both privileged
  functions (including the non-admin-gets-rejected case), and withdrawing
  pending vs. rejected submissions.

Frontend:
- authStore: minimal role awareness, replacing TopBar's local username
  fetch, used to gate the Review Queue UI.
- AdminSubmissionRepository/SupabaseAdminSubmissionRepository +
  adminReviewStore: list all submissions, approve/reject, usage impact,
  submitter usernames.
- AdminReviewModal: per-submission diff view (current vs. proposed, both
  row-shaped via the existing catalog<->row mappers), a duplicate-detection
  nudge (Levenshtein distance against existing public device names) for
  new device submissions, and an inline impact-check for edits to
  already-public entries before approving.
- TopBar: role-gated "Review Queue" button with a pending-count badge; "My
  Submissions" gets an unseen-outcome badge (localStorage-tracked, like the
  existing hidden-template preference) so a submitter notices a decision
  without having to keep reopening the modal.
- Deliberately deferred: the site-wide announcement banner (its own
  follow-up, per discussion) and the Admin/Super-Admin role-assignment UI
  (§9's later phase — becoming an Admin locally still means setting
  profiles.role via SQL/Studio).

Verified: tsc -b and oxlint clean; supabase db reset + 38/38 pgTAP tests
pass; confirmed the two new RPC functions are actually reachable through
PostgREST (not just raw SQL) via a live curl call; manually tested
submit -> review -> approve/reject -> (for rejected) dismiss end to end.
2026-09-08 13:01:56 -05:00