Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / cmd/demo-seed/main.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 |
| Branch | master |
| Path or archive member | cmd/demo-seed/main.go |
| Original SHA-256 | 776fe8a64e9820f23620888e8c69be09f566d8b39d721ee7b0001675ed192f45 |
| Git blob SHA | 501297e0041125974b020ce339721bd18439ba4b |
| Reading-copy SHA-256 | 776fe8a64e9820f23620888e8c69be09f566d8b39d721ee7b0001675ed192f45 |
Every recorded occurrence
These 5 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 / cmd/demo-seed/main.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / cmd/demo-seed/main.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
| Janady13/missionmatch / cmd/demo-seed/main.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / cmd/demo-seed/main.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / cmd/demo-seed/main.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓229 lines · 8.6 KB
// Command demo-seed populates REAL engine backed screenMATCH evaluations for the demo org so the
// Command Center WhoCanSupport panel and the Candidates Win Impact panel are not empty. For each
// requirement in the org it screens a capped set of candidates through the existing
// matching.Service.ScreenCandidate, which scores with the frozen engine.ScoreCandidate, writes a
// served score audit event, and upserts a candidate_evaluations row. That is the ONLY correct way to
// produce an evaluation: this tool never fabricates a score and never inserts a candidate_evaluations
// row directly.
//
// It runs entirely under the NOBYPASSRLS application role, inside the tenant transaction that
// ScreenCandidate opens (RLS scoped to the org set on the context via tenant.WithOrg). ScreenCandidate
// upserts the latest qualification per candidate and requirement pair, so a rerun is safe and
// idempotent.
//
// Env: MM_DATABASE_URL (the app DSN, required), MM_DEMO_ORG_ID (optional, overrides the default demo
// org, itself overridable by the -org flag). Flags let you cap how many candidates are screened per
// requirement, cap how many requirements are processed, and preview with -dry-run.
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"sort"
"strings"
"time"
"github.com/google/uuid"
"github.com/missionworkforce/missionmatch/internal/modules/matching"
"github.com/missionworkforce/missionmatch/internal/modules/matching/engine"
"github.com/missionworkforce/missionmatch/internal/platform/audit"
"github.com/missionworkforce/missionmatch/internal/platform/database"
"github.com/missionworkforce/missionmatch/internal/platform/database/dbgen"
"github.com/missionworkforce/missionmatch/internal/platform/tenant"
)
// defaultOrg is the sales demo organization id. It is the same fixed id the other demo tooling uses.
const defaultOrg = "11111111-1111-1111-1111-111111111111"
// listPageLimit bounds a single ListRequirements or ListCandidates read. The demo org is small, so one
// page covers it; the cap keeps the tool honest against a large org too.
const listPageLimit = 500
// bandCounts is the green, yellow, and red tally for one requirement, read from the engine returned
// MatchResult band. The engine is the only source of a band; this only counts what it returned.
type bandCounts struct {
green, yellow, red int
}
func (b bandCounts) total() int { return b.green + b.yellow + b.red }
func main() {
orgFlag := flag.String("org", firstNonEmpty(os.Getenv("MM_DEMO_ORG_ID"), defaultOrg),
"organization id to seed (defaults to MM_DEMO_ORG_ID or the demo org)")
perRequirement := flag.Int("per-requirement", 40,
"cap on how many candidates to screen against each requirement")
maxRequirements := flag.Int("max-requirements", 0,
"cap on how many requirements to process (0 means all)")
dryRun := flag.Bool("dry-run", false,
"log what would be screened without writing any evaluation or audit row")
flag.Parse()
if *perRequirement <= 0 {
log.Fatal("demo-seed: -per-requirement must be positive")
}
if *maxRequirements < 0 {
log.Fatal("demo-seed: -max-requirements cannot be negative")
}
orgID, err := uuid.Parse(strings.TrimSpace(*orgFlag))
if err != nil {
log.Fatalf("demo-seed: bad org id %q: %v", *orgFlag, err)
}
dsn := strings.TrimSpace(os.Getenv("MM_DATABASE_URL"))
if dsn == "" {
log.Fatal("demo-seed: MM_DATABASE_URL (the app DSN) is required")
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
defer cancel()
pool, err := database.NewPool(ctx, dsn)
if err != nil {
log.Fatalf("demo-seed: db pool: %v", err)
}
defer pool.Close()
// Fail closed unless this is the NOBYPASSRLS app role, so the seed can never bypass tenant RLS and
// can only write the demo org it is scoped to. ScreenCandidate itself runs under RLS.
if err := database.AssertRole(ctx, pool, "missionmatch_app"); err != nil {
log.Fatalf("demo-seed: app pool role check: %v", err)
}
appDB := tenant.New(pool)
// The service is built with a nil matcher (exact match only, deterministic, no embedding provider
// needed) and a real audit writer so every served score is recorded, the same served score audit the
// live screenMATCH path writes. The nil matcher matches how the integration tests construct the
// service, matching.NewService(appDB, nil, nil), and keeps the run reproducible with no plane calls.
// The engine.ScoreCandidate reached through ScreenCandidate is the only scorer.
var aud *audit.Writer
if !*dryRun {
aud = audit.New(appDB)
}
svc := matching.NewService(appDB, nil, aud)
// Scope every read and write to the demo org. RunInTenantTx inside the service refuses to run without
// this, and the RLS policy would match zero rows, so this is the correctness boundary for the seed.
orgCtx := tenant.WithOrg(ctx, orgID.String())
reqs, err := svc.ListRequirements(orgCtx, listPageLimit, 0)
if err != nil {
log.Fatalf("demo-seed: list requirements for org %s: %v", orgID, err)
}
if len(reqs) == 0 {
log.Fatalf("demo-seed: org %s has no requirements to seed", orgID)
}
if *maxRequirements > 0 && len(reqs) > *maxRequirements {
reqs = reqs[:*maxRequirements]
}
// Load the candidate pool once: it is the same set for every requirement, so one read avoids a
// per requirement round trip. ListCandidates already excludes soft deleted rows; anonymized rows are
// filtered here so an erased candidate is never rescreened.
cands, err := svc.ListCandidates(orgCtx, listPageLimit, 0)
if err != nil {
log.Fatalf("demo-seed: list candidates for org %s: %v", orgID, err)
}
cands = screenable(cands)
if len(cands) == 0 {
log.Fatalf("demo-seed: org %s has no screenable candidates", orgID)
}
if len(cands) > *perRequirement {
cands = cands[:*perRequirement]
}
log.Printf("demo-seed: org=%s requirements=%d candidates_per_requirement=%d dry_run=%v",
orgID, len(reqs), len(cands), *dryRun)
perReq := make(map[uuid.UUID]bandCounts, len(reqs))
reqTitle := make(map[uuid.UUID]string, len(reqs))
var totalWritten, totalErrors int
for _, r := range reqs {
reqTitle[r.ID] = r.Title
if *dryRun {
log.Printf("demo-seed: [dry run] would screen %d candidates against requirement %s (%q)",
len(cands), r.ID, r.Title)
continue
}
var counts bandCounts
for _, c := range cands {
res, serr := svc.ScreenCandidate(orgCtx, c.ID, r.ID)
if serr != nil {
// A single candidate screen failure must not abort the whole run. Log it, wrapped with %w, and
// keep going so a bad row does not deny the rest of the panel its evaluations.
totalErrors++
log.Printf("demo-seed: %v", fmt.Errorf("screen candidate %s vs requirement %s: %w", c.ID, r.ID, serr))
continue
}
tallyBand(&counts, res.Band)
totalWritten++
}
perReq[r.ID] = counts
log.Printf("demo-seed: requirement %s (%q): screened %d, green=%d yellow=%d red=%d",
r.ID, r.Title, counts.total(), counts.green, counts.yellow, counts.red)
}
if *dryRun {
log.Printf("demo-seed: [dry run] complete, would have screened %d candidates across %d requirements",
len(cands)*len(reqs), len(reqs))
return
}
// Final summary: total evaluations written and the green, yellow, red counts per requirement, ordered
// by requirement id so the report is stable across runs.
log.Printf("demo-seed: DONE, wrote %d evaluations across %d requirements (%d screen errors)",
totalWritten, len(reqs), totalErrors)
ids := make([]uuid.UUID, 0, len(perReq))
for id := range perReq {
ids = append(ids, id)
}
sort.Slice(ids, func(i, j int) bool { return ids[i].String() < ids[j].String() })
for _, id := range ids {
c := perReq[id]
log.Printf("demo-seed: summary requirement %s (%q): green=%d yellow=%d red=%d total=%d",
id, reqTitle[id], c.green, c.yellow, c.red, c.total())
}
}
// screenable drops anonymized candidates from the pool. ListCandidates already excludes soft deleted
// rows (deleted_at IS NULL). An anonymized row is an erased candidate that should never be rescreened,
// so it is filtered here to keep the served scores clean.
func screenable(in []dbgen.Candidate) []dbgen.Candidate {
out := in[:0:0]
for _, c := range in {
if c.AnonymizedAt != nil {
continue
}
out = append(out, c)
}
return out
}
// tallyBand increments the count for the band the engine returned. The band is authoritative from the
// engine MatchResult; this only records it.
func tallyBand(counts *bandCounts, b engine.Band) {
switch b {
case engine.BandGreen:
counts.green++
case engine.BandYellow:
counts.yellow++
case engine.BandRed:
counts.red++
}
}
func firstNonEmpty(vals ...string) string {
for _, v := range vals {
if s := strings.TrimSpace(v); s != "" {
return s
}
}
return ""
}