---
title: "Readiness summary for this node's stacks"
method: GET
path: "/api/stacks/readiness-summary"
tags: ["Stacks"]
---

# Readiness summary for this node's stacks

`GET /api/stacks/readiness-summary`

## Request

- Base URL: `https://localhost:1852`
- URL: `https://localhost:1852/api/stacks/readiness-summary`
- Auth: HTTP bearer

Computes the canonical update and rollback readiness verdicts for the
stacks on this node, worst first, for the Fleet Readiness fan-out. It
runs the same verdicts that `GET
/api/stacks/{stackName}/update-readiness` and `GET
/api/stacks/{stackName}/rollback-readiness` return one stack at a time,
and adds no scoring of its own. The pass is bounded (an internal
deadline, a stack cap, and limited concurrency) and cached briefly, so a
truncated or stale result is reported as such rather than as a healthy
one. Requires `stack:read` permission.

## Headers

- `x-node-id` integer

## Response `200`

Per-stack readiness for the node.

- NodeStackReadinessSummary: Per-stack readiness as the node that owns the Docker socket computed it. The verdicts are the canonical update-readiness and rollback-readiness values passed through unchanged; this route adds no scoring.
  - `generatedAt` integer, required: Epoch ms of the pass that produced these verdicts, not of this request.
  - `truncated` boolean, required: True when the stack cap or the deadline cut the pass short.
  - `stale` boolean, required: True when the verdicts served are older than the freshness window, which is what an earlier failed pass leaves behind. Neither the Updates nor the Recovery cell may be `healthy` while this is true.
  - `stacks` StackReadinessRow[], required: Worst first; see `StackReadinessRow`. A stack missing from the array was not judged healthy, only left unevaluated.
    - `stack` string, required
    - `update` object, nullable, required: The canonical update verdict, or null when it was never evaluated: `{ "verdict": "ready" | "ready_with_warnings" | "review_required" | "blocked" | "unknown", "computedAt": <epoch ms|null>, "topReason": <string|null> }`. `topReason` is redacted before it leaves the node.
    - `rollback` object, nullable, required: The canonical rollback verdict, or null when it was never evaluated: `{ "overall": "ready" | "partial" | "not_ready", "computedAt": <epoch ms|null>, "topReason": <string|null> }`.
    - `unavailableReason` 'node_unreachable' | 'pilot_disconnected' | 'contact_stale' | 'probe_timeout' | 'workloads_exited' | 'workloads_partial' | 'workloads_unknown' | 'status_evidence_degraded' | 'status_evidence_stale' | 'update_blocked' | 'update_review_required' | 'update_ready_with_warnings' | 'rollback_not_ready' | 'rollback_partial' | 'snapshot_failed' | 'stacks_unknown' | 'summary_truncated' | 'summary_stale' | 'posture_partial' | 'posture_action_needed' | 'scanner_unavailable' | 'scans_stale' | 'scans_never_completed' | 'control_paused' | 'control_degraded' | 'control_unknown' | 'capability_absent' | 'domain_error', required: A closed vocabulary naming why a cell is not healthy. Each code belongs to one domain and maps to fixed copy in the client, which renders a code it does not know as "this check reported something this build does not know" rather than as healthy. `capability_absent` and `domain_error` apply to any domain.

## Other responses

- `401`: Authentication required. Provide a valid Bearer token.
- `403`: Insufficient permissions or license tier.
- `500`: Internal server error.

## Changes

- **2026-09-24** `d8373a6de800`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/studio-saelix/apis/sencho-api/changes/api/stacks/readiness-summary/get.md)

---

[API](https://skmtc.dev/studio-saelix/apis/sencho-api.md) - [All operations](https://skmtc.dev/studio-saelix/apis/sencho-api/llms.txt) - [OpenAPI document](https://skmtc.dev/studio-saelix/apis/sencho-api/revisions/1f7572eb735f?raw)
