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 | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 |
| Branch | m5-price-to-win |
| Path or archive member | internal/modules/alerts/dto.go |
| Original SHA-256 | 0444e6540dd80e5491f8543effb267a09bcee30b42854d214ae899f7f7040e2a |
| Git blob SHA | 0630203436d35e14984877ec4009ecafff584f0b |
| Reading-copy SHA-256 | 0444e6540dd80e5491f8543effb267a09bcee30b42854d214ae899f7f7040e2a |
Every recorded occurrence
These 9 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 | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | phase2-connectors | e038d4c687aec16f8bd9bc4d907eea14d91f8704 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / internal/modules/alerts/dto.go | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
Recovered source transcript
Download complete source text ↓120 lines · 5.3 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.
//
// Three 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.
//
// 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 three alert types, mirroring the alerts.alert_type CHECK constraint. Each names a distinct actionable
// event the watch loop detects.
const (
TypeRecompeteWinnable = "recompete_winnable"
TypeClearanceExpiring = "clearance_expiring"
TypeGapFillable = "gap_fillable"
)
// 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,
}
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 three 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"`
}
// Total is the sum of the three per type counts, the total number of alerts the sweep upserted.
func (s SweepSummary) Total() int {
return s.ClearanceExpiring + s.RecompeteWinnable + s.GapFillable
}
// 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
}