Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/alerts/dto.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 |
| Branch | master |
| Path or archive member | internal/modules/alerts/dto.go |
| Original SHA-256 | 41e58ca3573a6409520ea97915ac0fbd2a717542c23661ae9ff3f7012b12edc3 |
| Git blob SHA | 8636630cb95ff3a7bbbae35e46684387c98a190c |
| Reading-copy SHA-256 | 41e58ca3573a6409520ea97915ac0fbd2a717542c23661ae9ff3f7012b12edc3 |
Every recorded occurrence
These 11 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/alerts/dto.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | vendor-intelligence | fe9796a19c261951d3f2565206c0c1b5ac294465 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
Recovered source transcript
Download complete source text ↓128 lines · 6.0 KB
// Package alerts is the proactive alert engine, the watch loop. A best in world capture intelligence does
// not wait to be asked: it WATCHES the account and tells the analyst, unprompted, when something actionable
// happens. This module adds the MARKET EVENT arm to the existing scheduled bench watch
// (staffing.Service.RecomputeProactive) plus a typed, persisted, UI surfaceable alert.
//
// Four triggers fire per sweep, all RLS scoped to the caller's org:
//
// - clearance_expiring: a candidate the owner holds whose clearance lapses within the window, a staffing
// risk to flag before the reinvestigation lapses.
// - recompete_winnable: a recently posted federal opportunity in an agency the owner already shows interest
// in (a requirement for that agency, or a recorded bid) whose period of performance ends inside the
// forward recompete window. This is the market event arm: GLOBAL PUBLIC opportunity_records joined to the
// owner's own interest, RLS scoping only the interest read.
// - gap_fillable: an open requirement with no green evaluation that the bench NOW structurally covers (at
// least one candidate holds at least the required clearance level AND at least four fifths of the required
// skills, the SAME structural test as ai.BenchGapForRequirement, integer arithmetic, no float). This is a
// STRUCTURAL coverage test, never a match score: the frozen engine stays the only scorer.
// - collision: a candidate (most sharply a scarce cleared one) proposed or approved on the slates of two or
// more DISTINCT competing OPEN opportunities at once, the double commit of a scarce cleared person across
// competing bids. It is an ADVISORY finding with a deterministic best fit suggested primary a human
// resolves; it never auto rejects a slate member.
//
// Each alert UPSERTs ON CONFLICT (organization_id, dedupe_key), so a second sweep of the same event changes
// nothing new (idempotent). The sweep writes ONE counts only audit event (aedt.alert.swept) with the per type
// counts and NO PII: no candidate id, no agency value, just counts.
package alerts
// The four alert types, mirroring the alerts.alert_type CHECK constraint. Each names a distinct actionable
// event the watch loop detects. Collision is the cross opportunity deconfliction finding: a candidate proposed
// or approved on two or more distinct competing open opportunities at once.
const (
TypeRecompeteWinnable = "recompete_winnable"
TypeClearanceExpiring = "clearance_expiring"
TypeGapFillable = "gap_fillable"
TypeCollision = "collision"
)
// The three severities, mirroring the alerts.severity CHECK constraint, ordered from quiet to loud.
const (
SeverityInfo = "info"
SeverityWatch = "watch"
SeverityUrgent = "urgent"
)
// The three statuses the UI moves an alert through, mirroring the alerts.status CHECK constraint.
const (
StatusUnread = "unread"
StatusRead = "read"
StatusDismissed = "dismissed"
)
// The three subject kinds an alert points at, the owner's own record. An empty subject is allowed (the
// column defaults to the empty string) but the three triggers always set one.
const (
SubjectOpportunity = "opportunity"
SubjectCandidate = "candidate"
SubjectRequirement = "requirement"
)
// validTypes, validSeverities, and validStatuses are the closed sets the DB CHECK constraints enforce. The
// service and handler validate against them before a write so a bad value is a clean rejection rather than a
// raw constraint violation.
var (
validTypes = map[string]bool{
TypeRecompeteWinnable: true,
TypeClearanceExpiring: true,
TypeGapFillable: true,
TypeCollision: true,
}
validSeverities = map[string]bool{
SeverityInfo: true,
SeverityWatch: true,
SeverityUrgent: true,
}
validStatuses = map[string]bool{
StatusUnread: true,
StatusRead: true,
StatusDismissed: true,
}
)
// IsValidType reports whether t is one of the four allowed alert types.
func IsValidType(t string) bool { return validTypes[t] }
// IsValidSeverity reports whether s is one of the three allowed severities.
func IsValidSeverity(s string) bool { return validSeverities[s] }
// IsValidStatus reports whether s is one of the three allowed statuses.
func IsValidStatus(s string) bool { return validStatuses[s] }
// Alert is one persisted alert row returned to the UI. subject_id is omitted when the alert carries no
// subject; created_at and updated_at are RFC3339.
type Alert struct {
ID string `json:"id"`
AlertType string `json:"alert_type"`
Severity string `json:"severity"`
SubjectType string `json:"subject_type,omitempty"`
SubjectID string `json:"subject_id,omitempty"`
Title string `json:"title"`
Detail string `json:"detail,omitempty"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// SweepSummary is the per type count of alerts the sweep upserted, the only thing the sweep returns to the
// caller and the only thing the counts only audit event records. It carries NO PII: no candidate id, no
// agency value, no requirement title, just counts.
type SweepSummary struct {
ClearanceExpiring int `json:"clearance_expiring"`
RecompeteWinnable int `json:"recompete_winnable"`
GapFillable int `json:"gap_fillable"`
Collision int `json:"collision"`
}
// Total is the sum of the per type counts, the total number of alerts the sweep upserted.
func (s SweepSummary) Total() int {
return s.ClearanceExpiring + s.RecompeteWinnable + s.GapFillable + s.Collision
}
// dedupeKey builds the stable per (org, the thing alerted) dedupe key the UPSERT keys on. The org scoping is
// the UNIQUE (organization_id, dedupe_key) constraint, so the key itself carries only the type prefix and the
// subject id; a re sweep of the same event yields the same key and the UPSERT refreshes the one row. Keeping
// this pure and named lets the unit test pin the construction.
func dedupeKey(alertType, subjectID string) string {
return alertType + ":" + subjectID
}