Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/eeo/fairness.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 |
| Branch | master |
| Path or archive member | internal/modules/eeo/fairness.go |
| Original SHA-256 | d6ea2f3698b5ec60fa844bdd590facc3db7688b73e0aae6d5c7f31131419d033 |
| Git blob SHA | 06757d9397e75cb61caf40543a26188f4bf99d55 |
| Reading-copy SHA-256 | d6ea2f3698b5ec60fa844bdd590facc3db7688b73e0aae6d5c7f31131419d033 |
Every recorded occurrence
These 19 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 / internal/modules/eeo/fairness.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | phase2-connectors | e038d4c687aec16f8bd9bc4d907eea14d91f8704 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | vendor-intelligence | fe9796a19c261951d3f2565206c0c1b5ac294465 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | phase2-connectors | e038d4c687aec16f8bd9bc4d907eea14d91f8704 | Open original |
| Janady13/missionmatch / internal/modules/eeo/fairness.go | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
Recovered source transcript
Download complete source text ↓262 lines · 9.8 KB
package eeo
import (
"context"
"time"
"github.com/jackc/pgx/v5"
"github.com/shopspring/decimal"
)
// driftDelta is the fixed drop in a group's four fifths impact ratio, snapshot over snapshot, that
// raises a drift alert even while the ratio is still at or above 0.80. A best in world AEDT tool warns
// BEFORE a group crosses the threshold, so a 0.05 fall between two consecutive snapshots is surfaced.
var driftDelta = decimal.RequireFromString("0.05")
// SnapshotSummary is the group level aggregate result of one SnapshotAdverseImpact run for one org. It
// carries NO per person data: only the count of rows written and how many groups fell below the four
// fifths threshold, so a scheduler can log a concise line with no PII.
type SnapshotSummary struct {
OrganizationID string
GroupsWritten int
BelowThreshold int
ModelVersion string
SnapshotAtRFC string
}
// FairnessPoint is one demographic group bucket's impact ratio at one snapshot in the time series. The
// ratio is a decimal string exactly as the AdverseImpact report labels it: the highest rate reference
// group passes at 1.0 against itself, and "n/a" marks an unknown group or a cut with fewer than two known
// groups (never compared, never flagged).
type FairnessPoint struct {
SnapshotAt string `json:"snapshot_at"`
SelectionRate string `json:"selection_rate"`
ImpactRatio string `json:"impact_ratio"`
Selected int `json:"selected"`
Total int `json:"total"`
ModelVersion string `json:"model_version"`
}
// FairnessSeries is the continuous time series for one (decision_context, group_label) bucket, with an
// alert flag. Alert is true when the LATEST snapshot is below 0.80, OR when the impact ratio dropped by
// more than driftDelta from the prior snapshot (drift toward disparate impact). This is GROUP LEVEL
// aggregate data; it is never per person and never an input to matching.
type FairnessSeries struct {
DecisionContext string `json:"decision_context"`
GroupLabel string `json:"group_label"`
Points []FairnessPoint `json:"points"`
Alert bool `json:"alert"`
AlertReason string `json:"alert_reason"`
}
// SnapshotAdverseImpact computes the current adverse impact report for the caller's org and APPENDS one
// fairness_snapshots row per demographic group bucket through the compliance pool, stamping the model
// version in force at snapshot time. It is append only: it never updates or deletes a prior snapshot.
// Run on a schedule, it builds the continuous four fifths time series the drift alert reads.
//
// The whole read plus write runs inside one tenant transaction, so RLS scopes both the AdverseImpact
// join and the snapshot insert to the caller's org, and a partial run rolls back cleanly.
func (s *Service) SnapshotAdverseImpact(ctx context.Context, now time.Time) (SnapshotSummary, error) {
if s.compliance == nil || s.compliance.Pool == nil {
return SnapshotSummary{}, ErrNoCompliance
}
rep, err := s.AdverseImpact(ctx, now)
if err != nil {
return SnapshotSummary{}, err
}
snapAt := now.UTC()
summary := SnapshotSummary{SnapshotAtRFC: snapAt.Format(time.RFC3339)}
rows := snapshotRowsFromReport(rep)
err = s.compliance.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error {
model, e := activeModelVersion(ctx, tx)
if e != nil {
return e
}
summary.ModelVersion = model
for _, r := range rows {
if e := insertSnapshot(ctx, tx, snapAt, model, r); e != nil {
return e
}
summary.GroupsWritten++
if r.belowThreshold {
summary.BelowThreshold++
}
}
return nil
})
if err != nil {
return SnapshotSummary{}, err
}
return summary, nil
}
// snapshotRow is one group bucket flattened out of the report, ready to append. The rate and ratio are
// decimals (never float64) so the numeric column round trips bit stable.
type snapshotRow struct {
decisionContext string
groupLabel string
selected int
total int
selectionRate decimal.Decimal
impactRatio *decimal.Decimal // nil only for an n/a row, an unknown group or a cut with fewer than two known groups; the reference group passes at 1.0
belowThreshold bool
}
// snapshotRowsFromReport flattens every ImpactRow across both stages and all three cuts into append
// ready rows. decision_context is the stage plus the cut, so the series for one group is unambiguous and
// mirrors exactly what AdverseImpact reports. The rate and ratio strings the report already computed are
// parsed back into decimal so the snapshot is provably the same number the report shows.
func snapshotRowsFromReport(rep Report) []snapshotRow {
var out []snapshotRow
add := func(stage, cut string, imp []ImpactRow) {
ctxLabel := stage + " :: " + cut
for _, r := range imp {
out = append(out, snapshotRowFromImpact(ctxLabel, r))
}
}
add(rep.Selection.Stage, "by sex", rep.Selection.ByGender)
add(rep.Selection.Stage, "by race or ethnicity", rep.Selection.ByRace)
add(rep.Selection.Stage, "intersectional", rep.Selection.Intersectional)
add(rep.Screening.Stage, "by sex", rep.Screening.ByGender)
add(rep.Screening.Stage, "by race or ethnicity", rep.Screening.ByRace)
add(rep.Screening.Stage, "intersectional", rep.Screening.Intersectional)
return out
}
// snapshotRowFromImpact converts one report ImpactRow into an append ready snapshot row, recomputing
// below_threshold from the parsed ratio so it matches the report Flagged flag exactly.
func snapshotRowFromImpact(decisionContext string, r ImpactRow) snapshotRow {
row := snapshotRow{
decisionContext: decisionContext,
groupLabel: r.Group,
selected: r.Selected,
total: r.Considered,
selectionRate: decimalOrZero(r.Rate),
}
if r.ImpactRatio != "n/a" {
ratio := decimalOrZero(r.ImpactRatio)
row.impactRatio = &ratio
row.belowThreshold = ratio.LessThan(fourFifths)
}
return row
}
// decimalOrZero parses a fixed decimal string, returning zero on any unparsable value. The report only
// ever emits clean fixed strings here, so this is defensive, not a real path.
func decimalOrZero(s string) decimal.Decimal {
d, err := decimal.NewFromString(s)
if err != nil {
return decimal.Zero
}
return d
}
// FairnessTrend reads the appended snapshots for the caller's org since the given instant and returns,
// per (decision_context, group_label) bucket, the ordered series of impact ratios and an alert flag. The
// alert fires when the latest impact ratio is below 0.80, OR when it dropped by more than driftDelta from
// the prior snapshot. Decimals throughout, never float64.
func (s *Service) FairnessTrend(ctx context.Context, since time.Time) ([]FairnessSeries, error) {
if s.compliance == nil || s.compliance.Pool == nil {
return nil, ErrNoCompliance
}
var series []FairnessSeries
err := s.compliance.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error {
var e error
series, e = readTrend(ctx, tx, since)
return e
})
if err != nil {
return nil, err
}
return series, nil
}
// readTrend loads the ordered snapshots, groups them into per bucket series, and computes the alert for
// each. The SQL orders by bucket then time so the points within a series are already chronological.
func readTrend(ctx context.Context, tx pgx.Tx, since time.Time) ([]FairnessSeries, error) {
rows, err := tx.Query(ctx, trendQuery, since.UTC())
if err != nil {
return nil, err
}
defer rows.Close()
type key struct{ ctx, group string }
order := make([]key, 0)
byBucket := make(map[key]*FairnessSeries)
for rows.Next() {
var (
decisionContext, groupLabel, modelVersion string
snapshotAt time.Time
selected, total int
selectionRate decimal.Decimal
impactRatio *decimal.Decimal
)
if e := rows.Scan(&decisionContext, &groupLabel, &snapshotAt, &selected, &total, &selectionRate, &impactRatio, &modelVersion); e != nil {
return nil, e
}
k := key{decisionContext, groupLabel}
fs := byBucket[k]
if fs == nil {
fs = &FairnessSeries{DecisionContext: decisionContext, GroupLabel: groupLabel}
byBucket[k] = fs
order = append(order, k)
}
ratioStr := "n/a"
if impactRatio != nil {
ratioStr = impactRatio.StringFixed(4)
}
fs.Points = append(fs.Points, FairnessPoint{
SnapshotAt: snapshotAt.UTC().Format(time.RFC3339),
SelectionRate: selectionRate.StringFixed(4),
ImpactRatio: ratioStr,
Selected: selected,
Total: total,
ModelVersion: modelVersion,
})
}
if err := rows.Err(); err != nil {
return nil, err
}
out := make([]FairnessSeries, 0, len(order))
for _, k := range order {
fs := byBucket[k]
evaluateAlert(fs)
out = append(out, *fs)
}
return out, nil
}
// evaluateAlert sets the drift alert on a series. It alerts when the latest impact ratio is below 0.80,
// or when the latest ratio dropped by more than driftDelta from the prior snapshot's ratio (a fall
// toward disparate impact, flagged even while still above the threshold). Points with an n/a ratio (the
// reference group, or a cut with too few known groups) do not contribute a ratio to the comparison.
func evaluateAlert(fs *FairnessSeries) {
var ratios []decimal.Decimal
for _, p := range fs.Points {
if p.ImpactRatio == "n/a" {
continue
}
ratios = append(ratios, decimalOrZero(p.ImpactRatio))
}
if len(ratios) == 0 {
return
}
latest := ratios[len(ratios)-1]
if latest.LessThan(fourFifths) {
fs.Alert = true
fs.AlertReason = "latest impact ratio " + latest.StringFixed(4) + " is below the 0.80 four fifths threshold"
return
}
if len(ratios) >= 2 {
prior := ratios[len(ratios)-2]
drop := prior.Sub(latest)
if drop.GreaterThan(driftDelta) {
fs.Alert = true
fs.AlertReason = "impact ratio dropped " + drop.StringFixed(4) + " from " + prior.StringFixed(4) + " to " + latest.StringFixed(4) + ", more than the 0.05 drift limit"
}
}
}