Feed contract v1
Everything an integration needs. Generated on every run.
The item set includes the newest 100 records plus every corrected or noted published item,
regardless of age. IDs, original prose and publication dates stay unchanged. Sample items are
excluded. data.json.publication_counts.corrected_or_noted_all_time counts these
item notices across the complete database correction read; edition records remain separate.
Read
Concretely:
/feeds/v1/…, not /data.json.data.json is the dashboard's own payload — health rows, run economics, ledger
internals, whatever the page needed last week — and it changes shape whenever the page does.
An integration pinned to it breaks on a UI decision. The v1 feeds carry the
documented item fields and nothing else.Concretely:
data.json's url is
site-relative (/items/<id>), because the page that reads it is served from
this site. On your page it would resolve against your domain and 404. The
v1 feeds carry absolute URLs, and a test pins that they stay absolute. This is the
clearest single reason the split exists, so it is stated rather than left to be discovered.ENDPOINTS
Everything/feeds/v1/all.json
AI Platform Drift/feeds/v1/channel/ai-platform-drift.json
Security Advisory Triage/feeds/v1/channel/security-advisory.json
Regulatory Change/feeds/v1/channel/regulatory-change.json
Defense Contracting Rules not displayed publicly/feeds/v1/channel/defense-contracting.json
A channel feed exists for every configured channel, including channels the dashboard does not
display. The public switch governs the dashboard; it does not withdraw a feed a consumer has
been told to read.
ENVELOPE
{
"schema_version": 1,
"generated_at": "2026-09-24T05:30:00.000Z",
"channel": "defense_contracting", // null on all.json
"channel_label": "Defense Contracting Rules",
"public": false, // is it shown on the dashboard
"count": 12,
"contract": "https://radar.trulysovereign.com/docs/feed",
"items": [ … ]
}
ITEM FIELDS
| FIELD | TYPE | NOTES |
|---|---|---|
| id | string (uuid) | Stable for the life of the item. Use it as the dedupe key. |
| channel | string | Channel key, e.g. `ai_platform_drift`. Stable; labels may be reworded, keys are not. |
| headline | string | RADAR's one-line claim about the change. |
| what_changed | string | The change, factually, from the diff. |
| why_matters | string | The consequence for the channel's audience. |
| what_to_do | string | The action. Every published item has one — an item that cannot answer all three questions is never published. |
| severity | "action_needed" | "worth_knowing" | "fyi" | Closed set. A new value would be a major version. |
| action_type | string | Channel-specific vocabulary, e.g. `migrate`, `patch_now`, `deadline`. Open per channel — read it as a label, do not switch on the full set. |
| tags | string[] | From a fixed allowlist in config. May gain values; will not gain arbitrary ones. |
| confidence | number 0–1 | Model-reported confidence, not measured accuracy or a probability of correctness. Legacy missing values are unavailable, never 0%. |
| source_name | string | null | The source as named on the dashboard. |
| source_url | string | null | The page the change was detected on. |
| published_at | string (ISO 8601, UTC) | When RADAR published the item. Absolute, always UTC. |
| corrected_at | string | null | Set when the item was withdrawn. **A consumer must handle this** — see below. |
| correction | string | null | Why it was withdrawn. |
| url | string | Permalink to the item on radar.trulysovereign.com. |
| affects | {type,id,label}[] | What the change concerns. `type` is one of provider · model · product · api · package · cve · jurisdiction · regulation. **An empty list means "may apply to anyone", never "applies to no one"** — see below. Added in 1.1. |
| action_due | string (YYYY-MM-DD) | null | The date the reader must act by, **only when the source states one**. Never inferred from context. Added in 1.1. |
WHAT A CONSUMER MUST HANDLE
Corrections. RADAR withdraws items it got wrong rather than
deleting them:
RSS is different. It has no
Nulls.
Version. Read
An empty feed needs evidence.
Source fetch (optional addition).
Pipeline receipts are bound to the current workflow run and attempt plus database run ID. They require a returned persisted row, cannot predate invocation start, expire after 12h, and reject timestamps more than 60s in the future. Unbound historical run data cannot authorize pipeline continuation.
Status fields (optional additions).
Count denominators. Existing
corrected_at becomes non-null and correction says why.RSS is different. It has no
corrected_at and no update mechanism a reader
reliably honours, so a corrected item's <title> is prefixed
[CORRECTED], it gains a corrected category, and the correction is
the first thing in the <description>, above the original text. Filter on
the category if you are machine-reading it.
An item you have already acted on can be withdrawn later. Re-read the feed and honour
corrected_at — a consumer that only ever appends will keep showing a claim
RADAR has retracted.Nulls.
source_name, source_url,
corrected_at and correction are nullable. Everything else in the
table is always present.Version. Read
schema_version first and refuse a
major you do not know. Without that check, "we renamed a field" and "we broke every
integration" are the same commit.An empty feed needs evidence.
count: 0 means this feed contains no matching items in its rendered window.
It does not establish that nothing material changed. Check interpretation.status,
optional interpretation.verification_status and interpretation.execution, and coverage.state in
/data.json. Degraded, stale or missing evidence leaves quietness unverified.
Fresh generated_at and runs.latest describe generation and fetch, not model success.Source fetch (optional addition).
fetch reports the latest persisted fetch run: outcome
completed, partial, failed or unknown; run ID, finish time, sources checked, succeeded and failed, and failed source names.
Partial and failed results mean source monitoring is degraded even if interpretation completed. Unknown evidence cannot establish fetch health.
coverage.fetch_runs_with_errors counts completed fetch records with source errors in the coverage window;
any such record prevents verified quiet. Counts include all triggers; schedule attribution remains unavailable.Pipeline receipts are bound to the current workflow run and attempt plus database run ID. They require a returned persisted row, cannot predate invocation start, expire after 12h, and reject timestamps more than 60s in the future. Unbound historical run data cannot authorize pipeline continuation.
Status fields (optional additions).
interpretation.verification_status is healthy, degraded or unknown. The legacy interpretation.status retains its healthy/degraded values and reflects the queue check plus explicit failures; by itself it cannot verify the latest execution. interpretation.execution reports a sanitized outcome,
real observed_at and exit code. completed means worker completion, not necessarily a model call.
Unknown or absent execution evidence cannot establish current health. last_model_call_at retains the latest run-start timestamp with a recorded triage response. It is not a latest-attempt timestamp or proof of end-to-end success.
The default workflow grace is 12h for queue age; an explicit abort bypasses grace. Public queue counts use 0h grace.Count denominators. Existing
runs.total is the loaded window, up to 200, not all-time runs.
Optional runs.all_time and publication_counts.all_time expose database totals;
rendered, active, corrected/noted and edition-correction counts are separate. Precision is unmeasured until
50 resolved random reviews, excluding unresolved and targeted reviews. Item correction counts do not include edition records.VERSIONING PROMISE
Not breaking, no version change: adding a field; adding a value
to
Breaking, new major: removing or renaming a documented field; changing a field's type; adding a value to
A new major is published alongside the old one —
tags or action_type; adding a channel feed.Breaking, new major: removing or renaming a documented field; changing a field's type; adding a value to
severity; changing the meaning of an
existing field.A new major is published alongside the old one —
/feeds/v2/… appears and
/feeds/v1/… keeps working for a deprecation window announced on this page. A
contract that can be replaced in place is not a contract.