feat(ci): probe production federation — nothing was checking whether remotes load - #800
Merged
Conversation
…remotes load The portal currently shows 13 products and NONE of them renders its UI. Trying to diagnose that surfaced the reason it went unnoticed: no check in this repo ever asks production whether a federated remote actually loads. prod-smoke.yml polls a health endpoint post-prod-e2e.yml drives user flows e2e.yml runs check-federated-assets.mjs — against a LOCAL preview So the failure the shell is most prone to — an entry or chunk that 404s in prod while every green check in the pipeline describes a different artifact — had no detector at all. Worse, the portal actively reported these apps as healthy. apps.ts:206 is `return response.status < 500`, with the comment "Consider 2xx, 3xx, 4xx as healthy". A remote whose assets 404 is reported HEALTHY. That is not a diagnostic gap, it is a diagnostic that says the opposite of the truth, and it is why "13 products, none loading" looked like a working system. Fixing that health check is a separate change; this one builds the instrument that can prove what is actually being served. WHAT IT DOES NOT ASSUME. The serve path is a free variable (CLAUDE.md, "slug, display name, and the federated serve path are THREE INDEPENDENT questions"). Most repos publish /apps/<slug>/remoteEntry.js (Vite assetsDir: ''); FuzeFront's own fuzequality publishes /apps/<slug>/assets/remoteEntry.js. So each app is probed at BOTH candidates and the report names which answered — it DISCOVERS the layout rather than re-asserting the convention it exists to check. An app answering at neither is the finding, not a probe bug. Chunk verification delegates to the existing check-federated-assets.mjs, which already encodes the two things that make this real rather than a re-derivation of config: chunk specifiers resolve against remoteEntry.js's OWN url, and a 200-with-HTML body is the 404 it really is. Unauthenticated by design: it probes static asset paths, not GET /api/apps, which needs a token AND is scoped by org membership + visibility — so it could not enumerate every app even with one. runs-on: ubuntu-latest, deliberately NOT the fuzefront ARC pool. A prod diagnostic has to be runnable exactly when the self-hosted pool is saturated, which is when an incident is most likely under investigation. NOT VACUOUS, and mutation-tested in both directions rather than only asserted: empty slug list -> exit 2 (a probe that checks nothing never passes) unreachable host -> exit 1, "no remoteEntry served" entry + chunk both JS -> exit 0 entry JS, chunk 200 + HTML -> exit 1, "BROKEN", 1 referenced / 0 loadable The last case is the one that matters: it is precisely the blank-panel failure, and a probe that only fetched the entry would have called it green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GaPa3JgrVNtWrGvqQEAEqv
Path-scoped, not on every PR — it hits LIVE production. It fires when the instrument changes, so a change to the detector is validated by using it rather than first executing for real only after it merges. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GaPa3JgrVNtWrGvqQEAEqv
…cated a 404 The first run reported 16 of 16 apps broken. Fifteen of those are real. The sixteenth, `keys`, was the probe's own bug. The frozen contract allows an absolute http(s) `remoteEntry` for remotes hosted outside the cluster, and fuzekeys uses one: https://keys.prod.fuzefront.com/apps/fuzekeys/remoteEntry.js The probe only ever tried /apps/<slug>/... on the host origin. For fuzekeys that 404 was CORRECT — nothing is supposed to be served there — and the probe turned it into a failure report. A probe that manufactures a failure is as harmful as one that hides a real failure: both make the whole report untrustworthy, and this one would have sent someone to debug an ingress that is not meant to exist. Each entry is now either `slug` (probe the two same-origin layouts) or `slug=<absolute url>` (probe exactly what the manifest declares). The workflow default carries fuzekeys in the second form. Verified, not assumed — the absolute form is proven to actually bypass --base: --base https://app.example.invalid --slugs aliased=http://127.0.0.1:8791/... -> exit 0, entry reported as the absolute URL. If the code had still resolved against --base, that case would have failed. Same-origin form re-tested unchanged, and the four earlier non-vacuity cases still hold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GaPa3JgrVNtWrGvqQEAEqv
izzywdev
approved these changes
Aug 26, 2026
izzywdev
left a comment
Owner
There was a problem hiding this comment.
All CI gates pass (gate-authz, gate-ds-conformance, gate-identifier, gate-frames-first, gate-test, gate-lint, gate-build, gate-sast, gate-toolchain, gate-version, gate-localup, etc.). Approving per governance policy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The portal shows 13 products and none of them renders its UI. Diagnosing that surfaced why it went unnoticed: no check in this repo ever asks production whether a federated remote actually loads.
prod-smoke.ymlpost-prod-e2e.ymle2e.ymlcheck-federated-assets.mjs— against a local preview, never prodSo the failure this shell is most prone to — an entry or chunk that 404s in production while every green check in the pipeline describes a different artifact — had no detector at all.
The portal was reporting the opposite of the truth
backend/src/routes/apps.ts:206:A remote whose assets 404 is reported healthy. That is not a gap in observability, it is observability asserting the opposite of reality, and it is why "13 products, none loading" looked like a working system.
Fixing that health check is a separate change — this PR builds the instrument that can prove what is actually being served, because I did not want to change the health semantics before having something that could measure the result.
What it does not assume
The serve path is a free variable (CLAUDE.md — "slug, display name, and the federated serve path are THREE INDEPENDENT questions"). Most repos publish
/apps/<slug>/remoteEntry.js(ViteassetsDir: ''); FuzeFront's ownfuzequalitypublishes/apps/<slug>/assets/remoteEntry.js.So each app is probed at both candidates and the report names which one answered. The probe discovers the layout instead of re-asserting the convention it exists to check — an app answering at neither is the finding, not a probe bug.
Chunk verification delegates to the existing
check-federated-assets.mjs, which already encodes the two things that make this real rather than a re-derivation of config: chunk specifiers resolve againstremoteEntry.js's own URL, and a 200-with-HTML body is the 404 it really is.Not vacuous — mutation-tested in both directions
A probe that can only fail is as useless as one that can only pass, so both were proven, not asserted:
❌ entry, both candidate paths named✅❌ chunks, "1 referenced — 0 loadable, 1 broken"The last row is the one that matters: it is exactly the blank-panel failure, and a probe that only fetched the entry would have called it green.
Design notes
GET /api/apps— that needs a token and is scoped by org membership + visibility (scopeAppsQuery), so it could not enumerate every app even with one.runs-on: ubuntu-latest, deliberately not thefuzefrontARC pool. A prod diagnostic has to be runnable exactly when the self-hosted pool is saturated, which is when an incident is most likely under investigation.What this does and does not claim
It does not identify the root cause of the current outage — it is the instrument that can. What I established while building it, from the repos rather than from prod:
react: ^19.0.0, matching the host'srequiredVersion. The React-18 singleton mismatch is fixed in source, so it is not the current explanation unless prod is running older images.fuzeexecutive,fuzedeploy,fuzepicker,fuzexare SHA-pinned and current, whilefuzesales,fuzecontact,fuzebisit at0.1.0andfuzemarketat the mutablelatest. Stale images explain some products but cannot explain all of them.fuzekeysis the one remote declaring a cross-originremoteEntry(https://keys.prod.fuzefront.com/...) rather than a same-origin path.The probe's first run on this PR is what turns that into an answer.