RATATOSKRATATOSK
Sign in

Understanding the data

This page explains Ratatosk's data model — changes, the three axes that classify them, severity, and what counts as "action needed". Terms used in the API, MCP, and feeds docs are all defined here.

One model, every surface. The website, the REST API, the MCP tools, alerts and feeds are all built from the same records with the same rules. When two surfaces answer "how many things need me here?", they answer with the same number.

Changes

A change is one thing a release did, extracted verbatim from the official release note. Every recorded line becomes a change — nothing is discarded — and each carries three axes.

family — what kind of thing it is

Value Meaning
security A security fix, or a dependency update made for security reasons
breaking Something that can break an existing setup: a removal, a changed default, tightened validation, a rename, an API version change
deprecated An announced future removal, with its time window

This is the axis a human subscribes by: "tell me about security and breaking, not deprecations."

bucket — how to act now

Value Meaning
action Applies to every install of that version. Do it
check Applies only if applies_if matches your setup. Resolve the condition first
plan Announced for later. Nothing to do today
other The full record: routine lines and bot dependency bumps

bucket is computed by code from the stored fields, never chosen by a model, and the same rule runs behind the website, the API, and the weekly email. other is excluded by default on every surface — it is most of the record.

applies_if — is it yours

A boolean expression, not a sentence:

"applies_if": {
  "evaluable": true,
  "mode": "any_of",
  "clauses": [
    { "kind": "api", "name": "ScheduleJobAlpha1", "verb": "uses", "polarity": "present" }
  ],
  "raw": null
}

mode is all_of, any_of, or universal (applies to everyone). When evaluable is true, match the clauses against your own manifests instead of parsing prose. When it is false, raw holds the original sentence — we say so rather than inventing structure we do not have.

change_kind

What sort of alteration it was:

Value Meaning
added Something new appeared
removed An existing feature, option, or flag is gone
deprecated Removal announced for something that still works
renamed An identifier changed name
value_changed A version, default, or limit moved
behavior_changed Same configuration, different result
constraint_changed Validation or a limit got stricter or looser
defect_corrected A defect was fixed

Key fields

  • matter_key — the identity of the underlying matter, stable across releases and branches. The same security roll-up landing on five branches shares one key. /v1/matters/{key} returns every landing.

  • subjects — the identifiers this change touches, for matching by name against your manifests and configs. kind has these values:

    kind Meaning
    api API group/version (e.g. the subject of a v1beta1 → v1 promotion)
    crd Custom resource definition (CRD) name
    feature_gate Feature gate name
    flag Command-line flag (e.g. --listen-client-http-urls)
    metric Metric name or prefix
    config_field Field name in a config file or chart values
    extension Plugin or extension point name
    dependency Dependent library or component name
    cve CVE identifier
    advisory Security advisory ID (GHSA-… and other official project/GitHub notices)
    subsystem Subsystem name, when no single identifier pins it down
  • advisories — the CVE/advisory ids this change cites, each with the ledger's current severity (see below).

  • quote — the source line, copied character for character and never translated, so every change traces back to the original note.

  • window — timing, when the note gave it: introduced_in, deprecated_in, removed_in.

  • version_rank — a notation-independent array for ordering (v0.42.0[0, 42, 0]). null when the project's tag cannot be ordered numerically (monorepo tags like flagd/v0.16.1, channel tags like lts-4081.3.8); those are excluded from range comparisons rather than guessed at.

A real example

An actual change as the API returns it (fields not relevant here omitted):

{
  "change_id": "buildpacks:v0.40.9:83576398",
  "matter_key": "buildpacks/advisory:cve-2026-41178",
  "project": "buildpacks",
  "version": "v0.40.9",
  "version_rank": [0, 40, 9],
  "family": "security",
  "actionability": "act",
  "bucket": "action",
  "kind": "value_changed",
  "applies_if": { "evaluable": false, "mode": "universal", "clauses": [], "raw": null },
  "advisories": [
    { "id": "CVE-2026-41178", "severity": "medium" },
    { "id": "GO-2026-5158", "severity": "medium" }
  ],
  "subjects": [
    { "kind": "dependency", "name": "go.opentelemetry.io/otel", "name_full": "go.opentelemetry.io/otel", "role": "changed" },
    { "kind": "cve", "name": "cve-2026-41178", "name_full": "CVE-2026-41178", "role": "changed" }
  ],
  "window": { "introduced_in": "v0.40.9" },
  "quote": "`go.opentelemetry.io/otel` | v1.43.0 → v1.44.0 | GO-2026-5158 / CVE-2026-41178 — baggage header not length-capped | Medium",
  "source_url": "https://github.com/buildpacks/pack/releases/tag/v0.40.9",
  "seq": 1487
}

The REST API and MCP tools return this JSON unchanged.

Severity

Severity belongs to the advisory, not to the change. Each entry in advisories carries the severity read from the official source — cve.org, the GitHub advisory database, OSV — and re-read when it is later assigned or revised. The page and the API follow without re-analysis.

A change with advisories: [] is not "unrated". It means the release note cited no advisory id.

Release summaries expose the highest severity across a release's advisories as max_severity.

Note that one CVE can legitimately carry different severities in different projects: each source rates it for its own context.

The release detail page

A release detail page records every entry of the official release note and groups the ones that ask something of you into the three buckets above, plus the rest:

  • Action neededbucket: action.
  • Check if affectedbucket: check; each item shows its "Applies if …" condition.
  • Plan aheadbucket: plan, each with its time window (e.g. deprecated since v1.9.0 · removal planned in v2.0).
  • Other changes — the rest of the record, collapsed: verbatim quotes grouped by kind. Security-motivated entries are always shown as their own group, never buried.

When a release note says the same thing twice, the page counts it once — the record keeps both, the screen folds them.

What "action needed" means

The web home, email alerts, and personal RSS filters all use the same criteria: the action bucket, split by family.

  • security — security fixes. All of them, regardless of severity.
  • breaking — compatibility-breaking changes.
  • deprecated — announced removals.

The "action needed" window on the web home is the last 7 days (rolling). The type=security / type=breaking / type=deprecated filters in email alerts and personal RSS filter by the same three families — see Alerts and feeds.

Auditable silence

A release with zero changes is an answer, not a gap: it means the note was read and nothing in it needs you. The release summary still reports notes_total, the number of lines recorded, so you can tell "read and routine" from "not read".

Timestamps and time zone

Ratatosk stores, displays, and aggregates every timestamp in UTC. A release date is the publication time reported by GitHub (published_at).

Which projects are covered

Ratatosk tracks the projects in the CNCF landscape; the current list and each project's analysis history are at /projects.

Next steps