Conversation
Add ingestion_jobs and ingestion_items tables for tracking the extract-deduplicate-execute lifecycle of bulk text ingestion. Install append_thought_evidence RPC for idempotent evidence accumulation on thoughts. Part of the OB1 alpha milestone. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3abe49a057
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| UPDATE public.thoughts | ||
| SET metadata = jsonb_set( | ||
| coalesce(metadata, '{}'::jsonb), | ||
| '{evidence}', | ||
| v_current_evidence || jsonb_build_object( |
There was a problem hiding this comment.
Serialize evidence updates to avoid lost writes
append_thought_evidence reads metadata->'evidence' into v_current_evidence and later writes back v_current_evidence || ..., so concurrent calls on the same thought can clobber each other: if two workers append different evidence at the same time, the second write can overwrite the first and drop one entry. This breaks the function’s stated idempotent accumulation behavior for multi-item ingestion and should be fixed by locking the row (FOR UPDATE) or performing the append against the current row value inside a single UPDATE expression.
Useful? React with 👍 / 👎.
schemas/smart-ingest/schema.sql
Outdated
| GRANT EXECUTE ON FUNCTION public.append_thought_evidence(bigint, jsonb) | ||
| TO authenticated, anon, service_role; |
There was a problem hiding this comment.
Restrict SECURITY DEFINER RPC from anon/auth roles
This migration grants EXECUTE on a SECURITY DEFINER function to authenticated and anon, which allows callers to mutate public.thoughts through the function even when row-level access is intended to be service-role-only (as configured in docs/01-getting-started.md with a service-role policy on thoughts). In Supabase deployments where anon keys are client-visible, this exposes an authorization bypass for arbitrary thought_id updates and should be limited to service_role (or enforce caller ownership checks inside the function).
Useful? React with 👍 / 👎.
Add blank lines around headings (MD022), fenced code blocks (MD031), and between adjacent blockquotes (MD028). Fix broken link fragment (MD051) and remove extra blank line (MD012). No content changes. These errors were blocking CI on all open PRs since the lint check runs repo-wide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SECURITY DEFINER function was granted to authenticated/anon, allowing RLS bypass. Now restricted to service_role only. Added FOR UPDATE to prevent concurrent evidence appends from losing writes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
ingestion_jobsandingestion_itemstables for tracking the extract-deduplicate-execute lifecycle of bulk text ingestionappend_thought_evidenceRPC for idempotent evidence accumulation on thoughtsWhat's included
ingestion_jobsingestion_itemsingestion_items_job_idxappend_thought_evidence()Design decisions
CREATE TABLE IF NOT EXISTSandCREATE OR REPLACE FUNCTIONpatterns — safe to run multiple timespending → extracting → dry_run_complete → executing → complete, supporting human-in-the-loop review before mutationinput_hashunique constraint on jobs prevents duplicate processing of the same textappend_thought_evidenceuses SHA256 of(source_label + excerpt + thought_id)to prevent duplicate evidence entriesON DELETE CASCADEDependencies
thoughtstable columnsTest plan
schema.sqlinto Supabase SQL Editor and run — no errorsingestion_jobsandingestion_itemstables appear in Table Editorappend_thought_evidencefunction appears in Database > FunctionsSELECT count(*) FROM ingestion_jobs;— returns 0🤖 Generated with Claude Code