/** Which catalog table a submission is about. Mirrors `catalog_submissions.entity_type`'s * check constraint. */ export type CatalogEntityType = 'device_template' | 'port_type' | 'cable_type' | 'device_category' | 'manufacturer' /** * A user's request to change the public catalog — either promoting one of * their own private entries to public, or proposing an edit to an existing * public entry. Regular users can never write a public catalog row directly * (RLS only allows Admins to), so this is the only path either kind of * change can take; an Admin review queue (not yet built — organized-ideas.md * §9's next sub-phase) is what actually applies an approved one. */ export interface CatalogSubmission { id: string entityType: CatalogEntityType /** The row this submission is about — always an existing row in this * app's flow: either your own private entry (being promoted, possibly * with edits) or a public entry (you're suggesting an edit to). */ entityId: string /** Proposed field values, shaped like the underlying table's row (see * data/catalogRowMapping.ts) — so applying an approval is just writing * this object onto the row at `entityId`, not a separate translation * step future Admin-approval logic would otherwise have to redo. */ proposedData: Record submitterId: string status: 'pending' | 'approved' | 'rejected' reviewerId?: string /** Set by an Admin on rejection — organized-ideas.md §3's "notified either * way, with a reason attached on rejection rather than a silent disappearance." */ reviewReason?: string createdAt: string updatedAt: string } /** Storage abstraction for the catalog submission/review queue — mirrors * DiagramRepository/CatalogRepository's role for this concern. Only covers * the submitter's-eye view (create, revise, withdraw your own) for now; an * Admin's view (list all pending, approve/reject) is the next sub-phase. */ export interface SubmissionRepository { /** Every submission the current user has made, most recent first. */ listMine(): Promise /** Submits `entityId` (a row you own privately, or a public row you're * proposing an edit to) for Admin review. */ submit(entityType: CatalogEntityType, entityId: string, proposedData: Record): Promise /** Revises a still-pending or previously-rejected submission of your own * and puts it (back) into the pending queue. */ resubmit(id: string, proposedData: Record): Promise /** Updates only `proposed_data`, leaving status/reviewer/reason untouched. * Used to keep a submission's snapshot in sync with the live private * entry it's about (see catalogStore) — a plain edit to your library * entry shouldn't silently pull a rejected submission back into the * pending queue, so status changes stay a separate, explicit action * (`resubmit`), while the data itself is kept fresh automatically. */ updateProposedData(id: string, proposedData: Record): Promise /** Withdraws your own still-pending submission. */ withdraw(id: string): Promise }