Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / db/migrations/0104_corpus_documents.sql |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | db/migrations/0104_corpus_documents.sql |
| Original SHA-256 | a19b4dd6901073d229b4b35d6dcc2ceefd1f195af179767e040f8bdbc5817fdc |
| Git blob SHA | e93d34016ed4562f34fee6906f9fd1575f142194 |
| Reading-copy SHA-256 | a19b4dd6901073d229b4b35d6dcc2ceefd1f195af179767e040f8bdbc5817fdc |
Recovered source transcript
Download complete source text ↓146 lines · 8.1 KB
-- +goose Up
-- THE CORPUS DOCUMENT LAYER: missionMATCH's OWN KNOWLEDGE OF FEDERAL OPPORTUNITIES.
--
-- THIS IS PRODUCT KNOWLEDGE, NOT CUSTOMER DATA, and that is the whole reason these tables exist rather than
-- reusing the ones already here. opportunity_documents and opportunity_document_chunks carry RLS and an
-- organization_id because they were built for the tenant path: a customer tracks a pursuit and pulls that
-- package into THEIR space. Harvesting the federal corpus into those tables would file the government's
-- public solicitations inside one tenant's boundary, which is both wrong and unusable, because the next
-- tenant would have to download the same documents again to know the same public facts.
--
-- missionMATCH should already be an expert on every government opportunity before any customer arrives.
-- Each tenant then brings their own data and their own scopes on top of that. So these tables sit beside
-- opportunity_records and ingest_manifest in the SHARED layer, with no organization_id and no RLS, exactly
-- as the notice corpus does.
--
-- WHY DOCUMENTS AT ALL, WHEN THE NOTICE TEXT IS ALREADY EXTRACTED. Because for staffing the notice text is
-- usually a pointer and not an answer. A notice says "provide services in accordance with the attached
-- PWS". The labor category matrix, the clearance required per position, the education and experience
-- minimums, the certifications: all of that is in the attachment. The 2163 notice level extractions already
-- in this database prove the extraction works, and they also show its ceiling, because a notice that
-- delegates to its attachment yields a labor category and little else.
--
-- THE BINARY IS NOT RETAINED. Measured against sam.gov, an average notice carries 2.5 files and 2.3 MB.
-- Across the active federal landscape that is roughly 69 GB of PDF, and keeping it would buy nothing: SAM
-- is a permanent public store with stable URLs, so the durable copy already exists and is not ours to
-- duplicate. What is worth keeping is what was LEARNED. Every row here records the sha256 and the source
-- url, so any original can be refetched byte for byte on demand, and the download itself is transient:
-- fetch, extract, embed, discard, one file at a time.
--
-- downloaded per notice 2.3 MB transient
-- extracted prose ~80 KB three to five percent of a text PDF
-- after lz4 ~25 KB
-- ~20 chunks as halfvec ~15 KB
-- retained per notice ~40 KB a 57x reduction
--
-- That is the entire active federal opportunity landscape, searchable by meaning and citable to a page, in
-- roughly a gigabyte.
-- corpus_documents is one public federal document, described but not stored.
CREATE TABLE corpus_documents (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
-- The notice this document belongs to, in the SHARED corpus. No tenant is involved.
opportunity_record_id uuid NOT NULL REFERENCES opportunity_records(id) ON DELETE CASCADE,
-- SAM's own identifiers, so a re fetch needs nothing but this row.
resource_id text NOT NULL,
file_name text NOT NULL DEFAULT '',
media_type text NOT NULL DEFAULT '',
size_bytes bigint,
-- THE TWO COLUMNS THAT MAKE DISCARDING THE BINARY SAFE. sha256 is of the bytes as fetched, so a refetch
-- can be proved identical to what was learned from; source_url is where to get them. Neither is
-- optional, because a document whose original cannot be recovered is a claim without evidence.
sha256 text NOT NULL,
source_url text NOT NULL,
-- What happened when this document was read. A failure is RECORDED rather than retried forever, so a
-- scanned drawing that will never yield prose stops costing a request on every pass.
extract_status text NOT NULL DEFAULT 'pending'
CHECK (extract_status IN ('pending','ok','no_prose','too_large','fetch_failed','parse_error','skipped')),
extract_error text NOT NULL DEFAULT '',
page_count integer,
-- The bytes actually downloaded to learn this, kept as a number so the cost of the corpus is a fact
-- rather than an estimate. The bytes themselves are gone.
fetched_bytes bigint,
fetched_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
-- Provenance is born at origin, per migration 0081. A SAM attachment is a published federal document.
provenance text NOT NULL DEFAULT 'public_cache',
UNIQUE (opportunity_record_id, resource_id)
);
-- The harvester's working query: which notices still have documents to read.
CREATE INDEX IF NOT EXISTS idx_corpus_documents_status
ON corpus_documents (extract_status, fetched_at NULLS FIRST);
CREATE INDEX IF NOT EXISTS idx_corpus_documents_notice
ON corpus_documents (opportunity_record_id);
-- corpus_chunks is the knowledge itself: prose, where it came from, and what it means.
CREATE TABLE corpus_chunks (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
document_id uuid NOT NULL REFERENCES corpus_documents(id) ON DELETE CASCADE,
-- THE CITATION, which is not optional. A chunk that cannot say which page and section it came from is
-- an assertion, and this product does not make assertions. The tenant side enforces the same rule on
-- scope items through a database constraint; the corpus holds itself to it too.
page_number integer,
section_label text NOT NULL DEFAULT '',
-- lz4 rather than the cluster default pglz: this column is the bulk of the corpus, it is prose, and
-- lz4 both compresses it better and decompresses several times faster, which matters because every
-- retrieval reads it.
text_content text COMPRESSION lz4 NOT NULL,
content_hash text NOT NULL,
-- halfvec, NOT vector. Two bytes per dimension instead of four halves the largest fixed cost in the
-- corpus for a recall difference that does not survive measurement at this dimensionality. 384 matches
-- the embedding model already in service (bge-small-en-v1.5), so the corpus and the tenant bench speak
-- the same vector space and can be compared directly.
embedding halfvec(384),
extraction_method text NOT NULL DEFAULT '',
confidence real,
created_at timestamptz NOT NULL DEFAULT now(),
provenance text NOT NULL DEFAULT 'public_cache'
);
CREATE INDEX IF NOT EXISTS idx_corpus_chunks_document ON corpus_chunks (document_id);
-- HNSW over halfvec with cosine distance, the same measure the rest of the platform retrieves by. Built
-- now while the table is empty, which is far cheaper than building it over a million rows later.
CREATE INDEX IF NOT EXISTS idx_corpus_chunks_embedding
ON corpus_chunks USING hnsw (embedding halfvec_cosine_ops);
-- Full text as well as vector, because a solicitation is full of exact tokens that embeddings blur: a
-- clearance level, a NAICS code, a labor category name, a certification acronym. Retrieval fuses both.
CREATE INDEX IF NOT EXISTS idx_corpus_chunks_fts
ON corpus_chunks USING gin (to_tsvector('english', text_content));
-- NO ROW LEVEL SECURITY ON EITHER TABLE, and that is the point rather than an omission. This is the
-- product's own knowledge of public federal documents. Every tenant reads the same corpus, nobody owns it,
-- and there is nothing here that one customer could learn about another.
--
-- The application role reads it and never writes it. Writes come from the harvester running as the
-- migrator, the same shape opportunity_records already uses, so a compromised application session cannot
-- rewrite what the product claims to know.
GRANT SELECT ON corpus_documents TO missionmatch_app;
GRANT SELECT ON corpus_chunks TO missionmatch_app;
SELECT mm_mirror_staging_role_privileges();
-- +goose Down
DROP INDEX IF EXISTS idx_corpus_chunks_fts;
DROP INDEX IF EXISTS idx_corpus_chunks_embedding;
DROP INDEX IF EXISTS idx_corpus_chunks_document;
DROP TABLE IF EXISTS corpus_chunks;
DROP INDEX IF EXISTS idx_corpus_documents_notice;
DROP INDEX IF EXISTS idx_corpus_documents_status;
DROP TABLE IF EXISTS corpus_documents;