Add resource_edits review pipeline: holding table, queues, approve/reject/rollback - #24
Conversation
Registers the read-capable Slack MCP server (browser-session token auth) so sessions can query the Code for Philly / phlask workspace. Tokens are supplied via SLACK_MCP_XOXC_TOKEN / SLACK_MCP_XOXD_TOKEN environment secrets and referenced (not embedded) here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1
… RPCs Introduces the Supabase migration behind the crowdsourced resource-editing review flow (#3): - resource_edits holding table (PENDING edits, NEW/UPDATE, base_version) - resource_history: one row per version + change log (folds in #1) - accept_edit / reject_edit / rollback_resource transactional RPCs (#2) - dashboard views: two review queues, per-resource counts, change log - RLS: anon may only INSERT pending edits; reviewers run the RPCs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1
Local dry-run against a stub Postgres surfaced that _apply_resource_snapshot overwrote every resources column from the suggested payload, nulling any field the edit omitted (e.g. date_created -> not-null violation). Now overlays the suggested changes onto the current row so omitted fields are preserved, and never lets an edit change id / date_created / creator. Verified end-to-end: CREATE -> UPDATE -> REJECT -> ROLLBACK, with history versions [1,2,3] = [CREATE,UPDATE,ROLLBACK] and both queues draining to 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1
Local dry-run ✅Ran the migration against a throwaway Postgres 16 with a stubbed
Bug caught & fixed by the dry-run (
Generated by Claude Code |
| -- resource_edits: holding table for pending crowdsourced submissions. | ||
| -- --------------------------------------------------------------------------- | ||
| create table public.resource_edits ( | ||
| id uuid primary key default gen_random_uuid(), |
There was a problem hiding this comment.
Something to note is that our other tables are not using uuids as primary keys. Should we enforce our existing patterns here for consistency?
| -- and RLS policies below. | ||
| -- --------------------------------------------------------------------------- | ||
|
|
||
| -- Apply a pending edit; snapshot the resulting version into history. |
There was a problem hiding this comment.
Can you explain the use case for these SQL functions? I wonder if these should belong in our code rather than in SQL
There was a problem hiding this comment.
If we're not planning on using these, perhaps will be good to remove to simplify these migration files
Inspecting the live Supabase schema showed the earlier design was wrong: the team already has a `resource_revisions` table (full copy of the resources columns + mapped_resource/mapped_resources + a review `status` of PENDING/APPROVED/REJECTED), and `resources.id` is a bigint, not a uuid. The old resource_edits/resource_history/uuid design would have created a parallel, conflicting system. Reworked to be additive and non-destructive — no new tables, no alters, no RLS changes: - Views: revision_edits_queue, revision_new_queue, revision_edit_counts, resource_change_log (all over resource_revisions). - SECURITY DEFINER RPCs: approve_revision / reject_revision (review-state only). Deliberately defers copying an approved revision into `resources` (and any version bump / rollback): `status` is overloaded (operational vs review) and `version` is a schema version, so the write-path needs the data circle to confirm before automating a production write. Proposed path is in comments. Dry-run against a stub matching the real integer-keyed schema: migration applies clean; queues/counts correct; approve->APPROVED, reject->REJECTED, non-PENDING guarded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1
Reworked to match the live schemaHeads-up for the data circle 👀 — I inspected the live Supabase schema and reworked this PR, because the original design didn't match production:
So instead of a parallel Two things I need confirmation on before finishing the write-path (applying an approved revision into
Once those are settled I'll wire up Generated by Claude Code |
…-approve Per design decision: resource_revisions was a throwaway table, so build a new dedicated holding table instead and leave resource_revisions alone. - New resource_edits table: typed mirror of the ResourceEntry fields + a mapped_resource link (null = new site) + a DEDICATED review_status (PENDING/APPROVED/REJECTED), fixing the operational-vs-review status overload. - Integer (bigint) keys to match resources.id. - Views: resource_edits_queue, new_resources_queue, resource_edit_counts, resource_change_log. - RPCs: approve_edit (applies the edit into resources — update mapped or insert new site), reject_edit, rollback_to_edit. The copy uses jsonb_populate_record so it adapts to the real resources column types. - RLS: anon may only INSERT a PENDING edit; reviewers read + run the RPCs. Dry-run against a stub (resources.images text[] vs edit.images jsonb) passes: queues correct, approve applies + auto-maps new sites, images converts across types, reject + rollback work. DRAFT: still needs a staging run to confirm real resources column types and that resources.id has a default/identity for the new-site insert path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1
|
Update / correction to my earlier comment: Generated by Claude Code |
Drops the views, functions, and resource_edits table (with its policies and indexes); leaves resources and resource_revisions untouched. Kept in supabase/rollback/ so the Supabase CLI won't apply it as a forward migration. Verified: up -> down leaves the schema as it started. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1
Problem
Crowdsourced edits and new-site submissions need a place to be held, reviewed in queues, approved/rejected, applied to the live
resourcestable with the ability to roll back — none of which exists in a usable form yet.Solution
A new dedicated
resource_editsholding table plus the review pipeline around it. Migration:supabase/migrations/20260714231214_resource_editing.sql.resource_edits— a typed mirror of theResourceEntryfields (easy side-by-side compare) +mapped_resourcelink (null = new site) + a dedicatedreview_status(PENDING/APPROVED/REJECTED). Keeping review status separate from the mirrored operationalstatusavoids the overloading in the earlier scratch table.resources.id.resource_edits_queue,new_resources_queue,resource_edit_counts,resource_change_log.SECURITY DEFINER):approve_edit(applies the edit intoresources— updates the mapped resource, or inserts a new site and auto-maps it),reject_edit,rollback_to_edit. The apply usesjsonb_populate_record, so it adapts to the realresourcescolumn types.INSERTaPENDINGedit; authenticated reviewers read the queues and run the RPCs.Leaves the throwaway
resource_revisionstable untouched.Verification
Dry-run against a local stub of the real integer-keyed schema (with
resources.images text[]vs the edit'simages jsonb, to test type adaptation):approve_editapplies an update and auto-maps a new site;imagesconverts jsonb→text[];reject_editandrollback_to_editwork.Reference
Implements #3.
Screenshots
N/A — schema-only change.
Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01DQCnNexihkvzxUYee3NUa1