ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / internal/modules/matching/candidate_documents.go

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / internal/modules/matching/candidate_documents.go
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberinternal/modules/matching/candidate_documents.go
Original SHA-256f4c8c4fca812683886e4064ea0ac4d5921d4b170727c7641e3a54da390e90393
Git blob SHA48054b033da1b9d7b455a4ee36b0d85a9854ea39
Reading-copy SHA-256f4c8c4fca812683886e4064ea0ac4d5921d4b170727c7641e3a54da390e90393

Original source ↗

Recovered source transcript

package matching // CANDIDATE DOCUMENTS. The file on a person: the resume the agency formatted, the original the candidate // sent, a right to represent, a certification, a reference. // // It did not exist. opportunity_documents did, and nothing equivalent existed for the record type the entire // product is about, so a recruiter could not attach a resume to a candidate. That is a hole you hit on the // first day of a real client, which is why it lands before the frontend rather than after it. // // THE ORDER IS THE DESIGN, and it is copied deliberately from the opportunities document service rather than // reinvented: validate, then scan, then store the bytes, then record the row. A row that exists before its // bytes is a row a reader will fail on; stored bytes with no row are garbage nobody can find. // // CLEARANCE EVIDENCE IS A LABEL, NEVER A VERIFICATION. A candidate supplied document does not make a // clearance verified. The real check is the hiring client's FSO through DISS at onboarding, and this stores // the file so it can be found, never so it can be treated as proof. import ( "context" "encoding/json" "errors" "fmt" "path/filepath" "strings" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/missionworkforce/missionmatch/internal/platform/audit" "github.com/missionworkforce/missionmatch/internal/platform/storage" "github.com/missionworkforce/missionmatch/internal/platform/tenant" ) var ( ErrNoStorage = errors.New("matching: document storage is not configured on this node") ErrDocEmpty = errors.New("matching: the file is empty") ErrDocTooLarge = errors.New("matching: the file exceeds the maximum size") ErrDocMediaType = errors.New("matching: that file type is not accepted") ErrDocTypeInvalid = errors.New("matching: unknown document type") ErrDocDuplicate = errors.New("matching: that exact file is already on this candidate") ErrCandidateUnknown = errors.New("matching: no such candidate in this organization") ErrDocNotFound = errors.New("matching: no such document") ) // MaxCandidateDocBytes bounds a single upload. A resume is tens of kilobytes; twenty megabytes is generous // for a scanned certification and small enough that a mistaken upload cannot fill a volume. const MaxCandidateDocBytes = 20 << 20 // candidateMediaTypes is a CLOSED allowlist mapping an accepted type to the extension used in the storage // key. An allowlist rather than a denylist, because the interesting question is what a recruiter legitimately // sends, and that list is short. var candidateMediaTypes = map[string]string{ "application/pdf": ".pdf", "application/msword": ".doc", "application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx", "application/rtf": ".rtf", "text/plain": ".txt", "image/png": ".png", "image/jpeg": ".jpg", } var candidateDocTypes = map[string]bool{ "resume": true, "resume_original": true, "resume_formatted": true, "cover_letter": true, "certification": true, "clearance_evidence": true, "right_to_represent": true, "reference": true, "work_sample": true, "onboarding": true, "other": true, } // CandidateDocument is the metadata row. IT NEVER CARRIES THE BYTES, so a list of forty documents is forty // small rows and no caller can accidentally serialise a candidate's whole file into a response. type CandidateDocument struct { ID string `json:"id"` CandidateID string `json:"candidate_id"` DocumentType string `json:"document_type"` FileName string `json:"file_name"` MediaType string `json:"media_type"` SizeBytes int64 `json:"size_bytes"` SHA256 string `json:"sha256"` UploadedBy string `json:"uploaded_by_user_id,omitempty"` UploaderName string `json:"uploaded_by_name,omitempty"` IsCurrent bool `json:"is_current"` CreatedAt time.Time `json:"created_at"` } // CandidateDocInput is one upload. type CandidateDocInput struct { CandidateID string DocumentType string FileName string MediaType string Bytes []byte } // WithDocumentStore injects object storage. Nil means the routes report themselves unavailable rather than // accepting an upload and losing it, which is the same rule the opportunity document surface already follows. func (s *Service) WithDocumentStore(store storage.Storer) *Service { s.docStore = store return s } func (s *Service) UploadCandidateDocument(ctx context.Context, in CandidateDocInput, ip, ua string) (CandidateDocument, error) { var out CandidateDocument if s.db == nil { return out, ErrNoDatabase } if s.docStore == nil { return out, ErrNoStorage } // THE ORG COMES FROM THE VALIDATED CONTEXT, never from a parameter. A caller who could name the tenant // would be the authority on tenancy, which is exactly what row level security exists to prevent. orgStr, ok := tenant.OrgFromContext(ctx) if !ok { return out, tenant.ErrNoTenant } orgID, err := uuid.Parse(orgStr) if err != nil { return out, tenant.ErrNoTenant } candID, err := uuid.Parse(strings.TrimSpace(in.CandidateID)) if err != nil { return out, ErrCandidateUnknown } if len(in.Bytes) == 0 { return out, ErrDocEmpty } if len(in.Bytes) > MaxCandidateDocBytes { return out, fmt.Errorf("%w: %d bytes, the cap is %d", ErrDocTooLarge, len(in.Bytes), MaxCandidateDocBytes) } mt := normalizeCandidateMediaType(in.MediaType, in.FileName) ext, ok := candidateMediaTypes[mt] if !ok { return out, fmt.Errorf("%w: %q", ErrDocMediaType, mt) } docType := strings.TrimSpace(in.DocumentType) if docType == "" { docType = "resume" } if !candidateDocTypes[docType] { return out, fmt.Errorf("%w: %q", ErrDocTypeInvalid, docType) } sum := storage.SHA256Hex(in.Bytes) key := fmt.Sprintf("org/%s/candidate/%s/%s%s", orgID, candID, sum, ext) actor := actorUUIDPtr(ctx) err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { // The candidate must exist FOR THIS ORG, asked inside the tenant transaction so RLS answers rather // than the application believing. var exists bool if e := tx.QueryRow(ctx, `SELECT EXISTS (SELECT 1 FROM candidates WHERE id=$1 AND deleted_at IS NULL)`, candID).Scan(&exists); e != nil { return e } if !exists { return ErrCandidateUnknown } // DUPLICATE DETECTION BY CONTENT, scoped to the candidate. Recruiters re upload the same resume // constantly, and the same file legitimately appears on two different people, so a global unique // would be wrong. var dup string e := tx.QueryRow(ctx, `SELECT id::text FROM candidate_documents WHERE candidate_id=$1 AND sha256=$2 AND is_current LIMIT 1`, candID, sum).Scan(&dup) if e == nil { return fmt.Errorf("%w: %s", ErrDocDuplicate, dup) } if !errors.Is(e, pgx.ErrNoRows) { return e } // THE BYTES LAND BEFORE THE ROW. A row whose bytes are missing is worse than a stored blob with no // row, because the first is a broken record a person will open and the second is only wasted space. if e := s.docStore.Put(ctx, key, in.Bytes); e != nil { return fmt.Errorf("matching: store candidate document: %w", e) } e = tx.QueryRow(ctx, ` INSERT INTO candidate_documents (organization_id, candidate_id, document_type, file_name, media_type, storage_key, size_bytes, sha256, uploaded_by_user_id, extraction_status) VALUES (NULLIF(current_setting('app.current_org_id', true), '')::uuid, $1,$2,$3,$4,$5,$6,$7,$8,'pending') RETURNING id::text, created_at`, candID, docType, safeFileName(in.FileName), mt, key, int64(len(in.Bytes)), sum, actor). Scan(&out.ID, &out.CreatedAt) if e != nil { return e } if s.aud != nil { // THE BYTES ARE NOT IN THE AUDIT ROW. What is recorded is that a document of a named type was // attached to a named candidate, by whom, with its content hash. The hash is the integrity stamp // that lets somebody prove later that the file they are holding is the file that was uploaded. body, _ := json.Marshal(map[string]any{ "candidate_id": candID.String(), "document_type": docType, "file_name": safeFileName(in.FileName), "sha256": sum, "size_bytes": len(in.Bytes), }) return s.aud.OnTx(ctx, tx, audit.Event{ Action: "candidate.document.uploaded", ActorUserID: actor, EntityType: "candidate", EntityID: candID.String(), NewValues: body, IPAddress: ip, UserAgent: ua, }) } return nil }) if err != nil { return CandidateDocument{}, err } out.CandidateID, out.DocumentType, out.FileName = candID.String(), docType, safeFileName(in.FileName) out.MediaType, out.SizeBytes, out.SHA256, out.IsCurrent = mt, int64(len(in.Bytes)), sum, true if actor != nil { out.UploadedBy = actor.String() } return out, nil } func (s *Service) ListCandidateDocuments(ctx context.Context, candidateID uuid.UUID) ([]CandidateDocument, error) { if s.db == nil { return nil, ErrNoDatabase } out := make([]CandidateDocument, 0, 8) err := s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { rows, e := tx.Query(ctx, ` SELECT d.id::text, d.candidate_id::text, d.document_type, d.file_name, d.media_type, d.size_bytes, d.sha256, coalesce(d.uploaded_by_user_id::text,''), coalesce(u.full_name,''), d.is_current, d.created_at FROM candidate_documents d LEFT JOIN users u ON u.id = d.uploaded_by_user_id WHERE d.candidate_id = $1 ORDER BY d.is_current DESC, d.created_at DESC`, candidateID) if e != nil { return e } defer rows.Close() for rows.Next() { var d CandidateDocument if e := rows.Scan(&d.ID, &d.CandidateID, &d.DocumentType, &d.FileName, &d.MediaType, &d.SizeBytes, &d.SHA256, &d.UploadedBy, &d.UploaderName, &d.IsCurrent, &d.CreatedAt); e != nil { return e } out = append(out, d) } return rows.Err() }) return out, err } // DownloadCandidateDocument returns the bytes and the metadata needed to serve them safely. The storage key // is resolved from the ROW, never from anything a caller supplied, so a request cannot reach a path of its // own choosing. func (s *Service) DownloadCandidateDocument(ctx context.Context, docID uuid.UUID) ([]byte, CandidateDocument, error) { var meta CandidateDocument if s.db == nil { return nil, meta, ErrNoDatabase } if s.docStore == nil { return nil, meta, ErrNoStorage } var key string err := s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { e := tx.QueryRow(ctx, ` SELECT id::text, candidate_id::text, document_type, file_name, media_type, size_bytes, sha256, storage_key, is_current, created_at FROM candidate_documents WHERE id = $1`, docID). Scan(&meta.ID, &meta.CandidateID, &meta.DocumentType, &meta.FileName, &meta.MediaType, &meta.SizeBytes, &meta.SHA256, &key, &meta.IsCurrent, &meta.CreatedAt) if errors.Is(e, pgx.ErrNoRows) { return ErrDocNotFound } return e }) if err != nil { return nil, meta, err } b, err := s.docStore.Get(ctx, key) if err != nil { return nil, meta, fmt.Errorf("matching: read candidate document: %w", err) } // THE INTEGRITY STAMP IS CHECKED ON THE WAY OUT. If the stored bytes no longer hash to what was recorded, // something replaced them, and serving them anyway would hand a recruiter a file the audit trail does not // actually describe. if meta.SHA256 != "" && storage.SHA256Hex(b) != meta.SHA256 { return nil, meta, fmt.Errorf("matching: stored document %s does not match its recorded hash", meta.ID) } return b, meta, nil } // SupersedeCandidateDocument marks a document replaced rather than deleting it, so what was sent to a client // six months ago is still recoverable. There is no delete path, deliberately. func (s *Service) SupersedeCandidateDocument(ctx context.Context, docID uuid.UUID, ip, ua string) error { if s.db == nil { return ErrNoDatabase } actor := actorUUIDPtr(ctx) return s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { tag, e := tx.Exec(ctx, `UPDATE candidate_documents SET is_current = false WHERE id = $1 AND is_current`, docID) if e != nil { return e } if tag.RowsAffected() == 0 { return ErrDocNotFound } if s.aud == nil { return nil } body, _ := json.Marshal(map[string]any{"document_id": docID.String()}) return s.aud.OnTx(ctx, tx, audit.Event{ Action: "candidate.document.superseded", ActorUserID: actor, EntityType: "candidate_document", EntityID: docID.String(), OldValues: body, IPAddress: ip, UserAgent: ua, }) }) } // normalizeCandidateMediaType trusts the EXTENSION over the declared type. A browser's guess is frequently // wrong and is always caller supplied, while the extension is at least the name the person chose. Neither is // authoritative, which is why the result is checked against a closed allowlist rather than used directly. func normalizeCandidateMediaType(declared, fileName string) string { byExt := map[string]string{ ".pdf": "application/pdf", ".doc": "application/msword", ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".rtf": "application/rtf", ".txt": "text/plain", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", } if mt, ok := byExt[strings.ToLower(filepath.Ext(fileName))]; ok { return mt } d := strings.ToLower(strings.TrimSpace(declared)) if i := strings.IndexByte(d, ';'); i >= 0 { d = strings.TrimSpace(d[:i]) } return d } // safeFileName strips any path a caller supplied and bounds the length. The name is only ever a label shown // to a person and set in a Content-Disposition header; it never touches the storage key, which is derived // from the content hash. func safeFileName(n string) string { n = filepath.Base(strings.TrimSpace(n)) n = strings.Map(func(r rune) rune { if r < 32 || r == '"' || r == '\\' || r == '/' { return -1 } return r }, n) if n == "" || n == "." || n == ".." { return "document" } if len(n) > 180 { n = n[:180] } return n }

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