Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/matching/intelligence/access.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/matching/intelligence/access.go |
| Original SHA-256 | 9cf595c580e3056ef0dcdda923113e0757ab8000bccd247c0b45b098f62b1b72 |
| Git blob SHA | 522849585ffb7fd8f916a32daddb22fd8f362517 |
| Reading-copy SHA-256 | 9cf595c580e3056ef0dcdda923113e0757ab8000bccd247c0b45b098f62b1b72 |
Recovered source transcript
Download complete source text ↓162 lines · 7.8 KB
package intelligence
import (
"fmt"
"time"
)
// THE BREAK IN ACCESS CLOCK: whether a cleared person can still be reinstated, or now needs an investigation.
//
// This is the fact that decides placeability for a cleared workforce, and it is the one this product could not
// answer. Two TS/SCI candidates, one three months out of access and one twenty five months out, are entirely
// different staffing propositions: the first can usually start on a new sponsor's paperwork, the second is
// months of investigation lead time. missionMATCH rendered them identically.
//
// THE RULE, as it actually stands. Since 1 October 2021 DCSA has enrolled DoD clearance holders in Continuous
// Vetting under Trusted Workforce 2.0, which replaced the five and ten year periodic reinvestigations with
// ongoing monitoring. Separation pulls a person out of their sponsor's enrollment, and separation is the event
// the window is measured from. Inside twenty four months, with a favourable adjudication closed within the
// previous five years, a new employer can usually reinstate without a full reinvestigation. Outside either
// bound, a new investigation is likely.
//
// THIS PACKAGE IS PURE and this file keeps that property: no database, no clock, an explicit asOf. The same
// inputs produce the same posture every time, which is what lets a staffing decision made in March be
// reconstructed in June.
//
// IT NEVER ASSERTS ELIGIBILITY. Like every other clearance surface in this product, what is computed here is
// an INDICATOR derived from dates somebody entered. The real determination belongs to the hiring client's
// facility security officer through DISS, and the language throughout says so.
// AccessPosture is the answer, as a closed vocabulary a screen can branch on.
type AccessPosture string
const (
// PostureInAccess is somebody currently sponsored and in continuous vetting. No window is running.
PostureInAccess AccessPosture = "in_access"
// PostureReinstatable is a break inside twenty four months with an adjudication inside five years.
PostureReinstatable AccessPosture = "reinstatable"
// PostureClosing is inside the window but with ninety days or less left on it. It exists because the
// difference between twenty two months and twenty five months is the difference between a placement and a
// lost candidate, and a recruiter needs to see it coming rather than discover it.
PostureClosing AccessPosture = "closing"
// PostureInvestigationLikely is past twenty four months, or an adjudication older than five years.
PostureInvestigationLikely AccessPosture = "investigation_likely"
// PostureUnknown is the honest answer when the dates were never entered. It is NOT a synonym for a
// problem, and it must never be rendered as one: most benches will start here.
PostureUnknown AccessPosture = "unknown"
)
// The two bounds the rule turns on, named rather than inlined so the numbers are findable and so a change in
// policy is one edit.
const (
// ReinstatementWindowMonths is the break in access limit for reinstatement without a new investigation.
ReinstatementWindowMonths = 24
// AdjudicationValidYears is how recent the favourable adjudication must additionally be.
AdjudicationValidYears = 5
// ClosingSoonDays is how much of the window has to remain before it is called closing.
ClosingSoonDays = 90
)
// AccessFacts is what a candidate row carries about access. Every field is optional because every field is
// optional in the database, and an absent date is a real state rather than a defect.
type AccessFacts struct {
CVEnrolled *bool
AccessEndedOn *time.Time
LastAdjudicated *time.Time
ClearanceLevel string
ClearanceStatus string
}
// AccessIntel is the derived answer, shaped for a screen.
type AccessIntel struct {
Posture AccessPosture `json:"posture"`
// Label is the posture in the words a recruiter uses.
Label string `json:"label"`
// Detail is the one sentence that explains the posture, including the numbers it turned on, so nobody has
// to trust the label alone.
Detail string `json:"detail"`
// MonthsOutOfAccess is how long the break has run. Absent while somebody is in access or unknown.
MonthsOutOfAccess *int `json:"months_out_of_access,omitempty"`
// DaysLeftInWindow is how much of the twenty four months remains, negative once it has passed. Absent
// when no window is running.
DaysLeftInWindow *int `json:"days_left_in_window,omitempty"`
// AdjudicationStale reports the second bound failing independently of the first, because a candidate two
// months out of access with a six year old adjudication is still an investigation and the reason matters.
AdjudicationStale bool `json:"adjudication_stale,omitempty"`
}
// Access derives the posture as of a given day.
//
// THE ORDER OF THE CHECKS IS THE RULE. In access wins over everything, because a person currently sponsored
// has no window. Then unknown, because a posture computed from absent dates would be fiction. Then the two
// bounds, adjudication first, because it fails independently of the clock and a recruiter told "past twenty
// four months" about somebody eight months out would go looking for the wrong thing.
func Access(f AccessFacts, asOf time.Time) AccessIntel {
day := asOf.UTC().Truncate(24 * time.Hour)
if f.CVEnrolled != nil && *f.CVEnrolled {
return AccessIntel{
Posture: PostureInAccess,
Label: "In access",
Detail: "Currently in continuous vetting through a sponsor, so no break in access clock is " +
"running. Continuous vetting replaced periodic reinvestigation in October 2021.",
}
}
if f.AccessEndedOn == nil {
return AccessIntel{
Posture: PostureUnknown,
Label: "Access history not known",
Detail: "Nobody has recorded when this person was last in access, so their reinstatement " +
"position cannot be worked out. It is not a problem with the candidate, it is a gap in the " +
"record.",
}
}
ended := f.AccessEndedOn.UTC().Truncate(24 * time.Hour)
// monthsBetween already exists in this package with exactly these semantics, calendar months rather than
// thirty day blocks. Reused rather than reimplemented: two functions computing the same thing is how they
// come to disagree, and at the twenty four month mark a disagreement decides an answer.
months := monthsBetween(ended, day)
deadline := ended.AddDate(0, ReinstatementWindowMonths, 0)
daysLeft := int(deadline.Sub(day).Hours() / 24)
out := AccessIntel{MonthsOutOfAccess: &months, DaysLeftInWindow: &daysLeft}
// The adjudication bound, checked first because it fails on its own.
if f.LastAdjudicated != nil {
if f.LastAdjudicated.UTC().AddDate(AdjudicationValidYears, 0, 0).Before(day) {
out.AdjudicationStale = true
out.Posture = PostureInvestigationLikely
out.Label = "A new investigation is likely"
out.Detail = fmt.Sprintf(
"The favourable adjudication closed more than %d years ago, so even though the break in "+
"access is %d months, the simple reinstatement path does not apply.",
AdjudicationValidYears, months)
return out
}
}
switch {
case daysLeft < 0:
out.Posture = PostureInvestigationLikely
out.Label = "A new investigation is likely"
out.Detail = fmt.Sprintf(
"%d months out of access, past the %d month reinstatement window. Expect investigation lead "+
"time rather than a paperwork reinstatement.", months, ReinstatementWindowMonths)
case daysLeft <= ClosingSoonDays:
out.Posture = PostureClosing
out.Label = "Reinstatement window closing"
out.Detail = fmt.Sprintf(
"%d months out of access, with %d days left of the %d month window. After that a new "+
"investigation is likely.", months, daysLeft, ReinstatementWindowMonths)
default:
out.Posture = PostureReinstatable
out.Label = "Reinstatable"
out.Detail = fmt.Sprintf(
"%d months out of access, inside the %d month window, so a new sponsor can usually reinstate "+
"without a full reinvestigation.", months, ReinstatementWindowMonths)
}
return out
}