package intelligence import ( "strings" "testing" "time" ) func day(y int, m time.Month, d int) time.Time { return time.Date(y, m, d, 0, 0, 0, 0, time.UTC) } func ptr[T any](v T) *T { return &v } // THE WHOLE POINT, as one assertion: two TS/SCI candidates who look identical today are not the same asset, // and this is where the difference becomes visible. func TestThreeMonthsOutAndTwentyFiveMonthsOutAreDifferentAnswers(t *testing.T) { now := day(2026, time.August, 1) fresh := Access(AccessFacts{AccessEndedOn: ptr(day(2026, time.May, 1))}, now) stale := Access(AccessFacts{AccessEndedOn: ptr(day(2024, time.July, 1))}, now) if fresh.Posture != PostureReinstatable { t.Errorf("three months out = %q, want reinstatable", fresh.Posture) } if stale.Posture != PostureInvestigationLikely { t.Errorf("twenty five months out = %q, want investigation_likely", stale.Posture) } if fresh.Posture == stale.Posture { t.Fatal("the two rendered the same, which is the defect this exists to remove") } } // The boundary itself. Somebody separated on 15 January reaches twenty four months on 15 January two years // later, and the day before that they are still inside. func TestTheTwentyFourMonthBoundaryIsExact(t *testing.T) { ended := day(2024, time.January, 15) for _, c := range []struct { name string asOf time.Time want AccessPosture }{ {"one day before the line", day(2026, time.January, 14), PostureClosing}, {"on the line", day(2026, time.January, 15), PostureClosing}, {"one day past", day(2026, time.January, 16), PostureInvestigationLikely}, } { got := Access(AccessFacts{AccessEndedOn: &ended}, c.asOf).Posture if got != c.want { t.Errorf("%s: posture = %q, want %q", c.name, got, c.want) } } } // A stale adjudication fails the rule ON ITS OWN, and the message has to say which bound failed. A recruiter // told "past twenty four months" about somebody eight months out would go looking for the wrong thing. func TestAStaleAdjudicationFailsIndependentlyOfTheClock(t *testing.T) { now := day(2026, time.August, 1) got := Access(AccessFacts{ AccessEndedOn: ptr(day(2025, time.December, 1)), // eight months, well inside the window LastAdjudicated: ptr(day(2019, time.January, 1)), // but seven years ago }, now) if got.Posture != PostureInvestigationLikely { t.Fatalf("posture = %q, want investigation_likely on a stale adjudication", got.Posture) } if !got.AdjudicationStale { t.Error("the adjudication bound failed and the answer does not say so") } if !strings.Contains(got.Detail, "adjudication") { t.Errorf("the detail does not name the reason: %q", got.Detail) } } // In access beats everything. Somebody currently sponsored has no window running at all. func TestInAccessHasNoWindow(t *testing.T) { got := Access(AccessFacts{CVEnrolled: ptr(true)}, day(2026, time.August, 1)) if got.Posture != PostureInAccess { t.Fatalf("posture = %q, want in_access", got.Posture) } if got.DaysLeftInWindow != nil || got.MonthsOutOfAccess != nil { t.Error("a window was computed for somebody who is in access") } } // UNKNOWN IS NOT A PROBLEM AND MUST NOT READ AS ONE. Most benches start with no access history recorded, and // a product that painted every one of them as a risk would be crying wolf on its entire dataset. func TestUnknownSaysTheRecordIsIncompleteNotThatTheCandidateIsRisky(t *testing.T) { got := Access(AccessFacts{}, day(2026, time.August, 1)) if got.Posture != PostureUnknown { t.Fatalf("posture = %q, want unknown", got.Posture) } if !strings.Contains(got.Detail, "gap in the record") { t.Errorf("the detail blames the candidate rather than the record: %q", got.Detail) } if got.MonthsOutOfAccess != nil { t.Error("months were computed from a date that does not exist") } } // CALENDAR MONTHS, NOT THIRTY DAY BLOCKS. Dividing days by 30.44 is wrong by the better part of a week at the // twenty four month mark, which is precisely where it decides the answer. func TestMonthsAreCalendarMonths(t *testing.T) { for _, c := range []struct { from, to time.Time want int }{ {day(2024, time.January, 31), day(2024, time.February, 29), 0}, // not yet a full month {day(2024, time.January, 15), day(2024, time.February, 15), 1}, {day(2024, time.January, 15), day(2026, time.January, 14), 23}, {day(2024, time.January, 15), day(2026, time.January, 15), 24}, } { if got := monthsBetween(c.from, c.to); got != c.want { t.Errorf("monthsBetween(%s, %s) = %d, want %d", c.from.Format("2006-01-02"), c.to.Format("2006-01-02"), got, c.want) } } }