Files
sencho/frontend/src/components
Anso acfcb5567b fix(gitops): keep an application addressable when its evidence cannot be read (#2000)
* fix(gitops): keep an application addressable when its evidence cannot be read

A remote application whose evidence this hub cannot walk answered 404, the
same as one that does not exist, so an operator's only signal was an
application that had vanished. It now answers 503 with an
`evidence_unavailable` code when the row names the application but the
projection cannot be read, and the view says evidence is unavailable and
offers a retry. A row that never named the application still answers 404,
and an unreadable row stays 404 so the two cannot be told apart.

Validating that answer meant walking the projection properly. The detail
endpoint and the portfolio now check the same evidence: an artifact
qualification the facet and its latest evidence disagree on, a blank
generation or identity standing in for a real one, and a status from a
newer node all read as unknown evidence rather than as a convergence
claim. Convergence itself is now proven from the target evidence rather
than read off the rollout status, an Inline Blueprint no longer inherits a
Blueprint's claim, and a target the intent withdrew no longer keeps an
application in the attention queue.

Reading a remote row also authorizes it against the node that owns it
rather than the node the caller is viewing, and the phone portfolio says
partial when the merge cap dropped rows, not only when a node failed.

* fix(gitops): grade unfamiliar evidence as unknown instead of unavailable

Two shape validators rejected a vocabulary this build does not recognize, which
made a whole projection unusable rather than merely unfamiliar. An unusable
projection costs the operator its row: the portfolio shows an evidence
unavailable placeholder and the detail route answers 503. That claims the
evidence is unavailable, which is a stronger statement than an unfamiliar word
supports.

A last-known-good unavailable reason is now accepted on its structure and
graded as unknown evidence instead, on both sides of the wire. The browser
refusing the reason the server had already graded would only have replaced the
honest answer with a total read failure, and the two validators would have
disagreed about the same payload.

A drift identity kind is accepted the same way, so one unfamiliar kind costs
that row its label instead of the whole application. The label names the kind
it cannot read instead of rendering nothing. The kind list is a total record
over the identity union, so adding a kind without wording for it is a compile
error, and the lookup is own-property, so an inherited key reads as unfamiliar.

A blank reason is still rejected, and the mirror consistency rules still reject
an incoherent last-known-good record.

Verified: backend and frontend tsc clean; seven backend GitOps suites pass (446
tests); full frontend suite passes (3597 tests); frontend lint reports 0 errors.

* fix(gitops): restore the recovery-required rollback scope and drop a dead import

The conflict resolution carried this branch's three-member failed-runtime set
over the four-member set on the main branch, because this branch had reordered
the same three entries and the two edits merged without a conflict marker. A
target whose recovery is restoring or compensating reports recovery_required,
so it stopped counting as a failed target and the rollback dialog stopped
offering the failed-targets scope for exactly the stacks that need recovery.

The set now matches the main branch, with the type annotation kept. The
existing test covered recovery_failed only, so the scope is now asserted for
both recovery states.

Also removes a type import the same resolution orphaned. The type checker does
not report unused imports, so this surfaced only in the backend lint job.
2026-09-27 04:06:03 +00:00
..