Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / cmd/api/main.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 39df94f92b2a33f852481fe1954dabed841524bb |
| Branch | w0-aedt-compliance |
| Path or archive member | cmd/api/main.go |
| Original SHA-256 | b160ba0bbf7b262cd8e955d8b970391a2477036882be5a1e375d8b885d549ce2 |
| Git blob SHA | 655e0716fdedcae45ccf6f0b3435f0fb68ebbc75 |
| Reading-copy SHA-256 | b160ba0bbf7b262cd8e955d8b970391a2477036882be5a1e375d8b885d549ce2 |
Recovered source transcript
Download complete source text ↓240 lines · 9.5 KB
// Command api is the missionMATCH HTTP server entrypoint.
//
// It wires configuration, the FIPS startup guard and self test, the Postgres pool (NOBYPASSRLS app
// role), the embedding provider, the authentication module, and the tenant scoped API. Cloud and
// provider selection are configuration (the portability mandate); no cloud SDK is imported here.
package main
import (
"context"
"crypto/fips140"
"crypto/pbkdf2"
"crypto/rand"
"crypto/sha256"
"encoding/json"
"log"
"net/http"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/missionworkforce/missionmatch/internal/modules/auth"
"github.com/missionworkforce/missionmatch/internal/modules/awards"
"github.com/missionworkforce/missionmatch/internal/modules/commandcenter"
"github.com/missionworkforce/missionmatch/internal/modules/eeo"
"github.com/missionworkforce/missionmatch/internal/modules/governance"
"github.com/missionworkforce/missionmatch/internal/modules/matching"
"github.com/missionworkforce/missionmatch/internal/modules/opportunities"
"github.com/missionworkforce/missionmatch/internal/modules/sourcing"
"github.com/missionworkforce/missionmatch/internal/modules/wages"
"github.com/missionworkforce/missionmatch/internal/platform/audit"
"github.com/missionworkforce/missionmatch/internal/platform/config"
"github.com/missionworkforce/missionmatch/internal/platform/database"
"github.com/missionworkforce/missionmatch/internal/platform/embeddings"
"github.com/missionworkforce/missionmatch/internal/platform/security"
"github.com/missionworkforce/missionmatch/internal/platform/tenant"
)
func main() {
cfg, err := config.Load()
if err != nil {
log.Fatalf("config: %v", err)
}
// FIPS startup guard: in a FIPS deployment, refuse to start with crypto outside the validated module.
if cfg.RequireFIPS && !fips140.Enabled() {
log.Fatalf("FIPS required but OFF, build with GOFIPS140=v1.0.0 and run with GODEBUG=fips140=on")
}
// FIPS self test: actually derive a PBKDF2 key at the configured cost under the active module and
// fail closed if it errors, so a broken crypto path is caught at boot, not at first login.
if err := fipsSelfTest(); err != nil {
log.Fatalf("FIPS self test (PBKDF2 HMAC SHA 256) failed: %v", err)
}
log.Printf("missionMATCH starting: env=%s cloud=%s fips_enabled=%v module=%s",
cfg.Env, cfg.Cloud, fips140.Enabled(), fips140.Version())
ctx := context.Background()
var db *tenant.DB
if cfg.AppDatabaseURL != "" {
pool, err := database.NewPool(ctx, cfg.AppDatabaseURL)
if err != nil {
log.Fatalf("db pool: %v", err)
}
// Fail closed unless this pool is the NOBYPASSRLS app role, so a swapped or over privileged DSN
// can never silently bypass RLS.
if err := database.AssertRole(ctx, pool, "missionmatch_app"); err != nil {
log.Fatalf("app pool role check: %v", err)
}
db = tenant.New(pool)
defer db.Close()
} else {
log.Printf("WARNING: MM_DATABASE_URL unset, DB backed routes return 503")
}
// The compliance pool authenticates as the compliance role and is the ONLY pool with eeo access.
// It drives adverse impact reporting; the app pool above can never read demographics.
var complianceDB *tenant.DB
if cfg.ComplianceDatabaseURL != "" {
pool, err := database.NewPool(ctx, cfg.ComplianceDatabaseURL)
if err != nil {
log.Fatalf("compliance db pool: %v", err)
}
// Fail closed unless this is the NOBYPASSRLS compliance role. A BYPASSRLS DSN here would leak
// every tenant's demographics cross org through the adverse impact join.
if err := database.AssertRole(ctx, pool, "missionmatch_compliance"); err != nil {
log.Fatalf("compliance pool role check: %v", err)
}
complianceDB = tenant.New(pool)
defer complianceDB.Close()
} else {
log.Printf("WARNING: MM_COMPLIANCE_DATABASE_URL unset, adverse impact reporting returns 503")
}
emb, err := embeddings.New(cfg.Embeddings)
if err != nil {
log.Fatalf("embeddings: %v", err)
}
auditW := audit.New(db)
authSvc, err := buildAuthService(cfg, db, auditW)
if err != nil {
log.Fatalf("auth: %v", err)
}
csrf := security.NewCSRF(authKey(cfg.Auth.CSRFKey, 32, "MM_CSRF_KEY", cfg.IsProduction()))
authH := auth.NewHandler(authSvc, csrf, cfg.Auth.CookieSecure, cfg.AllowedOrigins, cfg.TrustedProxyHeader)
svc := matching.NewService(db, matching.NewEmbeddingSkillMatcher(emb), auditW)
h := matching.NewHandler(svc)
ccH := commandcenter.NewHandler(commandcenter.NewService(db))
oppH := opportunities.NewHandler(opportunities.NewService(db))
awardsH := awards.NewHandler(awards.NewService(db))
wagesH := wages.NewHandler(wages.NewService(db))
sourcingH := sourcing.NewHandler(sourcing.NewService(db, auditW))
eeoH := eeo.NewHandler(eeo.NewService(complianceDB))
govH := governance.NewHandler(governance.NewService(db, auditW, cfg.DecisionRetentionDays))
// Resolve the tenant middleware. In a release build this is always the session resolver; the dev
// X-Org-ID path only exists in a dev tagged build. Assert that positively in production.
sessionMW, resolverKind := chooseResolver(cfg, authH)
if cfg.IsProduction() && resolverKind != "session" {
log.Fatalf("production must resolve the tenant from a validated session, got resolver %q", resolverKind)
}
log.Printf("tenant resolver: %s", resolverKind)
csrfMW := csrf.Protect(authH.CSRFCookieName(), auth.CSRFHeader, cfg.AllowedOrigins)
r := chi.NewRouter()
r.Use(middleware.RequestID)
// NOTE: middleware.RealIP is deliberately NOT used; it trusts spoofable client headers (deprecated
// in chi for that reason). The auth handler derives the client IP from the TCP peer, or from
// MM_TRUSTED_PROXY_HEADER only when the app is behind a trusted reverse proxy that overwrites it.
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second))
r.Get("/healthz", func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
})
r.Get("/healthz/fips", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"fips_enabled": fips140.Enabled(),
"fips_enforced": fips140.Enforced(),
"module": fips140.Version(),
"pbkdf2_self_test": true, // a failure would have aborted startup
})
})
r.Route("/api", func(r chi.Router) {
// Public pre tenant auth: runs before any org is known. Behind the CSRF Origin allowlist and
// the signed double submit, but NOT the session resolver (these operate on a pre MFA session
// or no session and read the cookie themselves).
r.Group(func(r chi.Router) {
r.Use(csrfMW)
authH.PublicRoutes(r)
})
// Tenant scoped: the session resolver feeds app.current_org_id, then CSRF, then per route RBAC.
r.Group(func(r chi.Router) {
r.Use(sessionMW)
r.Use(csrfMW)
h.Routes(r)
ccH.Routes(r)
oppH.Routes(r)
awardsH.Routes(r)
wagesH.Routes(r)
sourcingH.Routes(r)
eeoH.Routes(r)
govH.Routes(r)
authH.TenantRoutes(r)
})
})
srv := &http.Server{Addr: cfg.HTTPAddr, Handler: r, ReadHeaderTimeout: 10 * time.Second}
log.Printf("listening on %s", cfg.HTTPAddr)
if err := srv.ListenAndServe(); err != nil {
log.Fatalf("server: %v", err)
}
}
// fipsSelfTest derives one PBKDF2 key at the production iteration count under the active crypto module.
func fipsSelfTest() error {
_, err := pbkdf2.Key(sha256.New, "missionmatch fips self test", []byte("self test salt"), security.PBKDF2Iterations, 32)
return err
}
// buildAuthService assembles the auth service from config. In production every key is present
// (config.Validate enforces it). In development a missing key falls back to an ephemeral random key
// with a loud warning, so the server still starts for local work.
func buildAuthService(cfg config.Config, db *tenant.DB, auditW *audit.Writer) (*auth.Service, error) {
prod := cfg.IsProduction()
pepperKeys := map[int][]byte{
cfg.Auth.PepperVersion: authKey(cfg.Auth.Pepper, 32, "MM_CREDENTIAL_PEPPER", prod),
}
if len(cfg.Auth.PepperPrevious) > 0 {
pepperKeys[cfg.Auth.PepperVersion-1] = cfg.Auth.PepperPrevious
}
pepper, err := security.NewPepper(cfg.Auth.PepperVersion, pepperKeys)
if err != nil {
return nil, err
}
hasher, err := security.NewHasher(pepper, security.PBKDF2Iterations)
if err != nil {
return nil, err
}
tagger, err := security.NewTagger(authKey(cfg.Auth.RecoveryLookupKey, 32, "MM_RECOVERY_LOOKUP_KEY", prod))
if err != nil {
return nil, err
}
return auth.NewService(auth.Deps{
DB: db,
Audit: auditW,
Hasher: hasher,
Tagger: tagger,
TOTP: security.TOTP{},
TOTPKEKs: map[int][]byte{cfg.Auth.TOTPKEKVersion: authKey(cfg.Auth.TOTPKEK, 32, "MM_TOTP_KEK", prod)},
TOTPKEKActive: cfg.Auth.TOTPKEKVersion,
TOTPIssuer: cfg.Auth.TOTPIssuer,
IdleSeconds: cfg.Auth.SessionIdleSeconds,
AbsoluteSeconds: cfg.Auth.SessionAbsoluteSeconds,
PendingSeconds: cfg.Auth.PendingAbsoluteSeconds,
InviteSeconds: cfg.Auth.InviteExpirySeconds,
CookieSecure: cfg.Auth.CookieSecure,
})
}
// authKey returns the configured key, or an ephemeral random key in development when it is unset.
func authKey(set []byte, size int, name string, prod bool) []byte {
if len(set) > 0 {
return set
}
if prod {
// config.Validate already fatals before here; this is a defensive backstop.
log.Fatalf("%s required in production", name)
}
b := make([]byte, size)
_, _ = rand.Read(b)
log.Printf("WARNING: %s unset, using an ephemeral dev key (sessions and credentials will not survive a restart; set %s for a stable dev database)", name, name)
return b
}