Files
aml/pkg/api/readiness.go
zeekay bae63692f0 the corporate name is Lux Industries Inc
Lux Partners Limited is the Isle of Man company and does not appear on a
public surface. Lux Industries Inc, a Delaware C corporation, is the one
these copyright lines, citations and terms name.

A bare "Lux Partners" is left alone unless the line says who owns
something — elsewhere it is the name of a site, not a party.
2026-08-28 16:43:59 -07:00

89 lines
2.6 KiB
Go

// Copyright 2024-2026 Lux Industries Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package api
import (
"net/http"
"time"
"github.com/hanzoai/base/core"
)
// screenStale mirrors the daemon's list-staleness budget. The lists refresh daily,
// so two days means two consecutive failures have gone unnoticed.
const screenStale = 48 * time.Hour
// screeningSources answers, per list, whether this instance is fit to screen
// against it and when it last loaded.
//
// The question is worth a route of its own because the failure it reports is
// otherwise invisible: a list that has stopped loading returns no matches, and no
// matches is exactly what a clean party returns. An operator has no way to tell
// "nobody on your payment is designated" from "the list you are screening against
// is empty" without being told the date and the count.
//
// It answers 503 when any source is unfit, so a readiness probe and a dashboard
// read the same truth rather than each deciding for itself.
func (h *Handler) screeningSources() func(e *core.RequestEvent) error {
return func(e *core.RequestEvent) error {
if _, err := h.tenant(e); err != nil {
return refuse(e, err)
}
if h.Readiness == nil {
return fail(e, http.StatusServiceUnavailable, "screening readiness is not wired")
}
now := time.Now().UTC()
lists := h.Readiness.Lists()
unfit := h.Readiness.Unfit(now, screenStale)
ready := len(unfit) == 0
type source struct {
Source string `json:"source"`
Entries int `json:"entries"`
LoadedAt *string `json:"loaded_at"`
AgeHours float64 `json:"age_hours"`
Fresh bool `json:"fresh"`
SHA256 string `json:"sha256,omitempty"`
Error string `json:"error,omitempty"`
AttemptedAt *string `json:"attempted_at"`
}
out := make([]source, 0, len(lists))
total := 0
for _, s := range lists {
row := source{
Source: s.Source,
Entries: s.Designations,
Fresh: s.Fit(now, screenStale),
SHA256: s.Digest,
Error: s.Err,
}
if !s.LoadedAt.IsZero() {
t := s.LoadedAt.Format(time.RFC3339)
row.LoadedAt = &t
row.AgeHours = s.Age(now).Hours()
}
if !s.AttemptedAt.IsZero() {
t := s.AttemptedAt.Format(time.RFC3339)
row.AttemptedAt = &t
}
total += s.Designations
out = append(out, row)
}
code := http.StatusOK
if !ready {
code = http.StatusServiceUnavailable
}
return e.JSON(code, map[string]any{
"ready": ready,
"unfit": unfit,
"total_entries": total,
"sources": out,
})
}
}