Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / docs/ARCHITECTURE.md |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 9bde0f9a74b89d01980fa658e5253acda7528d0c |
| Branch | per-tenant-routing |
| Path or archive member | docs/ARCHITECTURE.md |
| Original SHA-256 | 0f4710043e96496229a23436b048daecee7ef4ace2e3a1b9dadc6851ebe863d0 |
| Git blob SHA | 6c8f4f18798ca8451b26ac20897cede96c3a44b6 |
| Reading-copy SHA-256 | 0f4710043e96496229a23436b048daecee7ef4ace2e3a1b9dadc6851ebe863d0 |
Every recorded occurrence
These 3 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / docs/ARCHITECTURE.md | per-tenant-routing | 9bde0f9a74b89d01980fa658e5253acda7528d0c | Open original |
| Janady13/missionmatch / docs/ARCHITECTURE.md | deploy-and-ops | bdacd9d0b4d5998d25fc74bf4007f4c3ec538c7a | Open original |
| Janady13/missionmatch / docs/ARCHITECTURE.md | per-tenant-routing | 9bde0f9a74b89d01980fa658e5253acda7528d0c | Open original |
Recovered source transcript
Download complete source text ↓222 lines · 12.8 KB
# missionMATCH Architecture Blueprint (live)
A Cleared Workforce Intelligence Platform for US government contractors. It serves one loop:
**Requirement → Candidate Intelligence → Match Scoring → Ranked Slate → Proposal Readiness**, exposed as
three tools over one deterministic engine, with an AI brain that narrates but never scores.
Generated from the live codebase: 233 Go files, 22 modules, 18 platform packages, 19 migrations, 12 binaries,
a React frontend. The deterministic engine is at v1.1.0 (semantic skill threshold 0.62, registered in the
AEDT model registry). A companion rendered diagram is at `docs/architecture.svg`.
Non negotiables baked into the structure: no Python, no cgo, the API binary stays `CGO_ENABLED=0
GOFIPS140=v1.0.0` with `GODEBUG=fips140=on`; the deterministic engine is the floor (no model in any scoring
or eligibility decision); EEO data is physically and privilege isolated and is never a matching input;
multi tenancy is Postgres Row Level Security with a per request org GUC; every consequential action writes an
append only audit row; cloud specific I/O (storage, embeddings, secrets, identity) sits behind ports so AWS
GovCloud and Azure Government are configuration, not code.
## 1. System context
```mermaid
flowchart TB
subgraph CLIENT["Browser SPA (Vite + React 19 + TS, Tailwind, TanStack Query)"]
SW["Tool switcher: screenMATCH /screen · slateMATCH /slate · missionMATCH /command · Compliance · Auth"]
end
EDGE["nginx (Bubbles, Debian) · TLS 1.2+ · reverse proxy"]
subgraph API["mm-api · single static Go binary · FIPS 140-3"]
MW["Pipeline: RequestID, Recoverer, metrics, Timeout, RateLimit, Session+MFA, CSRF, RBAC"]
CORE["Deterministic core: tool routers to matching.Service to engine.ScoreCandidate (the floor)"]
BRAIN["AI brain: orchestrator CAG/RAG/TAG/KAG + memory + faithfulness gate + vector gate"]
OTHER["Command Center · Staffing W3 · Governance/AEDT · EEO · Auth/MFA · Market catalogs"]
end
DB[("PostgreSQL 16 + pgvector (HNSW) · RLS forced · 3 roles")]
PLANE["MEGAMIND inference plane (Ollama: bge-small, llama3.1, bge-reranker) · stateless"]
FED["Free federal data: SAM.gov · USASpending · BLS OEWS · GSA FCO · PeopleDataLabs"]
CLIENT --> EDGE --> API
MW --> CORE
MW --> BRAIN
MW --> OTHER
CORE <--> DB
BRAIN <--> DB
BRAIN --> PLANE
OTHER <--> DB
FED -->|daily systemd sync| DB
```
## 2. The one engine, three tools principle
`engine.ScoreCandidate(ctx, Candidate, Requirement, SkillMatcher) MatchResult` in
`internal/modules/matching/engine` is the single source of every match score. It is pure: no DB, no I/O, no
clock, no randomness, all arithmetic in `shopspring/decimal` so the same inputs always yield byte identical
scores and explanations (the AEDT reproducibility asset). It reads no demographic field, by type.
```
Match = Clearance*0.25 + Skills*0.25 + Certifications*0.15 + CustomerExperience*0.15
+ Experience*0.10 + LocationAvailability*0.10 (weights frozen, sum to 1.00)
Bands: Green >= 90 (Proposal Ready) · Yellow 75 to 89 (Potential) · Red < 75 (Recruiting)
Skills: exact match first, then SEMANTIC over stored bge HNSW vectors at cosine >= 0.62 (v1.1.0)
Output: per component trace + human readable rationale + gap summary + ModelVersion stamp
```
`screenMATCH`, `slateMATCH`, and `missionMATCH` are thin HTTP namespaces that mount the same
`matching.Handler` (`ScreenRoutes`, `SlateRoutes`, `ReadRoutes`, `IntelRoutes`, `MissionRoutes`), so the same
candidate against the same requirement shows the same number in all three. `commandcenter` and `staffing`
read the frozen `candidate_evaluations` the engine persists; they never recompute. A frozen contract test
pins the weights, bands, threshold, and ModelVersion so a refactor can never silently drift a number.
## 3. Request lifecycle
```mermaid
flowchart LR
R["HTTPS request"] --> N["nginx TLS"]
N --> P["RequestID, Recoverer, metrics, Timeout 60s, RateLimit/IP"]
P --> S["Session middleware: validate __Host- cookie, MFA satisfied, resolve org+principal"]
S --> C["CSRF double submit"]
C --> B["RBAC RequireCapability (CapSearchRun, CapBrainQuery, ...)"]
B --> T["RunInTenantTx: SET LOCAL app.current_org_id from the VALIDATED session"]
T --> H["handler to service to engine / brain"]
H --> A["append only audit row"]
A --> O["typed JSON response"]
```
No org in context yields zero rows (fail safe). The org GUC is set transaction locally and auto resets at
COMMIT or ROLLBACK, which is the pgx pool correctness rule. A production build cannot compile the dev
`X-Org-ID` header resolver (a build tag split, hard rejected again by config validation), and CI gates it.
## 4. The AI brain (augmented generation, narrates never scores)
`POST /ai/query` (capability `brain.query`) routes a natural language question. The brain may embed, narrate
behind a faithfulness gate, and check faithfulness; it is never in a scoring or eligibility decision.
```mermaid
flowchart TB
Q["question"] --> CL{"Classify"}
CL -->|"demographic or injection"| REF["Refuse (422): ForbidEEO + MentionsProtectedAttribute"]
CL -->|"stable rules"| CAG["CAG: preloaded public rules, no retrieval"]
CL -->|"retrieval"| RAG["RAG: embed query, hybrid pgvector + tsvector, RRF fuse, narrate"]
CL -->|"explicit intent"| TAG["TAG: curated parameterized read only SQL intent (allowlisted, never eeo)"]
RAG --> KAG["KAG: skill adjacency over HNSW (live, no model)"]
RAG --> FG{"Faithfulness gate"}
FG -->|"grounded"| ANS["model prose (rationale_source ai_faithful)"]
FG -->|"not grounded"| DET["deterministic rendering (rationale_source deterministic, still 200)"]
ANS --> AUD["audit aedt.ai.answered (no PII, no prose)"]
DET --> AUD
REF --> AUD2["audit aedt.ai.refused"]
```
Supporting guarantees:
- **Vector gate (enforced re embed).** At boot the API asserts the `skills.embedding` and
`candidates.resume_embedding` columns are vector(384) and re embeds a sample of stored skills with the
configured model; if the stored vectors were made by a different model (the all-minilm versus bge
corruption mode), `/ai/query` returns 503 `vector_model_mismatch` while the rest of the API serves, and it
self heals on the first query after a boot time plane outage.
- **Per tenant memory.** `ai_memory` (episodic and semantic, vector embedded) is RLS scoped, eeo guarded on
write, and wiped on erasure in both the on demand and retention paths.
- **EEO unreachability.** No brain path names the eeo schema; a compile time tripwire walks the ai package
and fails the build if it does.
## 5. Multi tenancy and security model
```mermaid
flowchart TB
subgraph ROLES["Postgres roles"]
APP["missionmatch_app · NOBYPASSRLS"]
MIG["missionmatch_migrator · BYPASSRLS"]
CMP["missionmatch_compliance"]
end
subgraph DATA["one shared database (per tenant DB routing is a sequenced follow on)"]
T["RLS tenant tables: candidates, requirements, slates, candidate_evaluations, staffing_recommendations, ai_memory"]
G["global catalogs (no org_id): skills HNSW, opportunity_records, sam_opportunities, usaspending_awards, bls_wages"]
SEC["secrets OUTSIDE RLS: auth_credentials, auth_sessions, mfa_totp, recovery, invites"]
EEO["eeo schema: candidate_demographics"]
AUD["audit_logs (append only)"]
end
APP -->|org GUC, FORCE RLS| T
APP -->|read| G
APP -.->|no table grant; SECURITY DEFINER fns only| SEC
APP -.->|REVOKE ALL, permission denied| EEO
MIG -->|migrations, sync writes, provisioning| DATA
CMP -->|SELECT public outcomes + eeo, one way to report| EEO
```
- **RLS.** Every tenant table has `organization_id` leading its keys and `FORCE ROW LEVEL SECURITY`. The app
sets `app.current_org_id` per request transaction from the validated session, never a client value.
- **Secrets.** The five secret tables carry no app grant and are reached only through about twenty migrator
owned `SECURITY DEFINER` functions with a locked `search_path`.
- **EEO isolation (absolute).** The `eeo` schema lives in a separate goose track and is not in the sqlc path,
so no Go model is ever generated for it; only `missionmatch_compliance` has grants (SELECT and append only
INSERT); the matching role gets a permission denied. Demographics flow one way into the four fifths adverse
impact report and never into a score.
- **Auth and accounts.** Opaque server side sessions (32 random bytes, stored only as a SHA 256 hash, in a
`__Host-` cookie, two stage pre MFA then active), PBKDF2 HMAC SHA 256 at 600000 iterations with a versioned
pepper, mandatory in house TOTP pinned to SHA 256 with a monotonic replay guard, TOTP secrets AES 256 GCM
encrypted with a key version. Org creation is migrator only provisioning plus invites, no public signup in
this phase.
- **Audit.** `audit_logs` is append only outside RLS, protected by row, statement, and privilege guards;
org scoped events ride the tenant transaction, pre auth security events insert directly and fail closed.
## 6. Schema (migrations 0001 to 0019)
| # | Migration | What it adds |
|------|-----------|--------------|
| 0001 | foundation | organizations, users (composite FKs), audit_logs (append only) |
| 0002 | matching | skills (global HNSW), candidates, requirements, slates, slate_members, the candidate/requirement detail tables |
| 0003 | command_center | opportunity value, requirement labor category and quantity |
| 0004 | command_center_fns | immutable clearance and poly ordinal functions (engine synced) |
| 0005 | sam_opportunities | SAM.gov contract cache (global, outside RLS) |
| 0006 | usaspending_awards | USASpending awards cache (global) |
| 0007 | bls_wages | BLS OEWS regional wage baseline (global) |
| 0008 | external_sourcing | candidate source fields, sourcing_log |
| 0009 | auth | credentials, sessions, MFA, recovery, invites, login attempts + SECURITY DEFINER functions |
| 0010 | aedt_governance | model_version on decisions, anonymized_at, model version registry, AEDT inventory, candidate notices |
| 0011 | opportunity_value_source | value provenance (representative/operator/sam/usaspending) |
| 0012 | clearance_provenance | clearance provenance and verified_at on candidates |
| 0013 | opportunity_records | unified global opportunity feed (SAM, awards, forecasts) |
| 0014 | notice_disclosed_by_fk | composite FK for the notice discloser |
| 0015 | candidate_evaluations | frozen engine result per candidate and requirement (the reconciliation table) |
| 0016 | slate_member_decision_note | human decision note on a slate member |
| 0017 | ai_memory | per tenant episodic and semantic memory, vector(384), erasable |
| 0018 | staffing_recommendations | recommendation_runs and staffing_recommendations (W3) |
| 0019 | model_version_v1_1_0 | registers v1.1.0 (semantic threshold recalibrated 0.80 to 0.62) |
## 7. Deployment topology and the inference plane
```mermaid
flowchart LR
subgraph BUB["Bubbles (Debian, public edge)"]
NGX["nginx TLS"] --> SVC["mm-api (systemd, GODEBUG=fips140=on, /etc/missionmatch/api.env 0600)"]
CRON["systemd timers: sam-sync, awards-sync, opp-sync, rates-sync, staffing-proactive"]
end
subgraph M4["M4 / Thunderport (Apple Silicon, Tailscale 100.94.8.94)"]
PG[("Postgres 16 + pgvector")]
GW["megamind-gateway (launchd) :8090"]
OLL["Ollama (Metal): bge-small-en-v1.5, llama3.1:8b, bge-reranker-v2-m3"]
end
SVC -->|pgx over Tailscale| PG
SVC -->|typed inference client: timeouts, retries, circuit breaker| GW
GW --> OLL
CRON --> PG
```
The gateway is stateless and sees no client identifier on the inference paths; it exposes `/v1/embed`,
`/v1/rerank`, `/v1/generate`, `/v1/faithfulness`, and a scrub guarded `/v1/teach` that persists nothing. The
embeddings provider is a port (fake for dev and tests, plus openai, azure_openai, bedrock, and megamind), so
a cloud swap is configuration. The same `embeddings.SkillEmbedText` defines the skill embed text for both the
backfill and the boot vector gate, so they cannot drift.
## 8. Binaries
`api` (the server), `megamind-gateway` (the inference plane), `embed-backfill` (skills and resume vectors),
`provision-org` and `provision-owner` and `provision-tenant` (account and tenant genesis), and the data sync
jobs `sam-sync`, `awards-sync`, `opp-sync`, `rates-sync`, `import-candidates`, and `staffing-proactive-sync`.
## 9. Responsible AI (AEDT) guarantees
This is an Automated Employment Decision Tool. The platform supplies the data and controls for the deploying
employer's bias audit; it does not transfer their liability. Every score is explainable (per component trace,
rationale, gaps, a recordable decision trace) and reproducible (decimal, frozen weights, stamped ModelVersion
registered in `aedt_model_versions`). Humans approve or reject every slate member and every staffing
recommendation; nothing is auto rejected. Demographic data is never a feature or proxy. The four fifths
adverse impact report runs only on the isolated compliance role. A model card lives at `docs/MODEL_CARD.md`.
Mathematical records from this source
0102
2. The one engine, three tools principle
This relation defines Match in the source section “2. The one engine, three tools principle”. It specifies the displayed relationship between the named quantities or parameters.…
2. The one engine, three tools principle
This relation defines Match in the source section “2. The one engine, three tools principle”. It specifies the displayed relationship between the named quantities or parameters.…