ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / db/migrations/0089_candidate_documents_and_messaging.sql

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / db/migrations/0089_candidate_documents_and_messaging.sql
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberdb/migrations/0089_candidate_documents_and_messaging.sql
Original SHA-25643d9a79a1a933071227dabce090ea979a97315d93e73149b58d21e994a1f3b14
Git blob SHA48902bffa4344ca11a6b8540aaffc6dc12e280b4
Reading-copy SHA-25643d9a79a1a933071227dabce090ea979a97315d93e73149b58d21e994a1f3b14

Original source ↗

Recovered source transcript

-- +goose Up -- THE TWO PREREQUISITES A RECRUITING PRODUCT CANNOT SHIP WITHOUT, closed before any screen is drawn. -- -- A route inventory against the established products in this market found the codebase strong on the -- recruiting spine, clients through requisitions through applications through offers through placements, -- with activity logging, tasks, dispositions, alerts and an audit trail. Two holes made it unusable in -- practice, and both change what a screen has to show, which is why they land before the frontend rather -- than after it. -- -- 1. A RESUME COULD NOT BE ATTACHED TO A CANDIDATE. opportunity_documents existed and nothing equivalent -- did for the record type the whole product is about. -- 2. NOTHING COULD BE SENT TO A CANDIDATE. The only two send calls in the codebase were the account invite -- and the settings test message. A recruiter's day is correspondence, and there was no way to write any. -- -- SENDING REUSES THE ORGANIZATION'S OWN MAIL SERVER from migration 0087, so a candidate hears from -- talent@theiragency.com and not from a domain they were trained to distrust, and it passes their own SPF -- and DKIM because it genuinely is them. -- ============================================================================ -- 1. candidate_documents -- ============================================================================ -- Deliberately the same shape as opportunity_documents: bytes in object storage under storage_key, this row -- is metadata and lifecycle, sha256 gives duplicate detection, and a superseded document keeps is_current -- false rather than being deleted so the history of what was sent to a client survives. -- -- IT IS NOT MERELY "THE RESUME". A cleared candidate's file is a package: the resume the agency formatted, -- the original the candidate sent, a right to represent, a certification, a reference. document_type is the -- closed vocabulary for that, and it exists because "attachment" as the only answer is how a compliance -- request six months later becomes an afternoon of opening files to see what they are. CREATE TABLE candidate_documents ( organization_id uuid NOT NULL REFERENCES organizations(id), id uuid NOT NULL DEFAULT gen_random_uuid(), candidate_id uuid NOT NULL, -- clearance_evidence IS A LABEL, NEVER A VERIFICATION. Storing a document a candidate supplied does not -- make a clearance verified: the real check remains the hiring client's FSO through DISS at onboarding, -- and the product says so wherever clearance appears. The value exists so the file can be FOUND, never -- so it can be treated as proof. document_type text NOT NULL DEFAULT 'resume' CHECK (document_type IN ('resume','resume_original','resume_formatted', 'cover_letter','certification','clearance_evidence','right_to_represent', 'reference','work_sample','onboarding','other')), file_name text NOT NULL DEFAULT '', media_type text NOT NULL DEFAULT '', storage_key text NOT NULL DEFAULT '', size_bytes bigint NOT NULL DEFAULT 0, sha256 text NOT NULL DEFAULT '', uploaded_by_user_id uuid, extraction_status text NOT NULL DEFAULT 'pending' CHECK (extraction_status IN ('pending','running','done','failed','skipped')), extraction_error_code text NOT NULL DEFAULT '', supersedes_document_id uuid, is_current boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (id), CONSTRAINT uq_cand_docs_org_id UNIQUE (organization_id, id), FOREIGN KEY (organization_id, candidate_id) REFERENCES candidates (organization_id, id) ON DELETE CASCADE, FOREIGN KEY (organization_id, uploaded_by_user_id) REFERENCES users (organization_id, id) ON DELETE SET NULL (uploaded_by_user_id), FOREIGN KEY (organization_id, supersedes_document_id) REFERENCES candidate_documents (organization_id, id) ON DELETE SET NULL (supersedes_document_id) ); CREATE INDEX idx_cand_docs_org_cand ON candidate_documents (organization_id, candidate_id, is_current); -- The same bytes are not accepted twice as a current document for one candidate. Recruiters re upload the -- same resume constantly, and without this a candidate's file becomes eleven copies of one document. CREATE UNIQUE INDEX uq_cand_docs_sha ON candidate_documents (organization_id, candidate_id, sha256) WHERE is_current AND sha256 <> ''; ALTER TABLE candidate_documents ENABLE ROW LEVEL SECURITY; ALTER TABLE candidate_documents FORCE ROW LEVEL SECURITY; CREATE POLICY candidate_documents_isolation ON candidate_documents 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); GRANT SELECT, INSERT, UPDATE ON candidate_documents TO missionmatch_app; -- ============================================================================ -- 2. message_templates -- ============================================================================ -- The reason a recruiter sends forty messages a day and each one still reads like a person wrote it. -- Placeholders are resolved SERVER SIDE from the record, so a template cannot address somebody by the wrong -- name, which is the single most expensive mistake in outreach. CREATE TABLE message_templates ( organization_id uuid NOT NULL REFERENCES organizations(id), id uuid NOT NULL DEFAULT gen_random_uuid(), name text NOT NULL, -- Which kind of record this template is written for, so the interface offers the right ones and the -- placeholder set can be validated against what that record actually has. audience text NOT NULL DEFAULT 'candidate' CHECK (audience IN ('candidate','contact')), subject text NOT NULL DEFAULT '', body text NOT NULL DEFAULT '', status text NOT NULL DEFAULT 'active' CHECK (status IN ('active','archived')), created_by uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (organization_id, id), CONSTRAINT fk_msg_templates_creator FOREIGN KEY (organization_id, created_by) REFERENCES users (organization_id, id) ON DELETE SET NULL, CONSTRAINT ck_msg_template_name CHECK (length(btrim(name)) BETWEEN 1 AND 120), CONSTRAINT ck_msg_template_size CHECK (length(subject) <= 300 AND length(body) <= 20000) ); CREATE UNIQUE INDEX uq_msg_templates_name ON message_templates (organization_id, lower(btrim(name))) WHERE status = 'active'; ALTER TABLE message_templates ENABLE ROW LEVEL SECURITY; ALTER TABLE message_templates FORCE ROW LEVEL SECURITY; CREATE POLICY message_templates_isolation ON message_templates 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); GRANT SELECT, INSERT, UPDATE ON message_templates TO missionmatch_app; -- ============================================================================ -- 3. messages, the record of what was actually sent -- ============================================================================ -- APPEND ONLY IN PRACTICE: no DELETE grant. What an agency told a candidate is a fact about the engagement, -- and under an Automated Employment Decision Tool it is part of the record of how a person was treated. A -- message that can be deleted is a message that cannot be produced in an audit. -- -- THE BODY IS RETAINED. That is a deliberate choice with a cost: it is candidate correspondence, so it is -- sensitive, it sits inside forced row level security, and it is covered by the same retention rule as every -- other decision record. The alternative, storing only that a message was sent, makes the trail useless -- exactly when somebody needs it. CREATE TABLE messages ( organization_id uuid NOT NULL REFERENCES organizations(id), id uuid NOT NULL DEFAULT gen_random_uuid(), -- Who it went to. Exactly one of candidate_id or contact_id is set, enforced below, because a message is -- to a person and a message addressed to two different kinds of person at once is a bug. candidate_id uuid, contact_id uuid, -- Optional context: the requisition or application this correspondence belongs to, so a candidate's -- history can be read per role rather than as one undifferentiated stream. requisition_id uuid, application_id uuid, channel text NOT NULL DEFAULT 'email' CHECK (channel IN ('email')), direction text NOT NULL DEFAULT 'outbound' CHECK (direction IN ('outbound')), to_address text NOT NULL, from_address text NOT NULL DEFAULT '', subject text NOT NULL DEFAULT '', body text NOT NULL DEFAULT '', template_id uuid, sent_by_user_id uuid, status text NOT NULL DEFAULT 'queued' CHECK (status IN ('queued','sent','failed')), -- The transport's own message when a send fails, scrubbed of credentials before it is written, so a -- recruiter can see that a mailbox bounced without reading a server log. error_text text NOT NULL DEFAULT '', created_at timestamptz NOT NULL DEFAULT now(), sent_at timestamptz, PRIMARY KEY (organization_id, id), CONSTRAINT fk_messages_candidate FOREIGN KEY (organization_id, candidate_id) REFERENCES candidates (organization_id, id) ON DELETE CASCADE, CONSTRAINT fk_messages_contact FOREIGN KEY (organization_id, contact_id) REFERENCES client_contacts (organization_id, id) ON DELETE CASCADE, CONSTRAINT fk_messages_template FOREIGN KEY (organization_id, template_id) REFERENCES message_templates (organization_id, id) ON DELETE SET NULL, CONSTRAINT fk_messages_sender FOREIGN KEY (organization_id, sent_by_user_id) REFERENCES users (organization_id, id) ON DELETE SET NULL, CONSTRAINT ck_messages_one_recipient CHECK ( (candidate_id IS NOT NULL AND contact_id IS NULL) OR (candidate_id IS NULL AND contact_id IS NOT NULL)), CONSTRAINT ck_messages_sent_has_time CHECK (status <> 'sent' OR sent_at IS NOT NULL) ); CREATE INDEX idx_messages_candidate ON messages (organization_id, candidate_id, created_at DESC) WHERE candidate_id IS NOT NULL; CREATE INDEX idx_messages_contact ON messages (organization_id, contact_id, created_at DESC) WHERE contact_id IS NOT NULL; CREATE INDEX idx_messages_sender ON messages (organization_id, sent_by_user_id, created_at DESC); ALTER TABLE messages ENABLE ROW LEVEL SECURITY; ALTER TABLE messages FORCE ROW LEVEL SECURITY; CREATE POLICY messages_isolation ON messages 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); GRANT SELECT, INSERT, UPDATE ON messages TO missionmatch_app; SELECT mm_mirror_staging_role_privileges(); -- +goose Down DROP TABLE IF EXISTS messages; DROP TABLE IF EXISTS message_templates; DROP TABLE IF EXISTS candidate_documents;

Search equations, builds, manuscript text, and recovered sources.