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 /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

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: 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 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.

Terms of use ↗ · Embedding RADAR ↗ · ← back to RADAR