Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/codebase-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ due time, the note's id and that phone's endpoint in `alert_reminder_times`, nev

Administrator source intake also records admission events in `document_admission_events`.

`documents`, `document_pages`, `document_images`, `document_chunks`, `document_embedding_fields`, `document_index_units`, `document_table_facts`, `document_labels`, `document_summaries`, `document_sections`, `document_memory_cards`, `document_index_quality`, `document_title_words`, `document_publication_approvals`, `document_corpus_access_state`, `document_corpus_access_snapshots`, `ingestion_jobs`, `ingestion_job_stages`, `indexing_v3_agent_jobs`, `import_batches`, `image_caption_cache`, `rag_queries`, `rag_query_misses`, `rag_aliases`, `rag_response_cache`, `rag_retrieval_logs`, `rag_visual_eval_cases`, `rag_visual_eval_runs`, `rag_answer_feedback`, `clinical_registry_records`, `clinical_registry_record_sources`, `clinical_quality_feedback_triage`, `clinical_quality_feedback_triage_events`, `medication_records`, `differential_records`, `source_review_events`, `user_favourites`, `user_favourite_sets`, `user_preferences`, `work_admin_paperwork`, `work_backups`, `work_booking_courses`, `work_course_bookings`, `work_hospitals`, `work_hospital_teams`, `work_role_grants`, `alert_reminder_times`, `alert_brief_sent`, `api_rate_limits`, `api_rate_limit_subjects`, `audit_logs`, `storage_cleanup_jobs`, `on_call_entries`, `cme_years`, `cme_requirements`, `cme_routines`, `cme_entries`, `cme_allocations`, `cme_evidence`, `cme_year_snapshots`, `cme_year_amendments`, `cme_plan_goals`, `cme_plan_goal_carries`, `cme_entry_goals`, `cme_training_periods`, `cme_training_milestones`, `cme_missed_sessions`, `cme_entry_drafts`, `calendar_feed_tokens`, `on_call_shift_imports`, `on_call_shifts`, `on_call_services`, `on_call_service_sites`, `on_call_service_members`, `on_call_service_invitations`, `on_call_service_entries`, `on_call_service_reports`, `on_call_service_orientation`, `site_content_publications`, `site_content_reconciliation_plans`, `site_content_public_records`, `site_content_sync_state`, `site_content_sync_events`, `site_content_sync_event_plans`, `site_content_sync_worker_invocations`, `site_content_releases`, `site_content_release_records`, `site_content_release_receipts`
`documents`, `document_pages`, `document_images`, `document_chunks`, `document_embedding_fields`, `document_index_units`, `document_table_facts`, `document_evidence_revisions`, `document_labels`, `document_summaries`, `document_sections`, `document_memory_cards`, `document_index_quality`, `document_title_words`, `document_publication_approvals`, `document_corpus_access_state`, `document_corpus_access_snapshots`, `ingestion_jobs`, `ingestion_job_stages`, `indexing_v3_agent_jobs`, `import_batches`, `image_caption_cache`, `rag_queries`, `rag_query_misses`, `rag_aliases`, `rag_response_cache`, `rag_retrieval_logs`, `rag_visual_eval_cases`, `rag_visual_eval_runs`, `rag_answer_feedback`, `clinical_registry_records`, `clinical_registry_record_sources`, `clinical_quality_feedback_triage`, `clinical_quality_feedback_triage_events`, `medication_records`, `differential_records`, `source_review_events`, `user_favourites`, `user_favourite_sets`, `user_preferences`, `work_admin_paperwork`, `work_backups`, `work_booking_courses`, `work_course_bookings`, `work_hospitals`, `work_hospital_teams`, `work_role_grants`, `alert_reminder_times`, `alert_brief_sent`, `api_rate_limits`, `api_rate_limit_subjects`, `audit_logs`, `storage_cleanup_jobs`, `on_call_entries`, `cme_years`, `cme_requirements`, `cme_routines`, `cme_entries`, `cme_allocations`, `cme_evidence`, `cme_year_snapshots`, `cme_year_amendments`, `cme_plan_goals`, `cme_plan_goal_carries`, `cme_entry_goals`, `cme_training_periods`, `cme_training_milestones`, `cme_missed_sessions`, `cme_entry_drafts`, `calendar_feed_tokens`, `on_call_shift_imports`, `on_call_shifts`, `on_call_services`, `on_call_service_sites`, `on_call_service_members`, `on_call_service_invitations`, `on_call_service_entries`, `on_call_service_reports`, `on_call_service_orientation`, `site_content_publications`, `site_content_reconciliation_plans`, `site_content_public_records`, `site_content_sync_state`, `site_content_sync_events`, `site_content_sync_event_plans`, `site_content_sync_worker_invocations`, `site_content_releases`, `site_content_release_records`, `site_content_release_receipts`

Team modes (Roster, Admin, Teaching): `admin_leave_balances`, `admin_settings`, `extra_time_records`, `on_call_service_member_events`, `registrar_assessments`, `registrar_training_milestones`, `roster_assignments`, `roster_calendar_links`, `roster_change_agreements`, `roster_changes`, `roster_draft_assignments`, `roster_drafts`, `roster_leave`, `roster_member_roles`, `roster_open_post_alerts`, `roster_open_post_keys`, `roster_open_shifts`, `roster_publication_protections`, `roster_publication_seen`, `roster_publications`, `roster_rotation_preferences`, `roster_rotation_rounds`, `roster_shift_codes`, `roster_staffing_needs`, `roster_swaps`, `roster_team_settings`, `roster_unavailability`, `teaching_attendance`, `teaching_audit_events`, `teaching_calendar_optins`, `teaching_checkin_claims`, `teaching_collection_sections`, `teaching_collections`, `teaching_display_links`, `teaching_feedback_answers`, `teaching_feedback_replied`, `teaching_group_members`, `teaching_groups`, `teaching_member_roles`, `teaching_notice_reads`, `teaching_notices`, `teaching_occurrences`, `teaching_readiness`, `teaching_resource_saves`, `teaching_resources`, `teaching_series`, `teaching_supervision_entries`, `teaching_supervision_notes`, `teaching_supervision_pairings`, `teaching_team_settings`, `teaching_week_adds`, `web_push_subscriptions`.

Expand Down
5 changes: 3 additions & 2 deletions supabase/applied-migration-hashes.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"note": "sha256 of every migration this repository has shipped, with newlines normalised. An entry whose hash changes means an applied migration was edited, which cannot reach the live database. See scripts/check-migration-immutability.mjs.",
"generator": "scripts/check-migration-immutability.mjs",
"sealed_at": "2026-10-18T08:41:00.862Z",
"sealed_at": "2026-10-18T09:59:47.045Z",
"versions": {
"20260527000000_bulk_ingestion.sql": "813e8e314064a6dcbaaa55e2765a8ce901d5783b304b4a7af7bb7417a07daf7c",
"20260527001000_documents_policy_cleanup.sql": "559c26f3172bf75e545a41adef75538b2bf648ea7d53c8eb3d3ea7c244c65a48",
Expand Down Expand Up @@ -324,6 +324,7 @@
"20261017175448_scope_ingestion_claim_atomically.sql": "af192755dd24aa8a6e6146013e1b7abd1b2954a53410c301dedfcb7576c88eba",
"20261018053558_recheck_ingestion_claim_scope_after_job_lock.sql": "a427b8aacce70579ad26bd701adb65912a345ab78d54e5b34386bbd05d261b6c",
"20261018062736_recheck_legacy_ingestion_claim_document_after_job_lock.sql": "39f08a91ed4c15a8aff0dff80341242604101886de873c5cadafa65e9b92e3c8",
"20261018082910_audit_durable_recovery_pairing_and_cache_fences.sql": "f0667fed9f0294c1f5ba40252d11ee66e6de07be340a1ec789e0503a1192f2ac"
"20261018082910_audit_durable_recovery_pairing_and_cache_fences.sql": "f0667fed9f0294c1f5ba40252d11ee66e6de07be340a1ec789e0503a1192f2ac",
"20261018095804_rag_cache_scope_evidence_revision.sql": "0a3c6845cda4d8feb22c54dbf176c7ece61da0333c4a75edb0664b3046a37994"
}
}
94 changes: 91 additions & 3 deletions supabase/drift-manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"generated_at": "2026-10-18T06:37:18.983Z",
"generated_at": "2026-10-18T10:29:05.818Z",
"generator": "scripts/generate-drift-manifest.ts",
"postgres_image": "supabase/postgres:17.6.1.127@sha256:be60aee15997daca475b710b734bc6bfe52cd544dcd7e9fd2ff58210b6747d83",
"schema_sha256": "ddba5299f794d7be628fe0e9a85a4f7c4c4218bd29854c9e209a25a3c24909e5",
"schema_sha256": "deeee8f86fe40c6e07c7ff56e5c97a85cab409112af961eda4403b9f4384dadf",
Comment thread
BigSimmo marked this conversation as resolved.
Resolved
"replay_seconds": 14,
"snapshot": {
"views": [
Expand Down Expand Up @@ -2979,6 +2979,34 @@
"rls_forced": false,
"rls_enabled": true
},
{
"acl": [
"postgres=arwdDxtm/postgres",
"service_role=arwdDxtm/postgres"
],
"name": "document_evidence_revisions",
"columns": [
{
"name": "document_id",
"type": "uuid",
"default": null,
"identity": "",
"not_null": true,
"generated": ""
},
{
"name": "revision",
"type": "bigint",
"default": "0",
"identity": "",
"not_null": true,
"generated": ""
}
],
"reloptions": null,
"rls_forced": false,
"rls_enabled": true
},
{
"acl": [
"postgres=arwdDxtm/postgres",
Expand Down Expand Up @@ -14709,6 +14737,12 @@
"table": "document_embedding_fields",
"def_hash": "7224a35b50c37a7394210ca930e4e99f"
},
{
"def": "CREATE UNIQUE INDEX document_evidence_revisions_pkey ON public.document_evidence_revisions USING btree (document_id)",
"name": "document_evidence_revisions_pkey",
"table": "document_evidence_revisions",
"def_hash": "2615588a76c4e5926413aec57fd7d419"
},
{
"def": "CREATE INDEX document_images_created_at_idx ON public.document_images USING btree (created_at)",
"name": "document_images_created_at_idx",
Expand Down Expand Up @@ -18188,6 +18222,21 @@
"name": "set_document_embedding_field_content_hash",
"table": "document_embedding_fields"
},
{
"def": "CREATE TRIGGER document_images_evidence_delete AFTER DELETE ON public.document_images REFERENCING OLD TABLE AS old_rows FOR EACH STATEMENT EXECUTE FUNCTION public.document_evidence_rows_changed()",
"name": "document_images_evidence_delete",
"table": "document_images"
},
{
"def": "CREATE TRIGGER document_images_evidence_insert AFTER INSERT ON public.document_images REFERENCING NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION public.document_evidence_rows_changed()",
"name": "document_images_evidence_insert",
"table": "document_images"
},
{
"def": "CREATE TRIGGER document_images_evidence_update AFTER UPDATE ON public.document_images REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION public.document_evidence_rows_changed()",
"name": "document_images_evidence_update",
"table": "document_images"
},
{
"def": "CREATE TRIGGER document_index_units_updated_at BEFORE UPDATE ON public.document_index_units FOR EACH ROW EXECUTE FUNCTION public.set_updated_at()",
"name": "document_index_units_updated_at",
Expand All @@ -18213,6 +18262,21 @@
"name": "document_sections_updated_at",
"table": "document_sections"
},
{
"def": "CREATE TRIGGER document_table_facts_evidence_delete AFTER DELETE ON public.document_table_facts REFERENCING OLD TABLE AS old_rows FOR EACH STATEMENT EXECUTE FUNCTION public.document_evidence_rows_changed()",
"name": "document_table_facts_evidence_delete",
"table": "document_table_facts"
},
{
"def": "CREATE TRIGGER document_table_facts_evidence_insert AFTER INSERT ON public.document_table_facts REFERENCING NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION public.document_evidence_rows_changed()",
"name": "document_table_facts_evidence_insert",
"table": "document_table_facts"
},
{
"def": "CREATE TRIGGER document_table_facts_evidence_update AFTER UPDATE ON public.document_table_facts REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION public.document_evidence_rows_changed()",
"name": "document_table_facts_evidence_update",
"table": "document_table_facts"
},
{
"def": "CREATE TRIGGER document_title_words_enforce_public_scope BEFORE INSERT OR UPDATE ON public.document_title_words FOR EACH ROW EXECUTE FUNCTION public.enforce_document_title_word_scope()",
"name": "document_title_words_enforce_public_scope",
Expand Down Expand Up @@ -18620,6 +18684,13 @@
"def_hash": "f02e0c8d223bb2621468b958df75f1f1",
"signature": "public.bind_public_source_upload_authority(jsonb)"
},
{
"acl": [
"postgres=X/postgres"
],
"def_hash": "e91b4cce6223c04f8e34780d31eb6aa9",
"signature": "public.bump_document_evidence_revisions(uuid[])"
},
{
"acl": [
"postgres=X/postgres",
Expand Down Expand Up @@ -19086,6 +19157,13 @@
"def_hash": "37f32cc93a66d9ce45bdcecf263ace70",
"signature": "public.detect_legacy_ivfflat_indexes()"
},
{
"acl": [
"postgres=X/postgres"
],
"def_hash": "58f5ef7258095fc953849fdb45a832d1",
"signature": "public.document_evidence_rows_changed()"
},
{
"acl": [
"postgres=X/postgres",
Expand Down Expand Up @@ -19724,7 +19802,7 @@
"postgres=X/postgres",
"service_role=X/postgres"
],
"def_hash": "6495e84c303f7bfb857743ff77c613ee",
"def_hash": "6e2e9461e611d13573b2e1aea26f0d5e",
"signature": "public.rag_cache_scope_revision_v1(uuid,boolean,uuid[])"
},
{
Expand Down Expand Up @@ -22154,6 +22232,16 @@
"name": "document_embedding_fields_source_chunk_id_fkey",
"table": "document_embedding_fields"
},
{
"def": "FOREIGN KEY (document_id) REFERENCES public.documents(id) ON DELETE CASCADE",
"name": "document_evidence_revisions_document_id_fkey",
"table": "document_evidence_revisions"
},
{
"def": "PRIMARY KEY (document_id)",
"name": "document_evidence_revisions_pkey",
"table": "document_evidence_revisions"
},
{
"def": "FOREIGN KEY (document_id) REFERENCES public.documents(id) ON DELETE CASCADE",
"name": "document_images_document_id_fkey",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
-- DRAFT. Merge only inside the owner's approved database-change window, and only after
-- 20261018082910_audit_durable_recovery_pairing_and_cache_fences.sql (it replaces that
-- migration's rag_cache_scope_revision_v1). Owner approval: 17:55 AWST 2026-10-18, relayed by Grok Bot.
Comment on lines +1 to +3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Owner approval is recorded only as a bot relay, not the owner's own words

The migration header and the PR body record the owner's approval as "17:55 AWST 2026-10-18, relayed by Grok Bot". The repo's Supabase safety rules (docs/decisions/2026-10-15-database-changes-need-owner-permission.md) require the owner's explicit yes, in words, to this specific change before it reaches main. Approval relayed secondhand by an agent can't be checked against that rule. Before merging, get the owner to confirm directly on this PR (a comment or review) and point to it.

Was this helpful? React with 👍 / 👎

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged; not resolving. Grok Bot relayed the owner's approval of this migration at 17:55 AWST 2026-10-18. Automation can't record the owner's own words. The owner needs to confirm this specific change in their own words, and pick the production window, before this merges. Auto-merge is deliberately off.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. This finding stays open until the owner confirms this specific migration in their own words and a production window is chosen. Keeping auto-merge off is the right call until then. I'm not making any code changes for this.

set local lock_timeout = '5s';
set local statement_timeout = '30s';

-- Cached answers and searches were keyed by a revision that hashed only document rows, so an
-- edit to a table fact or image (threshold, action, caption, relevance, searchability, ...)
-- left the revision unchanged and stale evidence could be served from cache. Each document now
-- carries an evidence counter, bumped in the writing transaction by statement-level triggers
-- whenever a retrieval-relevant fact or image row is inserted, deleted or changed. The scope
-- revision stays a single pass over documents plus one keyed join: no per-request scan of
-- facts or images.
create table public.document_evidence_revisions (
document_id uuid primary key references public.documents(id) on delete cascade,
revision bigint not null default 0
);
alter table public.document_evidence_revisions owner to postgres;
alter table public.document_evidence_revisions enable row level security;
revoke all on table public.document_evidence_revisions from public, anon, authenticated;
grant all on table public.document_evidence_revisions to service_role;

-- Bumps once per touched document per statement. Documents removed in the same statement
-- (cascade from public.documents) are skipped; their rows leave the scope revision anyway.
create function public.bump_document_evidence_revisions(p_document_ids uuid[]) returns void
language sql security definer set search_path = '' as $$
insert into public.document_evidence_revisions as r(document_id, revision)
select d.id, 1
from public.documents d
where d.id = any(p_document_ids)
order by d.id
on conflict (document_id) do update set revision = r.revision + 1
$$;
alter function public.bump_document_evidence_revisions(uuid[]) owner to postgres;
revoke all on function public.bump_document_evidence_revisions(uuid[]) from public, anon, authenticated;

-- Retrieval-relevant means every stored column except created_at (and generated search_tsv,
-- which follows its sources). A no-op UPDATE does not bump the counter.
create function public.document_evidence_rows_changed() returns trigger
language plpgsql security definer set search_path = '' as $$
begin
if tg_op = 'INSERT' then
perform public.bump_document_evidence_revisions(array(select distinct n.document_id from new_rows n));
elsif tg_op = 'DELETE' then
perform public.bump_document_evidence_revisions(array(select distinct o.document_id from old_rows o));
else
perform public.bump_document_evidence_revisions(array(
select distinct x.document_id from (
select o.document_id as old_document_id, n.document_id as new_document_id
from old_rows o join new_rows n on n.id = o.id
where (pg_catalog.to_jsonb(o) - array['created_at','search_tsv'])
is distinct from (pg_catalog.to_jsonb(n) - array['created_at','search_tsv'])
) changed
cross join lateral (values (changed.old_document_id), (changed.new_document_id)) x(document_id)
));
end if;
return null;
end $$;
alter function public.document_evidence_rows_changed() owner to postgres;
revoke all on function public.document_evidence_rows_changed() from public, anon, authenticated;

create trigger document_table_facts_evidence_insert after insert on public.document_table_facts
referencing new table as new_rows for each statement execute function public.document_evidence_rows_changed();
create trigger document_table_facts_evidence_update after update on public.document_table_facts
referencing old table as old_rows new table as new_rows for each statement execute function public.document_evidence_rows_changed();
create trigger document_table_facts_evidence_delete after delete on public.document_table_facts
referencing old table as old_rows for each statement execute function public.document_evidence_rows_changed();
create trigger document_images_evidence_insert after insert on public.document_images
referencing new table as new_rows for each statement execute function public.document_evidence_rows_changed();
create trigger document_images_evidence_update after update on public.document_images
referencing old table as old_rows new table as new_rows for each statement execute function public.document_evidence_rows_changed();
create trigger document_images_evidence_delete after delete on public.document_images
referencing old table as old_rows for each statement execute function public.document_evidence_rows_changed();

-- Same signature, digest shape and grants; each document's row hash now also carries its
-- evidence counter.
create or replace function public.rag_cache_scope_revision_v1(p_owner_id uuid, p_include_public boolean, p_document_ids uuid[] default null)
returns text language sql stable security invoker set search_path = '' as $$
select 'rag-cache-scope-v1:' || pg_catalog.md5(coalesce(pg_catalog.string_agg(row_hash, '' order by id),''))
from (
select d.id, pg_catalog.md5(pg_catalog.jsonb_build_array(d.id,d.owner_id,d.status,d.updated_at,d.metadata,d.index_generation_id,
coalesce(r.revision, 0))::text) as row_hash
from public.documents d
left join public.document_evidence_revisions r on r.document_id = d.id
where (d.owner_id = p_owner_id or (coalesce(p_include_public,false) and d.owner_id is null))
and (coalesce(cardinality(p_document_ids),0) = 0 or d.id = any(p_document_ids))
) revision
$$;
alter function public.rag_cache_scope_revision_v1(uuid,boolean,uuid[]) owner to postgres;
revoke all on function public.rag_cache_scope_revision_v1(uuid,boolean,uuid[]) from public, anon, authenticated;
grant execute on function public.rag_cache_scope_revision_v1(uuid,boolean,uuid[]) to service_role;
Loading
Loading