Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / db/migrations/0073_opportunity_document_chunks.sql |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | db/migrations/0073_opportunity_document_chunks.sql |
| Original SHA-256 | ae5c192a33369297894aad17691ddafd7aebd3c99b702ebfb47c79c0e540da46 |
| Git blob SHA | 48e5af0bc56af6e43377d272fa7a0cc80abc9d9a |
| Reading-copy SHA-256 | ae5c192a33369297894aad17691ddafd7aebd3c99b702ebfb47c79c0e540da46 |
Recovered source transcript
Download complete source text ↓49 lines · 2.6 KB
-- +goose Up
-- opportunity_document_chunks is the exact extraction provenance of a document: one row per extracted span
-- with its page, section label, the extracted text, a content hash, the extraction method, and a
-- confidence. Every scope item the model or a human later derives cites a chunk, so a requirement traces
-- back to the precise place in the solicitation it came from. Tenant data (the text is the tenant's
-- uploaded document content), so organization_id, forced RLS, and a composite index leading with
-- organization_id. Chunks are write once extraction output tied to a document.
CREATE TABLE opportunity_document_chunks (
organization_id uuid NOT NULL REFERENCES organizations(id),
id uuid NOT NULL DEFAULT gen_random_uuid(),
document_id uuid NOT NULL,
page_number integer, -- 1 based page, nullable for a non paginated source
section_label text NOT NULL DEFAULT '',
text_content text NOT NULL DEFAULT '',
content_hash text NOT NULL DEFAULT '',
extraction_method text NOT NULL DEFAULT '', -- for example pdf_text, ocr, table, heading
confidence real NOT NULL DEFAULT 0, -- extraction confidence, never a scoring input
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (id),
FOREIGN KEY (organization_id, document_id) REFERENCES opportunity_documents (organization_id, id) ON DELETE CASCADE
);
-- Chunks are read per document in page then section order; the composite index leads with organization_id.
CREATE INDEX idx_opp_chunks_org_doc ON opportunity_document_chunks (organization_id, document_id, page_number);
ALTER TABLE opportunity_document_chunks ENABLE ROW LEVEL SECURITY;
ALTER TABLE opportunity_document_chunks FORCE ROW LEVEL SECURITY;
CREATE POLICY opp_chunks_isolation ON opportunity_document_chunks
USING (organization_id = NULLIF(current_setting('app.current_org_id', true), '')::uuid)
WITH CHECK (organization_id = NULLIF(current_setting('app.current_org_id', true), '')::uuid);
-- The extraction pipeline inserts chunks and the app reads them; chunks are not edited in place, so the
-- grant is SELECT, INSERT with no UPDATE or DELETE.
GRANT SELECT, INSERT ON opportunity_document_chunks TO missionmatch_app;
-- +goose Down
-- +goose StatementBegin
DO $$
DECLARE n bigint;
BEGIN
SELECT count(*) INTO n FROM opportunity_document_chunks;
IF n > 0 THEN
RAISE EXCEPTION 'refusing to drop opportunity_document_chunks: % extraction rows present', n;
END IF;
END $$;
-- +goose StatementEnd
DROP TABLE IF EXISTS opportunity_document_chunks;