DASH-DATA-005 — record-level confidence and freshness vocabulary, policies, precedence, and rollout semantics.
Record trust cues
Section titled “Record trust cues”Record-level confidence and freshness cues for publications (DASH-DATA-005). They let workspace members distinguish fresh, trusted, stale, conflicting, partial, and unknown evidence at the point of decision, without an opaque quality score. Field-level trust remains the field provenance inspector; this page covers the record-level layer on top of it.
Vocabulary and precedence
Section titled “Vocabulary and precedence”Two independent axes, documented in @platform/schemas (TrustFreshnessStateSchema,
TrustConfidenceStateSchema) and derived by @platform/utils (trust-cues):
| Axis | States | Decided by |
|---|---|---|
| Freshness | fresh, aging, stale, unknown | Fetch timestamp vs. freshness policy |
| Confidence | trusted, edited, partial, conflicting, unknown | Provenance field states |
Confidence precedence when several signals apply: conflicting > unknown > partial > edited > trusted. A record with one conflicting field is conflicting even if everything else is fine; a record with no attributable evidence at all is unknown; missing evidence alongside attributable fields is partial; deliberate edits alone are edited, not a trust failure.
Freshness policy (publication enrichment v1)
Section titled “Freshness policy (publication enrichment v1)”| State | Age of last_fetched_at |
|---|---|
fresh | ≤ 90 days |
aging | > 90 and ≤ 180 days |
stale | > 180 days |
unknown | timestamp missing or invalid — never rendered as healthy |
The policy lives in PUBLICATION_FRESHNESS_POLICY (@platform/utils); changing the numbers
changes the dashboard badges and the server-side filter together. It aligns with manual/periodic
enrichment cadence; per-source budgets are a later expansion behind the same schema.
Where cues appear
Section titled “Where cues appear”- Publications list: per-row freshness badge (desktop column + mobile card), freshness filter
(
all / fresh / aging / stale), served by the publication-query worker as boundedlast_fetched_atcomparisons against the same policy boundaries. The freshness header is not sortable: ingestion-date sorting was deliberately removed from this surface. - Provenance inspector: record trust summary with freshness + confidence badges and plain-language reasons (which fields conflict, which are missing, which were edited, fetch age).
Computation contract
Section titled “Computation contract”- Cues are derived on read from existing authorized contracts — the provenance response
(
record.last_fetched_at, per-field states) and list rows (last_fetched_at). No persistence, no new route, no worker change for the badge layer (ADR-0020). - Derivation is pure and bounded: O(supported fields) per record; perf tests pin list-scale and record-scale batches.
- Degraded input degrades explicitly: malformed field lists or missing timestamps produce
unknowncues, never a thrown error or a healthy default.
Observability and rollout
Section titled “Observability and rollout”- Filter usage is reported in
listPublicationsroute metrics (freshnessattribute); filter queries flow through the worker’s traced DB queries (db.logic: publication-list-*). - Rollout: enable the filter/badges on the publications list first; extend to further surfaces only
after interpretation is validated. Worker filter changes follow the standard production deploy +
route verification for
workers/*. - Rollback: remove the cue layer from affected routes (badges/summary are presentational; the filter param is optional and rejected-safe). No schema or data rollback exists because nothing new is persisted.
v1 limits
Section titled “v1 limits”- Publications only; person records and works keep their existing surfaces for now.
- The list-level freshness badge uses fetch timestamps only — record confidence needs the provenance inspector (per-record evidence is not loaded on lists by design).
unknownfreshness cannot be filtered server-side (a missing timestamp cannot be queried); it is always visible as a badge instead.