ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / docs/ARCHITECTURE.txt

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / docs/ARCHITECTURE.txt
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberdocs/ARCHITECTURE.txt
Original SHA-25671765110e4603b77e946cc5c6bd260b5d03cbb648d7a3859e31f21b17e09e535
Git blob SHAb4f436ec95566302e5ceeb019d7d5494aeb0b677
Reading-copy SHA-25671765110e4603b77e946cc5c6bd260b5d03cbb648d7a3859e31f21b17e09e535

Original source ↗

Recovered source transcript

Download complete source text ↓1,876 lines · 107.7 KB
================================================================================ missionMATCH PLATFORM Architecture, Data Flow, Product Breakdown, AI Layer, Operations, Incidents ================================================================================ THIS IS A LIVING DOCUMENT. Canonical at docs/ARCHITECTURE.txt in the repository and NOWHERE ELSE. Any copy outside the repo is stale by definition. Revision 29 July 2026, revision 4, at commit 870d5ad. Supersedes revision 3 (9a73b61), revision 2 (b1a298d), revision 1 (b8c7b07), the 28 July early edition (e9ff911), and the 21 July edition (9e77f65). Trigger for this revision: a phase close and two production deploys. Phase 2 scope completion added table extraction, split and merge, draft generation, and the three missing intake screens; migrations 0081 through 0084 shipped to production; and Gates A, B, C and D were all re run, Gate C for the first time against these screens. SECRETS NEVER APPEAR IN THIS DOCUMENT, regardless of anyone's direction, including the owner's. A previous copy of this file carried an API key at its tail; it was removed before this file was first committed, and git history was checked and confirmed never to have contained it. WHEN THIS DOCUMENT IS REVISED, exactly four moments and no others: every phase close, as a Gate D line item every production deploy every incident closed every recorded decision HOW IT IS REVISED. Volatile facts are RE MEASURED, never edited by hand: schema versions queried per database, binary hashes, account and data counts, environment flags, task and track statuses, the risk register, and the current state section. The header takes a new date, commit, and supersedes line. A claim that cannot be re measured is labeled INFERRED in the sentence that makes it. Corrections are withdrawn BY NAME, never silently edited. Nothing aspirational ever enters: a planned thing belongs in the directive and the ledger, not here. GOVERNING DOCUMENTS, read in this order: CLAUDE.md docs/CLAUDE_CODE_BUILD_DIRECTIVE.md the work order docs/DIRECTIVE_AMENDMENTS_CONSOLIDATED.md amendments 1 through 5 docs/DIRECTIVE_AMENDMENT_6.md identity, roles, the operator plane docs/BUILD_CONTINUATION_PROTOCOL.md the five gate phase close docs/BUILD_STATE.md the append only ledger docs/RUNBOOK_RESTORE.md how to actually restore this file what the system IS, measured Everything here was measured. Where a number came from a command, that is said. Where something is inferred rather than observed, the sentence says so. Where an earlier claim was wrong, it is withdrawn by name rather than quietly edited, because a document that hides its corrections cannot be trusted about anything. CONTENTS 0 What this is 1 Physical topology 2 Control plane and data plane 3 Environments 4 Request data flow, the map 5 Authorization model 6 Authentication and session security 7 THE FOUR PRODUCTS, IN DEPTH 8 The matching engine 9 The opportunity pipeline 10 THE AI LAYER, UNDER SCRUTINY 10A THE LEARNING BOUNDARY, three doors and no fourth 11 Federation relationship to PANTHEON 12 File architecture 13 How it is built 14 Deployment and its real failure modes 15 Observability and what runs on a timer 16 THE 28 JULY 2026 INCIDENT RECORD 17 Current state, honestly 18 Risk register 19 The design decisions that explain the rest 20 Glossary SCALE, re measured 28 July 2026 at commit 9a73b61: 327 Go source files 68,304 lines 228 Go test files 37,903 lines (36 percent of the Go is tests) 87 TypeScript and TSX files 13,217 lines 80 SQL migrations, head 0081, plus a segregated EEO set of 2 36 command line binaries 24 domain modules, 31 cross cutting platform packages 22 capabilities, 8 roles, 4 products 86 tables in the tenant database, 50 with FORCED row level security 372 commits on feature/opportunity-to-outcome scoring engine diff against the e74fd2e baseline: EMPTY, verified (anchor corrected 29 July 2026, finding D8; 9e77f65 was the 24 June project baseline and diffs 1476 lines, so it could never be empty) MEASURED STATE AT THIS REVISION, every number re measured rather than carried forward: scale 339 Go source files, 236 test files, 94 frontend files, 83 migrations at head 0084, 408 commits. The frozen scoring engine diff against e74fd2e is EMPTY, and the anchor and path are both asserted to exist before that result is trusted, because this check has failed open twice. schema, queried per database, never summarized control plane 100.77.114.40:5433/missionmatch v84 tenant 100.94.8.94:5432/missionmatch v84 staging 100.94.8.94:5432/missionmatch_staging v84 ALL THREE LEVEL for the first time since the build began. 0081 through 0084 are additive and carry no data, so they ship to production while the routes stay dark, which keeps the Gate 6 freeze intact. CORRECTION TO THE CONTROL PLANE ADDRESS, and it cost time to rediscover. Earlier revisions wrote "megamind-agi:5433". megamind-agi has TWO tailnet identities: the Windows host at 100.69.120.61, and the WSL2 instance at 100.77.114.40 running its own tailscaled. Postgres binds INSIDE WSL2, so it answers on .40 and a connection to .61:5433 times out with no useful error. There is no sshd inside WSL2 either, so the only route in is ssh to the Windows host and then wsl with a STAGED script, never inline quoting. STAGING IS ONE AHEAD deliberately: migration 0081, provenance at origin, is staging only pending an approved production deploy under the Track guardrails. Named here so it reads as intended rather than as drift. binaries both production API nodes 8f24414531e80a9a (identical) staging API 98edd2b8094721f0 live bundle /assets/index-BE5iWWvj.js environment flags, production MM_ENV=development MM_TENANCY_MODE=per_tenant MM_MFA_REQUIRED=false MM_OPERATOR_MFA_REQUIRED=false accounts, six, from the authoritative control plane joseph.w.anady@gmail.com operator active last login 28 Jul 11:51 patriciacox6@aol.com superuser active last login 28 Jul 08:04 tallen282005@gmail.com superuser active last login 27 Jul 14:42 batwood@igotozarks.com recruiter active last login 27 Jul 15:17 trutle973@hotmail.com recruiter active last login 27 Jul 16:51 trackh.probe@missionmatch.test viewer DISABLED last login 28 Jul 16:36 The probe was created for one production positive control and retired. Every last login value above is real and current, which was NOT true this morning: see incident 7. data, tenant database candidates 11, requirements 6, opportunity_records 6676, audit_logs 56470, clients 0, requisitions 0, applications 0 track and phase status PHASE 2 current. Phases 3, 4, 5, 5A, 6 not started. TRACK U complete, all six items, all four gate items proven. TRACK H items 1, 3, 4, 5 complete. Items 2 and 6 are the owner's. PHASE 2 Gate A is OPEN pending exactly ONE blocker, a real solicitation package. Gate E is pending the real document trial plus the owner's approval. Gates B, C, and D PASS. The complete bundle is filed at docs/evidence/phase2/ with a README that states what it does NOT claim next to what it does. See docs/PHASE2_DOCUMENT_TRIAL.md. Tasks T1 and T2 complete. -------------------------------------------------------------------------------- 0. WHAT THIS IS -------------------------------------------------------------------------------- A Cleared Workforce Intelligence Platform for United States government contractors, cleared staffing firms, proposal teams, and capture teams. It is NOT a generic applicant tracking system. Everything serves one loop: Requirement -> Candidate Intelligence -> Match Scoring -> Ranked Candidate Slate -> Proposal Readiness The current build program extends the front of that loop: Opportunity -> Source Documents -> Scope Extraction -> Human Review -> Approved Requirements -> Staffing Slates -> Proposal Workspace -> Submission -> Outcome Legally the product is an Automated Employment Decision Tool. That single fact drives more architecture than any technical consideration: NYC Local Law 144, Title VII, Colorado and California fair employment law, the EU AI Act, and the vendor exposure recognised in Mobley v. Workday. Every design choice that looks paranoid below traces back to it. WHO IS ON IT TODAY. One production organization, Acme GovCon, five accounts: one operator (Joseph Anady), two tenant superusers (Patricia Cox, Tallen), two recruiters (Brian Atwood, one other). FG Talent Partners is the live design partner and the first client site. -------------------------------------------------------------------------------- 1. PHYSICAL TOPOLOGY -------------------------------------------------------------------------------- internet | Cloudflare | +------------------------v--------------------------+ | BUBBLES Debian 13, i5-8350U, 15GB | | 100.90.97.104 | | | | nginx TLS, fail2ban, ~60 other vhosts | | | | | +-- upstream mm_api (least_conn, passive | | | health checks, keepalive 32) | | | +-- 127.0.0.1:8094 Bubbles | | | +-- 100.77.114.40:8094 megamind-agi | | | | | +-- limit_req zone=mm_auth 1r/s, answers 429 | | +-- missionmatch.thatwebhostingguy.com | | | root /var/www/sites/missionmatch | | +-- missionmatch-staging.thatwebhostingguy.com | | | root /var/www/sites/missionmatch-staging | | | /api/ proxies to 127.0.0.1:8097 | | +-- fg-talent.com | | root /var/www/sites/fgtp | | | | mm-api /home/user/missionmatch/mm-api | | mm-api-staging /opt/missionmatch-staging/mm-api | | mmorch :9505 mmdb :9506 mmk :9500 mmreason | +---------------------------------------------------+ | | | tailnet | tailnet v v +------------------------+ +---------------------------------+ | M4 Mac mini | | MEGAMIND-AGI | | 100.94.8.94 | | Windows 11 + WSL2 Ubuntu 26.04 | | 10 core, 16GB | | 100.77.114.40 | | | | i7-8700K 12t, 26GB allotted | | PostgreSQL 16.14 :5432 | | | | missionmatch | | PostgreSQL 18 | | TENANT DATA PLANE | | :5432 PANTHEON cluster | | org 11111111... | | :5433 missionmatch cluster | | 86 tables, v84 | | missionmatch | | missionmatch_staging | | CONTROL PLANE, v84 | | full stack, v84 | | missionmatch_staging | | | | EMPTY SHELL, unused | | megamind-gateway :8090 | | | | bearer authenticated | | mm-api :8094 second node | | Ollama :11434 | | /opt/missionmatch/mm-api | | bge-small-en-v1.5 | | | | llama3.1:8b | | PANTHEON organs: mm-oracle 9402,| +------------------------+ | mm-loom 9410, mm-serve, mm-eye, | | mm-sem, mm-world, mm-game, | +------------------------+ | mm-narrate, mm-shard, | | VALKYRIE M1, 8GB | | mm-genserve | | 100.89.0.6 codex 8790 | +---------------------------------+ +------------------------+ WHY THIS SHAPE The API tier is genuinely liquid. mm-api holds no per process state: sessions live in the control plane database, CSRF is a signed double submit. Any request may be served by either node, and a session minted on one is valid on the other. Passive health checks take a dead node out and put it back with no operator action. Verified by stopping a node mid traffic: 14 of 14 requests succeeded. The DATABASE tier is deliberately NOT liquid, and this is the single most important architectural decision in the system. Recruiting correctness rests on FOR UPDATE row locks that serialise seat caps, stage transitions, and ownership claims. Multi master would break every one of them silently. So state is one primary per tenant. What IS distributed is TENANTS. tenant_directory records a host and port PER TENANT, so different tenants live on different machines while each still has exactly one primary and every lock keeps working unchanged. THE LIABILITY OF THIS SHAPE, stated plainly. Three of the four machines are consumer hardware in one physical location, two of them are a laptop and a desktop that can be closed or unplugged, and there is no off machine backup of either database. The design is cloud portable by construction and is running on a home network by circumstance. Those are different facts and only the first is an architectural claim. TOPOLOGY RULE, owner decision 29 July 2026, and it is enforced rather than aspirational: BUBBLES CARRIES EXACTLY TWO THINGS hosted website content, the 138 nginx vhosts deployed production artifacts, the API node binary and the job binaries systemd actually runs, plus two rollback points EVERYTHING ELSE LIVES ON MEGAMIND-AGI build workspace /home/user/missionmatch/workspace document intake /home/user/missionmatch/inbox archived build artifacts /home/user/missionmatch/archive Bubbles is the revenue web host. Build residue there competes with customer vhosts on a disk already at 82 percent, and a scratch file left beside a deployed binary is something a later session can mistake for deployed state. Audited and enforced on 29 July: 463 MB of stale rollback binaries, 59 MB of gate captures, and twelve staged scripts were archived to megamind-agi by checksum and only then removed, with every serving surface verified untouched afterwards. -------------------------------------------------------------------------------- 2. CONTROL PLANE AND DATA PLANE -------------------------------------------------------------------------------- CONTROL PLANE megamind-agi 100.77.114.40 PORT 5433, database missionmatch organizations, users, auth_credentials, mfa_totp, mfa_recovery_codes, auth_sessions, user_invites, login_attempts, user_tool_access, tenant_directory. Schema v84. This is what MM_DATABASE_URL points at. ANSWER EVERY IDENTITY QUESTION HERE. TENANT DATA PLANE M4 100.94.8.94 PORT 5432, database missionmatch. Schema v84. Everything else. 86 tables, 50 with forced RLS. Reached ONLY by routing through tenant_directory. Named in no env file except as the value of MM_TENANT_DSN_TENANT_ACME. ITS COPY OF users IS NON AUTHORITATIVE, and is currently stale and incomplete: it was missing two of the five real accounts and had a stale status on a third. STAGING M4 100.94.8.94 PORT 5432, database missionmatch_staging. Schema v84. 2766 organizations, 8872 candidates, its own API, vhost, and isolated role. Runs shared tenancy, not per_tenant. NOT USED megamind-agi 5433 database missionmatch_staging is an EMPTY SHELL. Named in an early amendment. Must never be used. WHY SPLIT. Login resolves a user by GLOBAL email BEFORE any organization is known. Handing the router to auth would make authentication depend on the very answer it exists to produce. So auth is wired to a direct pool and never to the router (cmd/api/main.go line 257), while business queries go through the router. Global email uniqueness does NOT break under per tenant databases, because identity is authoritative in ONE database. The unique index there is genuinely global. Copies of users in tenant databases exist only so business tables can foreign key to a user, and are synced, not authoritative. TWO MODES, selected by MM_TENANCY_MODE. shared: one database, isolation by forced RLS, the default, what staging runs. per_tenant: each organization's business data in its own database, resolved per request, RLS still forced INSIDE each tenant database so the mechanisms stack. Production runs per_tenant, confirmed from the boot log: secrets_backend=env max_pools=32 max_conns_per_pool=4 idle_evict=15m0s. PER ENVIRONMENT ROLE NAMES, from incident D6, 29 July 2026. ROLES ARE CLUSTER SCOPED. DATABASES ARE NOT. The production tenant database and missionmatch_staging live in ONE M4 cluster and therefore share ONE role namespace, so for a long time they shared missionmatch_migrator. A rehearsal aimed at staging changed the password of a role production depended on, and one of the two API nodes was down for one minute fifty nine seconds as a result. nginx failed over and no client saw a 5xx, which is the redundancy working rather than an argument that the mistake was small. missionmatch_migrator PRODUCTION TENANT only missionmatch_staging_migrator STAGING only, CONNECT on the production database REVOKED, proven by refusal The containment is proven with a positive control rather than asserted: the staging role reads 2,784 staging organizations, and the same credential against the production database is refused with permission denied. THE RULE THAT GOES WITH IT: on a shared cluster, roles, role passwords, extensions, tablespaces, and cluster settings are PRODUCTION CHANGES by definition, whichever database the statement names. Rehearsals of cluster scoped mutations do not exist. Every credential and every consuming location is inventoried in docs/CREDENTIAL_CONSUMERS.md, references only. Rotations enumerate from it, because the rotation that caused D6 was enumerated from memory and missed two. -------------------------------------------------------------------------------- 3. ENVIRONMENTS -------------------------------------------------------------------------------- DEVELOPMENT STAGING PRODUCTION API local go run Bubbles :8097 Bubbles :8094 and megamind-agi :8094 control DB local or staging M4 missionmatch_ megamind-agi:5433 staging missionmatch data plane same as control same (shared) M4:5432 missionmatch tenancy shared shared per_tenant DB role missionmatch_app missionmatch_ missionmatch_app staging_app MM_ENV development development development MFA off off off operator MFA on (the default) off off binary HEAD HEAD baseline + track only THE STAGING ISOLATION STORY, because it failed twice before it passed. Round one: staging and production ran as the SAME role on the SAME cluster, so staging credentials could connect to production and successfully write a row. The zero row reads people took for isolation were RLS with no org GUC set, not a privilege denial. PostgreSQL grants CONNECT to PUBLIC by default, which is what made every role in the cluster able to reach production. Fixed by creating missionmatch_staging_app with grants mirrored inside missionmatch_staging only, granting CONNECT on production explicitly to the four legitimate roles, and revoking the PUBLIC blanket. Round two: that fix mirrored TABLE grants and not FUNCTION grants, so the new role held EXECUTE on ZERO of the nineteen SECURITY DEFINER auth functions. Nothing could log in on staging at all and invite acceptance returned 500. Found 28 July, nineteen grants mirrored in. IF A ROLE IS EVER CLONED AGAIN, CLONE FUNCTIONS AS WELL AS TABLES. -------------------------------------------------------------------------------- 4. REQUEST DATA FLOW, THE MAP -------------------------------------------------------------------------------- browser | | https, __Host- session cookie, X-CSRF-Token header v nginx on Bubbles | TLS terminate, limit_req on /api/auth/, proxy_next_upstream | (never non_idempotent: a GET may retry on the other node, a POST never | does, because a retried write could apply a placement twice) v chi router (cmd/api/main.go) | +-- obs middleware structured slog, request id, metrics +-- ratelimit token bucket, PER PROCESS +-- CSRF Protect signed double submit, bound to the session hash +-- SessionMiddleware __Host- cookie -> auth.Validate | | | +-> CONTROL PLANE: session row, state=active, mfa_satisfied | +-> loads role AND tool entitlement onto the principal | +-> EffectiveTools widens the top seats BY RULE, once, here | +-> tenant.WithOrg(ctx, org) + tenant.WithUser(ctx, principal) | +-- RequireCapability what you may DO (22 capabilities) 403 +-- RequireTool what you may SEE (4 products) 404 +-- RequirePlatform the platform plane (operator only) 404 | v module handler (internal/modules/<name>/handler.go) | thin: decode, call the service, map the error v service (service.go) | +-- db.RunInTenantTx(ctx, fn) | | | +-- per_tenant: router resolves org -> tenant_directory -> | | secrets resolver (MM_TENANT_DSN_<REF>) -> tenantpool | | (bounded LRU, singleflight, ping before cache, refcount pin, | | typed errors that NEVER fall back to another tenant) | | | +-- shared: the one pool | | | +-- BEGIN | +-- SELECT set_config('app.current_org_id', $1, true) | | transaction local, so it cannot leak across the pool | +-- fn(ctx, tx) <-- ALL repository work happens here | +-- COMMIT (or ROLLBACK on any error) | v PostgreSQL forced row level security, policy = org matches the GUC, no GUC set yields ZERO rows (default deny, fail safe) TWO STACKED SAFEGUARDS: Go side no validated org in context, RunInTenantTx refuses before the pool is touched at all. DB side an unset GUC makes current_setting(...,true) NULL, so the policy matches nothing. PROVEN, not asserted, on 28 July using the production DSN the running process holds: connect as missionmatch_app, confirm rolbypassrls=false, read candidates with NO org GUC and get 0 rows, read the same table inside a transaction with the GUC set and get 11. That is the application's real path. THE TRAP THAT CATCHES EVERYONE. A query with an explicit "WHERE organization_id = $1" predicate LOOKS scoped and is not. Forced RLS filters the row out before the predicate is evaluated, so a statement on a bare pool connection with no GUC matches ZERO rows and returns "not found" for a row that plainly exists. PATCH /me/profile answered 404 to the signed in user on her own account for exactly this reason. Any read or write of a tenant table must be inside RunInTenantTx, without exception. THE RATE LIMITER IS PER PROCESS, so a client's effective allowance is the configured rate times the node count. That is why the login throttle lives in nginx, where it is globally correct regardless of how many nodes exist, and the in process limiter is a second layer only. -------------------------------------------------------------------------------- 5. AUTHORIZATION MODEL -------------------------------------------------------------------------------- THREE INDEPENDENT AXES. Collapsing any two would be wrong. ROLE = what you may DO viewer(0) member(1) recruiter(2) manager(3) admin(4) owner(5) superuser(6) operator(7) OPERATOR is the PLATFORM PLANE, above and outside the tenant ladder. It holds every platform capability and every tenant capability in every tenant. It exists because superuser previously meant two things at once, the platform seat and the client's top seat, which is why a client was once shown platform shaped controls that refused her. SUPERUSER is now the TENANT top seat: everything BY RULE WITHIN ITS TENANT, explicitly not the platform capabilities. Grant rule: strictly BELOW your own, with one exception. Superuser may grant superuser, because a tier that cannot reproduce can only shrink and an organization losing its last holder would be locked out of its own access control. Nobody may change their OWN role, ever. PLATFORM CAPABILITIES are the ones that act across every tenant at once. Today exactly {curation.curate}, which writes the GLOBAL skill ontology every tenant is scored against. A client's top seat approving an ontology edge would change what a competitor's candidates score. TOOL = what you may SEE missionmatch, screenmatch, slatematch, recruitmatch. Per user, explicit, FAILS CLOSED for every role below superuser. Two bounds on granting: outrank the target, AND confer only tools you hold. Revocation needs only the first, because taking access away is safe. BY RULE for the top seats, because relying on provisioning to keep an invariant true is not the same as the invariant being true: the design partner's top seat held superuser with ZERO grants and saw nothing. Enforced on each tool's route GROUP. Answers 404, never 403. PLANE = whether the surface is tenant scoped at all RequirePlatform, operator only, 404. A platform surface must be indistinguishable from a path that was never built. NO SILENT GREY. A disabled entitlement control must STATE ITS REASON, and the two reasons are distinct because they have different fixes: the organization is not entitled to that product, or you do not personally hold that tool. OPEN DESIGN POINT: no organization level product entitlement table exists yet, so every tenant is treated as entitled to all four. security.OrgEntitledTools(orgID) is the single place that narrows when the Phase 5A operator console lands. It takes orgID today, unused, so adding the lookup is a body change and not a signature change through every caller. -------------------------------------------------------------------------------- 6. AUTHENTICATION AND SESSION SECURITY -------------------------------------------------------------------------------- PASSWORD KDF PBKDF2 HMAC SHA 256 (SP 800-132). NEVER argon2 or bcrypt, which sit outside the validated boundary. 600,000 iterations. Input capped at 64 characters to stay inside the CAVP tested length bound. Exceeding the tested iteration envelope is a STRONGER choice, not a deviation; state it that way to an assessor. PEPPER Versioned, HMAC SHA 256 under a server held key, applied BEFORE PBKDF2 so it stays in boundary. Per credential pepper_version so it can rotate without a flag day. MFA TOTP RFC 6238, HMAC SHA 256 end to end, 32 byte secret, 6 digits, 30 seconds, strictly monotonic replay guard so a used code and every earlier in window step cannot be replayed. Implemented on crypto/hmac rather than a library, so every primitive is provably inside the validated module. Secrets AES 256 GCM at rest with a key_version. 10 recovery codes. SESSIONS Opaque, server side, 32 random bytes, stored ONLY as a SHA 256 hash. __Host- cookie, HttpOnly, Secure, SameSite Strict. Instantly revocable. Two stage: auth_pending then active. 15 minutes idle, 12 hours absolute, computed by the DATABASE clock, not the application's. CSRF Signed double submit BOUND to the session hash. That binding is what stops an attacker being handed a token that works against a victim's session. LOCKOUT Keyed on EMAIL alone, never (email, ip). Scoped to the pair it was free to bypass by rotating source addresses, which defeated the per ip rate limiter with the same move, so two controls shared one exit. The audit records the source spread. IDENTITY One human, one account, one org. Global unique index on lower(email). Login resolves by global email BEFORE the org GUC is set, through a SECURITY DEFINER cross org lookup. PROVISIONING No public signup. First org and owner by the migrator role through a migrator only SECURITY DEFINER function. Everyone else by authority bounded invite. Delivery is MANUAL at pilot: the endpoint returns the one time link and a human delivers it. DEFERRED OIDC Login.gov, Entra Gov, SAML, WebAuthn, PIV CAC, and public forgot password are sub phase 2.9. The five federal auth libraries are deliberately not in go.mod yet. CURRENT DEVIATIONS, both deliberate and both recorded: MM_MFA_REQUIRED is FALSE everywhere, so login is password only. Config REFUSES this when MM_ENV is production. MM_OPERATOR_MFA_REQUIRED is FALSE in production only, set 28 July 2026 at the owner's explicit direction. Default is true, staging proves the rule, config refuses it in a production MM_ENV, and the boot log states it at every start. Re arming is one environment variable per node. -------------------------------------------------------------------------------- 7. THE FOUR PRODUCTS, IN DEPTH -------------------------------------------------------------------------------- All four are ONE binary, ONE database, ONE candidate spine. A product is a TOOL ENTITLEMENT plus a route group plus a set of screens. There is no duplicated candidate model, no second scoring engine, and no per product database. That is the whole reason a person can sit on a proposal slate and in a recruiting pipeline at once and resolve to one candidate id. ................................................................................ 7.1 missionMATCH "who can support this mission today" ................................................................................ WHO IT IS FOR: capture leads and program managers who need to know whether the bench can cover a mission right now. SCREENS (frontend/src/tools/missionmatch/) CommandCenter.tsx mission readiness aggregation, the executive view Candidates.tsx the candidate roster and profile Ask.tsx the natural language interface to the AI layer WhoCanSupport.tsx the named question the product is built around API SURFACE GET /command-center readiness tiles GET /command-center/federal-signal external signal overlay POST /command-center/upcoming/{id}/adopt adopt a forecast record GET /candidates/intelligence enriched candidate view GET /requirements/{id}/support who can support this POST /ai/query the Ask path WHAT IT ACTUALLY COMPUTES. The command center derives readiness from live counts, not from a stored score: available candidates by clearance tier against open requirement demand, producing a readiness band and a list of named gaps ("NEED 10 Intelligence Analysts, 3 Data Scientists, 2 Cyber Architects"). The demo seed is deliberately shaped so that Win Impact reads HIGH on the Candidates page while the Command Center still names the open gaps, so the two screens tell one connected story rather than contradicting each other. STATE: works. Renders with zero 5xx. Data is thin: 11 candidates, 6 requirements in production. ................................................................................ 7.2 screenMATCH "is this candidate qualified for this requirement" ................................................................................ WHO IT IS FOR: recruiters and proposal staff qualifying ONE person against ONE requirement, and needing to defend the answer. SCREENS (frontend/src/tools/screenmatch/) ScreeningQueue.tsx the work queue of pending evaluations CandidateEvaluation.tsx the full explainable result for one pairing ScreenCompare.tsx two candidates side by side AliasSettings.tsx skill alias and term normalization controls API SURFACE POST /match the flat legacy alias POST /screen the canonical evaluation GET /requirements/{id}/candidates ranked for one requirement GET /candidates/{id}/opportunities the reverse direction GET /candidates/{id}/clearance-provenance where a clearance claim came POST /mission-check/screen the browser parse path GET /mission-check/opportunities WHAT MAKES IT DEFENSIBLE. Every evaluation returns the per component breakdown, the band, which caps were applied and why, the engine version, the timestamp, and which candidate skill matched which required skill with the similarity that matched them. That last item is the one an auditor asks for and the one most products cannot produce. CLEARANCE PROVENANCE is its own endpoint on purpose: a clearance value is a self reported indicator, and the product must be able to show WHERE the claim came from rather than presenting it as fact. STATE: works. The most complete product in the platform after the engine. ................................................................................ 7.3 slateMATCH "who belongs on the proposal" ................................................................................ WHO IT IS FOR: proposal and capture teams building a named staffing slate for a bid. THIS IS THE COMMERCIAL DIFFERENTIATOR: requirement to slate. SCREENS (frontend/src/tools/slatematch/) Slate.tsx the ranked slate with per member decisions Capture.tsx opportunity intake (Phase 1, DARK in production) OpportunityDetail.tsx opportunity intelligence and edit (DARK) API SURFACE POST /slates/generate build a ranked slate GET /requirements/{id}/slates slates for a requirement GET /slates/{id} one slate POST /slates/{id}/members/{candidateID}/decision approve or reject GET /slates/{id}/members/{candidateID}/trace the decision trace GET /slates/{id}/proposal-readiness readiness for the bid GET /slates/{id}/export csvsafe export DARK IN PRODUCTION until Gate 6, mounted only at repository HEAD: POST /opportunities/tracked, PATCH .../{id}, GET .../scope, POST .../scope/items, POST /requirement-drafts/{id}/approve and /reject DECISION VOCABULARY: slate_members.decision is CHECK constrained to pending, approved, rejected. Human in the loop is a database constraint, not a convention. Nothing auto rejects. EXPORT goes through internal/platform/csvsafe, which escapes formula injection, because a slate export is opened in Excel by someone who did not create it. STATE: the slate path works. The opportunity capture front end is BUILT and verified on staging but deliberately DARK in production, because the Gate 6 freeze says no build feature route is reachable in production until the whole program passes. Proven dark after every deploy. ................................................................................ 7.4 recruitMATCH "work the desk" ................................................................................ WHO IT IS FOR: the recruiting desk. Clients, job orders, candidate pipeline, interviews, offers, placements. This is the operational heart and it is the LEAST exercised product in the platform. SCREENS (frontend/src/tools/recruitmatch/), 11 of them RecruiterDashboard.tsx the desk overview Clients.tsx / ClientDetail.tsx Requisitions.tsx / RequisitionDetail.tsx Pipeline.tsx the stage board for one requisition Assignment.tsx one application in depth Tasks.tsx ActivityFeed.tsx Analytics.tsx Reports.tsx API SURFACE, the largest in the platform, 40 routes clients GET/POST /clients, GET/PATCH /clients/{id}, POST /clients/{id}/contacts, PATCH /contacts/{id}, POST /clients/{id}/claim | /release | /reassign requisitions GET/POST /requisitions, GET/PATCH /requisitions/{id}, POST /requisitions/{id}/status | /claim | /release, GET /requisitions/{id}/pipeline, POST /requisitions/{id}/applications applications GET /applications, GET /applications/{id}, POST /applications/{id}/stage | /interviews | /offers | /placement, GET /applications/{id}/assignment offers POST /offers/{id}/status placements GET /placements, POST /placements/{id}/end work GET/POST /activities, PATCH /activities/{id}/note, GET/POST /tasks, PATCH /tasks/{id}, GET /tasks/queue reporting GET /analytics, GET /reports, GET /dispositions THE STATE MACHINES, read from the live database constraints, not from docs: applications.stage sourced -> screened -> submitted -> interviewing -> offered -> placed with rejected and withdrawn reachable from any stage requisitions.status draft, open, on_hold, filled, closed, cancelled offers.status extended, accepted, declined, rescinded, expired placements.status pending_start, active, completed, terminated, fell_off THE LOCKS THAT MAKE IT CORRECT. recruiting/ownership.go holds three FOR UPDATE locks (claim, release, reassign), requisition_service.go two, and placement_service.go one on the seat cap. These are the reason the database tier is not allowed to be multi master. Proven by racing them: 16 concurrent stage transitions elected one winner, 8 racing claims produced one owner, 8 placements into one seat produced one placement. STATE, AND THIS IS THE HONEST PART: recruitMATCH has ZERO PRODUCTION DATA. 0 clients, 0 requisitions, 0 applications, 0 placements. The schema, the services, the endpoints, the locks, the screens, and the analytics are all built. Nothing has ever been created, because the New Client form is too thin to record a real client. Expanding it is Phase 5 item 1. Consequences today: The dashboard "NOT TRACKED YET" panel is STALE HARDCODED COPY at internal/modules/recruitmatch/derive.go:73 and is now wrong about interviews, offers, and placements. Revenue, bill rates, and candidate source are genuinely not tracked. Time to fill has a migration but no service. Dashboard stat cards are not clickable through to their filtered lists. ................................................................................ 7.5 THE SHARED SPINE ................................................................................ ONE candidates table. ONE application record linking candidate to requisition. The frozen engine is reached from BOTH directions, a job order ranking candidates and a candidate ranking open job orders, through the same requisition to requirement bridge. screenMATCH is the deep evaluation of one pairing. slateMATCH is the proposal branch off the same spine. Shared read routes are gated on holding ANY tool rather than a specific one, because gating the candidate and requirement pickers to one product would break the other three, while leaving them open would expose the candidate list to an account entitled to nothing. THE FLAT ALIAS SURFACE. Pre split paths (POST /match, /slates/..., /candidates) still exist so older clients and the screenmatch redirect keep working. They carry the SAME tool entitlement as their canonical namespaces. They previously did not, which made the entitlement layer cosmetic: a user refused at /slatematch/slates/{id} could fetch the same slate, its decision trace, and its CSV export from /slates/{id} with no gate at all. The bookmark the gate exists to defeat was the flat one. -------------------------------------------------------------------------------- 8. THE MATCHING ENGINE (the regulated core) -------------------------------------------------------------------------------- Match Score = Clearance x0.25 + Skills x0.25 + Certifications x0.15 + CustomerExperience x0.15 + Experience x0.10 + LocationAvailability x0.10 Bands: Green (Proposal Ready) 90+, Yellow (Potential) 75 to 89.99, Red (Recruiting Required) below 75. Clearance: exact OR higher scores 100 percent; lower, expired, or unknown scores 0. The hierarchy is encoded, so TS/SCI satisfies Secret and Secret does NOT satisfy TS/SCI. Skills: 100 percent of required met scores full, 80 to 99 partial, below 80 reduced. Exact match first, then semantic similarity through embeddings, and the system always records WHICH candidate skill matched WHICH required skill and the similarity, because an AEDT decision must be explainable at that grain. TWO DETERMINISTIC BAND CAPS, applied after the band is derived. Neither ever changes the Total; each can only LOWER a band: 1. A clearance gap caps at Red. 2. An unmet mandatory skill caps a Green at Yellow. ALL scoring uses shopspring/decimal, never float64. The engine is a pure Go package with no DB and no I/O, skill_matcher injected. That purity is not aesthetic: it is what makes the score bit stable and reproducible, which is what an AEDT compliance artifact requires. THE ENGINE IS FROZEN. internal/modules/matching/engine is untouchable under the current directive and its diff against the starting commit is checked and must stay empty. Verified empty at this revision. EEO data lives in a physically and privilege segregated schema the application and scoring roles cannot read at all, with its own migration set and version table so sqlc never models it. Demographics flow ONE WAY, into adverse impact reporting run by a separate compliance role, never into a score. The matching and search code must never reference the EEO tables. THE COMPLIANCE ARTIFACT CHAIN, which is the actual product for a regulated buyer: per component breakdown, human readable rationale, gap summary, engine version, weights, caps applied, and a recordable decision trace. Humans approve or reject every slate member and nothing is ever auto rejected. Adverse impact reporting produces selection rates and four fifths ratios so a customer can run their own LL144 or OFCCP audit. The platform SUPPLIES the data for that audit; it does not constitute one, and vendor tooling does not transfer the employer's liability. -------------------------------------------------------------------------------- 9. THE OPPORTUNITY PIPELINE -------------------------------------------------------------------------------- An opportunity may enter through the SAM.gov API, manual entry, uploaded solicitation documents, a customer or partner scope, a spreadsheet import, or a future agency forecast feed. Every path converges into one workflow, and the SAFETY BOUNDARY is that nothing a machine derived becomes visible to the scoring engine without a named human approving it. TABLES, all with organization_id, forced RLS, composite indexes: ingest_manifest shared reference data, no RLS. EVERY synced row and every knowledge card traces to a row here. tracked_opportunities 31 columns. Unique partial index on (org, public_opportunity_id) so a tenant cannot track one notice twice. opportunity_versions IMMUTABLE. A trigger allows only the is_current flag to change and blocks DELETE outright. opportunity_documents sha256 duplicate detection, extraction_status state machine, malware scan hook between upload and pending. opportunity_document_chunks page, section, content hash, method, confidence opportunity_scope_items ck_scope_items_cited REFUSES uncited machine produced scope. A manual item may be uncited. requirement_drafts ck_drafts_approved_has_requirement, ck_drafts_decided_has_reviewer (so no automated path can approve), ck_drafts_skill_flags_align THE GATE RULES LIVE IN THE SCHEMA, not only in code. A future service bug cannot write uncited scope or an unattributed approval, because the database refuses it. The constraint names are listed so that claim is checkable. PROMOTION is one audited transaction taking FOR UPDATE on the draft row, recording the named approver, writing the requirement, and flipping the draft together. Raced: 8 concurrent promotions produced exactly 1 requirement. SEMANTIC RETRIEVAL IS LIVE. opportunity_records carries vector(384) with a partial HNSW cosine index and a generated search_tsv with a gin index. 6,676 records embedded with qllama/bge-small-en-v1.5. "cybersecurity engineering support for the Air Force" returns PACAF Cyber Systems Operations Support and Cybersecurity Support Services at 0.78 cosine, ranked by meaning. AMENDMENT HANDLING. sam-sync compares the source payload hash per tracking tenant and on a change writes an immutable version, retires its predecessor in the same transaction, cites the manifest, and raises an alert. Tenant authored fields survive a source refresh BYTE FOR BYTE, proven by md5 fingerprint. THE EXTERNAL BOUNDARY, redesigned 28 July 2026 after its fixtures found a hole. PROVENANCE IS BOUND AT ORIGIN, migration 0081. Six tables carry a provenance column that a DEFAULT supplies, a CHECK pins to one value, and a BEFORE INSERT OR UPDATE trigger overwrites on insert and refuses to change on update. A row in the public SAM cache is BORN public_cache; a tenant upload is BORN tenant_upload; a candidate is BORN tenant_record. The application cannot choose it, so fabricating provenance requires shipping a migration, which is a named reviewable location rather than a constant at a call site. WHY, and it is worth keeping. The gate was originally content based, and the Gate 2 fixtures proved that cannot hold: a candidate row with the uuid, email and phone stripped is still one named cleared human with a clearance, a location and an availability, and it crossed; a customer's own performance work statement contains no personal data at all and crossed too. The first is private because of WHAT IT IS, the second because of WHERE IT CAME FROM, and no pattern match on the bytes recovers either fact once a caller has flattened it into a string. A second version took provenance as a CALL TIME argument, which is a control one mistake defeats. Only the stored value survives contact. The gate now takes the SET of provenance values read from every row a payload was composed from. ONE TENANT ELEMENT POISONS THE WHOLE PAYLOAD, because a public notice with one paragraph of a customer's PWS folded in is a customer's PWS. AN EMPTY SET IS REFUSED, because silence is not permission. A BACKSTOP REMAINS, and its limit is asserted by name rather than assumed away: a caller that MISDECLARES a stripped candidate row is not caught by content scanning, and a test says so explicitly so nobody mistakes the backstop for a guarantee. Only four egress classes may leave the machine: PUBLIC_KNOWLEDGE, PUBLIC_DATA_SUMMARY, ONTOLOGY_SUGGEST, REQUIREMENT_NORMALIZE. NEVER external, enforced by the gate and by tests: candidate rows, resume text, names, emails, phone numbers, tenant identifiers, anything from the eeo schema, RouteRAG and RouteGraph over tenant data, scoring inputs, scoring outputs, slate contents. The gate fails closed to the local plane. Every external call audits backend, class, byte count, and content hash, NEVER content. CURRENT DATA: 6,676 opportunity_records, 1 tracked_opportunity, 5 manifest rows. -------------------------------------------------------------------------------- 10. THE AI LAYER, UNDER SCRUTINY -------------------------------------------------------------------------------- This section is deliberately harder on the AI layer than a sales document would be, because the failure mode of an AI feature in a regulated product is not a bad answer, it is a confident bad answer that someone acts on. THE ARCHITECTURE. Routed, not monolithic. One router picks the cheapest sufficient strategy, defined in orchestrator.go: RouteRefuse unsafe input (EEO, injection) RouteTAG the database must compute (count, sum, aggregate) RouteRAG retrieve the tenant's candidates and narrate RouteDirect answer from stable rules in context (CAG), no retrieval RouteGraph walk a cited graph evidence path RoutePlan bounded plan and execute over closed intents THE REAL SHAPE OF THE CODE, by size, which tells you where the weight is: graph_route.go 835 planner.go 841 tag.go 798 mag.go 642 curation.go 655 orchestrator 524 graph_market.go 488 teaching.go 446 graph_teaming 403 plus graph_lifecycle, graph_agency, graph_loop, graph_skill, graph_clearance, graph_bench, capture_readiness, knowledge, memory, safety, suppression, vectorguard, egress, feed WHAT IS GENUINELY STRONG RAG, the hybrid retrieval. pgvector cosine kNN fused with tsvector rank by Reciprocal Rank Fusion (k=60), IN SQL. This is the best piece in the layer. It now spans TWO corpora, the tenant's candidates and the public opportunity catalog, and the detector yields to any bench noun so a question touching both planes keeps its candidate corpus rather than being hijacked by the market one. Fusion in SQL rather than in Go means one query plan, one round trip, and no reranking layer to drift. THE CLOSED INTENT REGISTRY. 80 curated, parameterised, read only intents in tag.go. The model selects an intent NAME. It never authors SQL, never authors parameters, and never sees a query planner. THIS IS A SECURITY PROPERTY, NOT A MISSING FEATURE, and it is the single most important decision in the layer. Every NL to SQL system is one prompt injection away from an arbitrary read; this one is not, because there is no code path from model output to SQL text. THE VERIFIER. A faithfulness gate: model prose ships ONLY if the verifier confirms it against the retrieved evidence, otherwise the user gets the deterministic rendering of the same evidence. It FAILS CLOSED on a parse error. This is what makes the layer safe to put in front of a recruiter: the worst case is a plainer answer, not a wrong one. THE POLICY STACK. EEO prohibition on the question itself, read only SQL guard, table allowlist, stacked statement rejection, k anonymity suppression. A federation audit widened the protected noun matching beyond bare terms to close proxies, which is the part most implementations miss. WHAT IS REAL BUT SHALLOWER THAN IT SOUNDS GraphRAG. Recursive CTE traversal, depth capped, cycle guarded, across 20 graph files covering agency, bench, clearance, lifecycle, loop, market, route, skill, and teaming. It is real graph traversal over real relational data with real citations. It is NOT a graph database, there is no learned embedding of the graph, and the traversals are hand written per domain. That is a reasonable engineering choice and it does mean "GraphRAG" here means "parameterised recursive SQL with provenance", which is less than the term implies elsewhere. PAG, the planner. K=3 self consistency, DAG execution, real data dependency chaining between intents. 841 lines. The plan space is bounded by the same closed intent registry, so it cannot plan its way to something the registry does not already permit. That bound is what makes it safe and also what caps how clever it can be. KAG and OAG. 30 cited GovCon knowledge cards plus O*NET, NICE, PSC, and CALC ontologies. Cited is the operative word. But 30 cards is a small corpus and curation is a manual, operator only, two step approve then verify process. It is trustworthy and it is not large. WHAT IS SCAFFOLDED, OFF, OR HONESTLY ABSENT The teaching signal channel. missionMATCH emits contents free craft signals. PANTHEON does not learn from them: the gateway VALIDATES a signal and then DISCARDS it. The working federation path is the knowledge feed harvest, not the teaching channel. Anyone reading "teaching loop" should read "built, validated, and currently a no op at the consumer". Federated differential privacy. Scaffolded and OFF. The Gaussian sampler returns ErrNotImplemented. It is a placeholder with a good shape, not a capability. The external OpenAI backend. Built, boot guarded (enabled with no secret exits 1, proven against the live gateway), and currently pointed at the LOCAL model. REQUIREMENT_NORMALIZE has therefore never executed against OpenAI end to end. Enabling it is a config change protected by the boot guard, not new code, but the end to end path is UNPROVEN. DELIBERATELY ABSENT, and these are decisions, not gaps: Self-RAG needs a fine tuned critic; incompatible with a stateless commodity plane and the no Python rule. Web retrieval must not happen with CUI. NL to SQL replaced by the closed registry, on purpose. Multimodal, vision no use case in a text domain. THE SCRUTINY THAT MATTERS MOST 1. The layer's safety rests on the verifier and the closed registry, and both are code paths, not model behaviour. That is the right place to put trust. 2. The EEO prohibition operates on the QUESTION. A question that never names a protected attribute but correlates with one is not caught by it. The real defence there is that demographics are in a schema the query role cannot read at all, which is architectural rather than heuristic. That is the stronger guarantee and it should be the one cited. 3. Nothing in this layer can write. Every intent is read only and the guard enforces it. The AI cannot change a score, a stage, or an entitlement. 4. The inference plane is a SEPARATE stateless Go binary on another machine, bearer authenticated. The FIPS API binary never hosts a model; it speaks HTTP. So a model process crash cannot take the API down and a model cannot be reached without the token. 5. UNPROVEN AT SCALE. Every claim above is proven by tests and by small live checks. No part of this layer has served production traffic at volume, because production has five users and 11 candidates. -------------------------------------------------------------------------------- 10A. THE LEARNING BOUNDARY, THREE DOORS AND NO FOURTH -------------------------------------------------------------------------------- A standing rule about what INGESTION is allowed to change, recorded 28 July 2026 as the corpus began to grow at scale. INGESTION MAY OPEN EXACTLY THREE DOORS: 1. THE CORPUS new documents, chunks, notices, attachments 2. THE EMBEDDINGS new vectors over that corpus 3. ONTOLOGY SUGGESTIONS candidate skills and adjacencies PROPOSED for curation THERE IS NO FOURTH DOOR. Ingestion never alters scoring weights, never alters the band thresholds, never alters the clearance hierarchy, and never promotes an ontology suggestion into the live ontology by itself. WHY IT IS WRITTEN DOWN. The scoring engine is an AEDT under NYC LL144 and OFCCP. Its weights are frozen, diffed, and exhaustively tested precisely so a customer can point at one number and say what produced it. A pipeline that learned from the market and adjusted those weights would produce a scoring function nobody could reproduce, explain, or audit, and it would do it silently, one federal document at a time. The failure would not look like a bug. It would look like the numbers slowly changing. DOOR 3 IS THE ONE THAT LOOKS SAFEST AND IS NOT. An ontology that grows itself changes which candidate skills match which required skills, which changes the Skills component, which changes the score. So a SUGGESTION is data, a PROMOTION is an operator action by a named human, and the gap between them is load bearing. cmd/promote-ontology exists for exactly that gap. HOW IT IS ENFORCED TODAY, honestly: by the frozen engine diff against e74fd2e asserted EMPTY at every drift check, by ontology promotion being a separate operator binary, and by nothing else. It is a rule with a DETECTOR, not a rule with a LOCK, and it is named that way so nobody mistakes one for the other. -------------------------------------------------------------------------------- 11. FEDERATION RELATIONSHIP TO PANTHEON -------------------------------------------------------------------------------- ONE WAY, by design. missionMATCH --publishes--> PANTHEON missionMATCH is a standalone product, NOT an organ of the federation. It is not in ORACLE's registry, nothing routes tasks into it, and it has no knowledge that any consumer exists. GET /knowledge/manifest declares federation_member:false, routable:false, as DATA not prose GET /knowledge/cards the whole curated public set in one pull Both sit OUTSIDE /api, because the public vhost proxies only /api/ and /healthz. They are reachable across the tailnet, not from the internet, and a bulk pull does not spend the API rate limit real traffic depends on. PANTHEON harvests hourly through curator-db.sh, content addressed and idempotent, alongside codex-lore and seferim-events. WHY PUBLISH RATHER THAN JOIN: a registered organ is DELEGATED to, and the orchestrator needs it reachable every time. A harvested feed is ABSORBED, and the consumer knows the material afterwards with missionMATCH offline or gone. Learning is what survives the source going away. -------------------------------------------------------------------------------- 12. FILE ARCHITECTURE -------------------------------------------------------------------------------- missionmatch/ | +-- cmd/ 36 binaries | +-- api/ THE SERVER. Config, FIPS guard, pools, | | modules, routes. ~720 lines, all wiring. | +-- megamind-gateway/ stateless inference proxy (runs on M4) | +-- provision-org/ create an org and its first owner | +-- provision-tenant/ create a NEW empty tenant database | +-- register-tenant/ adopt an EXISTING database into the directory | +-- migrate-all-tenants/ fan out migrations across control plane and | | every active tenant (see Section 14) | +-- sync-tenant-identity/ copy org and users into a tenant DB | +-- sam-sync, opp-sync, awards-sync, rates-sync, oews-national-sync, | | ontology-sync, missionclass-sync, icims-sync external ingestion | +-- opportunity-scope-normalize model normalization into cited drafts | +-- aioe-run, aioe-sim, aioe-backfill adaptive weight optimization | +-- train-model, eval-model, eval learned model lifecycle | +-- teach-aggregate contents free craft signals | +-- fairness-snapshot adverse impact monitoring | +-- embed-backfill, verify-vector-model, verify-resolver | +-- alert-sweep, staffing-proactive-sync, demo-seed, brain-probe, | import-candidates, import-bench, promote-ontology, tag-missions | +-- internal/platform/ 31 cross cutting packages | +-- config/ ALL configuration and validation. Cloud choice | | is CONFIG, never code. | +-- database/ pool construction, pgvector codecs per | | connection, role assertion failing BOOT closed | +-- tenant/ THE CORRECTNESS BOUNDARY. RunInTenantTx, the | | org GUC, the Router interface, Principal | +-- tenantpool/ bounded per tenant registry: LRU evict, | | singleflight, ping before cache, refcount pin, | | typed errors that never fall back | +-- directory/ tenant_directory access | +-- identity/ seed org and users into a tenant DB | +-- secrets/ Store (named) and Resolver (per tenant refs, | | TTL cached, env backend MM_TENANT_DSN_<REF>) | +-- security/ rbac, capabilities, tools, CSRF, password | | hashing, TOTP, session tokens, RequirePlatform | +-- audit/ append only trail, System() and OnTx() | +-- inference/ typed client, circuit breaker, bounded retries | +-- scrub/ egress payload classes, enforced twice | +-- csvsafe/ formula injection escape | +-- federated/ differential privacy scaffolding (OFF) | +-- embeddings/, magstore/, learn/, eval/, aioe/, docextract/, extraction/ | +-- samgov/, samawards/, bls/, marketintel/, forecast/, connector/ | +-- ratelimit/, obs/, storage/, ontology/ | +-- internal/modules/ 24 domain modules | | each: handler.go, service.go, dto.go, repo.go | +-- auth/ login, MFA, sessions, invites, users, roles, | | tool entitlement, self service profile | +-- matching/ THE ENGINE plus screen and slate cores | | +-- engine/ pure deterministic scoring, decimal, FROZEN | +-- screenmatch/ slatematch/ missionmatch/ recruitmatch/ | +-- recruiting/ THE DESK, 40 routes, the state machines | +-- opportunities/ public cache PLUS the tenant capture layer | +-- commandcenter/ mission readiness aggregation | +-- ai/ orchestrator, retrieval, planner, 20 graph | | files, memory, knowledge, safety, suppression, | | vectorguard, curation, teaching, egress, feed | +-- eeo/ adverse impact, SEGREGATED | +-- governance/ retention, AEDT inventory, model registry | +-- aioe/ adaptive weights | +-- opportunity_intelligence/, awards/, wages/, sourcing/, staffing/, | alerts/, bidoutcomes/, ontology/, termalias/, org/, federalsignal/ | +-- db/ | +-- migrations/ 79 files, head 0080. The ONLY way schema | | changes. 0020 is absent from the sequence; | | numbers are never reused. | +-- migrations_eeo/ SEPARATE set, separate version table, so sqlc | | never models the eeo schema | +-- bootstrap/ cluster roles | +-- queries/ sqlc source SQL | +-- frontend/src/ 87 files, 13,217 lines | +-- App.tsx routes + ToolGuard entitlement redirect | +-- main.tsx ErrorBoundary > QueryClient > Router | +-- components/ AppShell (tool switcher, nav, signed in | | identity), ui, ErrorBoundary, ExecutiveCards | +-- lib/ api, auth, AuthContext, can (capabilities, | | tools, the two disabled reasons), homeTool, | | queries, types | +-- screens/ Login, AcceptInvite, Admin, Settings, | | Compliance, Requirements, TimeZonePanel, | | NotFound | +-- tools/ 22 views across the four products (Section 7) | +-- docs/ CLAUDE_CODE_BUILD_DIRECTIVE (the work order), | DIRECTIVE_AMENDMENTS_CONSOLIDATED, | DIRECTIVE_AMENDMENT_6, BUILD_STATE (the append | only ledger), AI_RESEARCH, STACK_DECISIONS, | MODEL_CARD, runbooks +-- ops/m4/ gateway lifecycle +-- scripts/deploy.sh encodes three SILENT failure modes -------------------------------------------------------------------------------- 13. HOW IT IS BUILT -------------------------------------------------------------------------------- NON NEGOTIABLE RULES (CLAUDE.md): 1. No Python anywhere. Go backend, TypeScript frontend, bash scripts. HTML written by hand, never generated by a program. 2. No dashes in written output. Hyphens only inside URLs, HTTP header names, CLI flags, and code identifiers. 3. Every API key stays on the server. Root owned 0600, never in the repo, never in the browser bundle. 4. Clearance is "clearance intelligence", never "verified". THE BUILD PROGRAM. Work runs under docs/CLAUDE_CODE_BUILD_DIRECTIVE.md, phase locked: work only on the lowest incomplete phase, never start phase N+1 until every item in the phase N gate is verified and recorded in docs/BUILD_STATE.md. That ledger takes only VERIFIED items; aspirations never enter. Phase 0 and Phase 1 complete with gates passed, Phase 2 current, Phases 3 through 6 not started. TRACK U (identity and access) ran in parallel and is complete. Tasks T1 and T2 are standalone client site work outside the phase gates. FROZEN AND UNTOUCHABLE: internal/modules/matching/engine, db/migrations_eeo, every existing migration file, generated sqlc output, append only audit semantics. ENGINEERING INVARIANTS: organization_id, forced RLS, and composite indexes leading with organization_id, on every tenant table. ON DELETE SET NULL on a composite FK MUST use the column list form. The bare form tries to null organization_id, which is NOT NULL, making the referenced row undeletable. Migration 0053 repaired 24 of these. audit_logs is append only. UPDATE and DELETE revoked, triggers enforce it. A down migration may drop what its up added but may NOT delete rows the application authored. Several downs REFUSE with a count. Widen a CHECK from the CURRENT constraint, never from an old migration's vocabulary, or a later migration's additions are silently dropped. Caught twice. Role enum values are EXTENDED, never renamed, never removed. VERIFICATION METHOD: Reproduce the defect against a live database FIRST, fix, verify against the same database, verify end to end through the live AUTHENTICATED API, then look at the rendered screen. Concurrency proven by RACING it: 16 concurrent stage transitions elected one winner; 8 racing claims one owner; 8 placements into one seat one placement; 8 concurrent promotions of one draft one requirement. Artifacts are GREPPED, not trusted. A bundle is checked for the strings it must and must not contain, because a source tree that looks right can still build the wrong thing. This caught a Phase 1 navigation link riding into a production bundle on 28 July. A NEGATIVE RESULT IS ONLY EVIDENCE WHEN THE INSTRUMENT IS KNOWN TO WORK. Added 28 July after being burned twice in one day (Section 16). A check that can pass by doing nothing needs a positive control. THE MERGE GATE: make build-test-gates runs gofmt, go vet, the full unit suite, the security gates, and a clean frontend production build. Green at this revision. -------------------------------------------------------------------------------- 14. DEPLOYMENT AND ITS REAL FAILURE MODES -------------------------------------------------------------------------------- Every item below is something that has actually gone wrong. BUILD CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOFIPS140=v1.0.0 go build -trimpath API DEPLOY Stage to /tmp, COMPARE SHA256, stop, swap, start, poll healthz. BOTH nodes must get the same binary or the failover serves two different answers. On 28 July the second node briefly ran a binary with no operator role while the first had it, which would have given the operator zero capabilities on one node and everything on the other. The correct response is to mark the stale node DOWN in the nginx upstream and reload BEFORE shipping anything further. SECOND NODE megamind-agi has no direct SSH and refuses publickey. Use PASSWORD authentication to the WINDOWS host josep@100.69.120.61, scp there, then run a STAGED BASH SCRIPT through wsl. Multi line quoting through wsl breaks; stage a file rather than inlining. WSL sudo is NOPASSWD. MIGRATIONS Use cmd/migrate-all-tenants, NOT the goose CLI (which pulls heavy unrelated drivers absent from go.sum). It EMBEDS migrations with go:embed, so an edited .sql does NOTHING until the migrator binary is REBUILT. CRITICAL DEFECT, found AND FIXED 28 July 2026, recorded because the failure mode is worth knowing. The tool built each tenant DSN with swapDB(controlDSN, dbName), swapping only the DATABASE NAME and IGNORING the db_host and db_port that tenant_directory exists to carry. A tenant on another host was never reached: it connected to a database of the same name on the CONTROL PLANE host, migrated it a second time, and printed APPLIED for both. Every run reported success while the production control plane fell TWELVE migrations behind the tenant database. The fix builds the target from the directory row, host and port and name together. MM_TENANT_MIGRATOR_DSN_<REF> overrides for a tenant whose credential differs, folded by the same rule internal/platform/secrets uses. A row with no host is an ERROR, never a guess, and a target that cannot be addressed is reported FAILED and carried into the exit code rather than dropped from the summary. Five tests pin it, including one using an identical database name on both hosts, which is the shape that made the original bug invisible. THE GENERAL LESSON: a fan out tool that cannot reach a target must FAIL, never silently succeed against something else. Verify the version in EVERY database regardless of the summary. FRONTEND npm run build, ship dist/assets, then rewrite ONLY the two asset hashes in the live index.html. Overwriting it destroys injected SEO lines. Verify the line count is unchanged. ENV FILES sudo tee TRUNCATES. Stage to /tmp then cp, and assert the result is non empty and not smaller before replacing. POST DEPLOY Re prove the build feature routes DARK and run a zero 5xx sweep, sampled enough times that both pool members answer. AND INCLUDE AN AUTHENTICATED LEG: a sweep of unauthenticated paths cannot see a defect behind the session gate, which is exactly what hid a 500 on 28 July. PRODUCTION BINARIES ARE NOT REPOSITORY HEAD. HEAD carries Phase 1 and 2 build features that must stay dark until Gate 6. The production binary is built in a worktree at the pre build baseline e74fd2e with only the approved track's files overlaid and cmd/api/main.go hand resolved. Any deploy before Gate 6 must be built the same way and the artifacts grepped to prove it. -------------------------------------------------------------------------------- 15. OBSERVABILITY -------------------------------------------------------------------------------- LOGGING Structured slog, JSON, request id, method, route, status, latency, bytes on every request. Debug in development, info in production. PII is never logged. METRICS /metrics outside /api so a scrape never spends the API rate limit. Feeds database pool gauges so connection saturation is visible. Unauthenticated by design, firewalled to the scraping network. HEALTH /healthz per node. nginx passive health checks handle failover. AUDIT audit_logs is the operational record as well as the compliance one: logins, failures, lockouts with source spread, permission changes, identity changes, exports, every material write through OnTx. ALERTS The alerts module plus alert-sweep. SCHEDULED mm-sam-sync.timer runs daily SAM.gov ingestion on Bubbles. WHAT RUNS ON A TIMER, all installed 28 July 2026 and each proven by an induced failure where one was possible: 02:45 megamind-agi mm-cp-backup control plane dump, streamed through gpg into ssh, pushed to Bubbles 03:05 Bubbles mm-db-backup tenant and staging dumps, ingest of the pushed artifact only after it is proven to decrypt, manifest, prune to 14 daily and 8 weekly every 5 min Bubbles mm-watch public site, BOTH API nodes named individually so a single node failure is not masked by the pool, and 5xx since the last run. Alerts on a TRANSITION, once when a problem starts and once when it clears. hourly megamind-agi mm-identity-sync control plane to every active tenant, reconciled after each run rather than trusting the exit code Delivery is mm-alert.sh through Gmail SMTP, reusing the app password the form handlers already use. The systemd OnFailure notifier routes through it. A TIMER THAT IS NOT ON THAT LIST AND FAILS EVERY DAY, found 28 July 2026 at the Phase 2 drift check and recorded as finding D1: 05:16 Bubbles mm-fairness-snapshot FAILING SINCE INSTALLATION It exits 1 with "set MM_COMPLIANCE_DATABASE_URL (the compliance role DSN, the only path to the eeo schema)". The unit reads /etc/missionmatch/api.env and that file does not carry the variable. Its sibling on the control plane node, /etc/missionmatch/db.env, does, and that DSN authenticates, so the repair is configuration and not code. WHY THIS ONE MATTERS MORE THAN A FAILED TIMER USUALLY DOES. The adverse impact snapshot is the AEDT compliance artifact this product exists to provide: the selection rates and four fifths ratios a customer needs for an LL144 or OFCCP audit. The claim that missionMATCH supplies it is currently true of the code and FALSE of the running system. ALERTING COVERAGE IS PARTIAL, which is why the above survived, recorded as finding D2. Exactly TWO units on Bubbles carry OnFailure, bubbles-cert-check and mm-db-backup, both wired during Track H item 3. That work fixed the alerting PATH and proved it by breaking things; it did not sweep every existing unit onto that path. A failing unit outside those two is silent. This is the same shape as the decorative alerting already found once: the mechanism works, the coverage does not, and partial coverage is harder to notice than a mechanism that is plainly broken. Both are production changes and both are QUEUED rather than fixed, because the Phase 2 lock holds. One deploy closes both. REMAINING GAPS: no metrics scraper and no dashboard. That is a deliberate ordering, not an oversight: a phone that buzzes was worth more than a graph nobody is watching at three in the morning. -------------------------------------------------------------------------------- 16. THE 28 JULY 2026 INCIDENT RECORD -------------------------------------------------------------------------------- A full account, because the corrections are more instructive than the features. INCIDENT 1: THE STAGING ROLE COULD NOT AUTHENTICATE AT ALL FOUND Provisioning a Track U repro account. Invite acceptance returned 500. CAUSE The isolated role missionmatch_staging_app was created with TABLE grants mirrored and FUNCTION grants not. It held EXECUTE on ZERO of the nineteen SECURITY DEFINER auth functions. IMPACT No login, no invite acceptance, no session validation on staging from the moment the role was introduced. It also means an earlier ledger claim that Track U items were "proven on staging" could not have been an end to end check, because no authenticated request could complete. That claim was withdrawn. FIX The nineteen missing grants mirrored into missionmatch_staging only, generated by comparing the two roles rather than hand listed. VERIFIED 0 of 188 functions still missing. The staging role is STILL refused on missionmatch, tenant_alpha, and tenant_beta. Production grants unchanged at 151 of 152. Production site 200. INCIDENT 2: THE BY RULE TOOL FIX NEVER REACHED THE BROWSER CAUSE SessionInfo re read the RAW rows of user_tool_access instead of the principal's already widened set. IMPACT A tenant superuser with no grant rows was widened for every server side check and still received tools:[], which hides the entire navigation and locks every entitlement checkbox. The reported symptom surviving its own fix, one layer up. FIX SessionInfo returns the principal's tools. INCIDENT 3: PATCH /me/profile ANSWERED 404 ON THE CALLER'S OWN ACCOUNT CAUSE writeProfile, getProfile, and roleOf ran on a bare pool connection with no app.current_org_id. users carries forced RLS, so every statement matched zero rows. LESSON The explicit "WHERE organization_id = $1" predicate LOOKS like it does the scoping and does not. RLS filters first. FIX All three run inside RunInTenantTx. The same class of bug was introduced in AcceptInvite the same day and fixed the same way. INCIDENT 4: A PHASE 1 NAVIGATION LINK NEARLY SHIPPED TO PRODUCTION CAUSE Copying HEAD's AppShell.tsx wholesale into the production build dragged a /slate/capture link with it. CAUGHT BY Grepping the BUILT BUNDLE, not the source tree. FIX That file rebuilt from the baseline with only the Track U change. INCIDENT 5: THE PRODUCTION TOPOLOGY WAS RECORDED WRONG, AND IT BROKE PRODUCTION CAUSE The ledger described production as missionmatch on M4 5432. That is the TENANT data plane. The CONTROL PLANE is missionmatch on megamind-agi 5433, and it was at v68, twelve migrations behind. IMPACT The Track U binary selects title and phone from users; those columns were added by 0079, applied to the tenant database. On the control plane they did not exist, so GET /api/auth/session WOULD have returned 500 to the first person to sign in. SCOPE Stated precisely: the journal shows ZERO 5xx and ZERO ERROR lines across the entire window between deploy and fix. Nobody logged in while it was broken. The defect was real and had no victim. WHY IT WAS MISSED The post deploy zero 5xx sweep used only unauthenticated paths, which answer 403 before the failing handler runs. A sweep with no session cannot see a defect behind the session gate. FIX Control plane snapshotted and migrated v68 to v80. VERIFIED title and phone present, remap audit trail written on the authoritative database with all three superuser grants named, the promoted account's sessions revoked, login returns 401 for a wrong password rather than 500, zero 5xx across 21 requests. ROOT CAUSE The migrate-all-tenants swapDB defect (Section 14). FIXED, with five tests, and proven against the real two host topology: the fixed tool now targets the tenant's own host and, when credentials did not match, FAILED LOUDLY instead of quietly succeeding elsewhere. DRIFT NOW CLOSED. Control plane v80, tenant v80, staging v80, each verified by querying that database directly rather than trusting the summary. INCIDENT 6: TWO OF MY OWN FINDINGS WERE WRONG 6a I reported Patricia Cox could not sign in, with no password credential and no live invite, and built a Resend invitation button on that basis. I had read the TENANT copy of users, which is non authoritative and was stale. On the control plane she is ACTIVE with a password and four tool grants; she has simply never logged in. Production has FIVE accounts, not three. The button is still correct work (amendment 6 lists resend invitations and nothing called the endpoint), but the urgency was based on a bad read. 6b I reported MM_TENANT_DSN_TENANT_ACME missing from production and put it in the risk register as a probable breakage. It is defined on line 23 of api.env and present in the running process. The claim came from a grep run through two layers of shell quoting that silently matched nothing. WITHDRAWN, and the data plane is now PROVEN working instead: connecting with the exact DSN the running process holds reaches the tenant database as missionmatch_app, that role is NOBYPASSRLS, a read of candidates with no org GUC returns 0 rows, and the same read with the GUC set returns 11. INCIDENT 7: THE LOGIN INSTRUMENT LIED FOR WEEKS, and a design partner caught it REPORTED She said she had logged in and the control plane showed "never signed in". MEASURED She was right, and it was worse than one account. FOUR of five accounts held real ACTIVE sessions while the screen said none had ever signed in, and the fifth was STALE BY A WEEK. CAUSE internal/modules/auth/service.go read _, _ = db.Exec(ctx, `SELECT auth_touch_last_login(, )`, ...) The $1 and $2 PLACEHOLDERS WERE MISSING FROM THE SOURCE, almost certainly stripped by an edit made through a shell that expanded the dollar signs away. Postgres rejected it as a syntax error on EVERY sign in, and both return values were discarded, so it failed silently. This is the no scripts rule demonstrated in production. RULED OUT by direct test, not by reading: the function works when called as a superuser, the app role holds EXECUTE, and RLS is not the cause because the function is SECURITY DEFINER owned by a BYPASSRLS role. ONE OF MY OWN TESTS WAS INVALID and is recorded as such: subselects run as the app role returned NULL under RLS, so the function's NULL guard returned early and it looked like a failure that was not one. FIX Placeholders restored, and the failure is now LOGGED at ERROR including the zero rows case, which Postgres does not treat as an error and which is exactly what a silent no op looks like. It still does not fail the login, because recording a sign in is bookkeeping and denying entry over bookkeeping would turn a reporting defect into an outage. Swallowed deliberately is different from swallowed

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