What
The partner's client page reports what the REGISTRY says, not whether the restaurant's app is actually running. Add the per-tenant health signal the platform already has.
Current state (on origin/develop)
app/(control)/dashboard/clients/[id]/page.tsx renders ClientTenantPanel from the registry entry. client-tenant.ts is explicit about what "live" means there:
kind: "live" — Provisioned: the registry entry is the answer to every question on the panel.
But a registry entry proves a founder merged a PR — not that the build and provision succeeded, and not that the app is up now. lib/tenant-liveness.ts documents exactly this: registry status: active is "a manual follow-up commit that nothing automatic writes and nothing automatic reads".
The instrument already exists
probeTenantHealthy (lib/tenant-health.ts, an unstable_cache-wrapped HTTP probe) is what the OWNER-facing surfaces already use:
components/control/OwnerDashboard.tsx:176
lib/go-live-notify.ts:125
The partner panel simply never calls it.
The ask
Extend the partner's client page with the same earned signal — observed serving / not serving / could not check — so the person who sold the tenant sees the product they sold is actually up, not that a registry entry exists.
Design constraints already settled elsewhere, keep them:
- Partner reads stay scoped by
partnerId (requirePartner() + the scoped findFirst) — ADR-009's security posture, unchanged.
- The probe is server-side and cached; no new client-side fetch surface.
- Degrade honestly: "could not check" is a sentence, not "down" — the same rule
tenant-liveness.ts encodes for the owner surface ("NEVER claim ready from" an unobserved state). The three non-live branches (awaiting / unreadable / unlisted) stay as they are.
Acceptance criteria
Ref: workspace docs/plans/BACKLOG.md, Track S queue row "Per-tenant health on the partner panel"; sofra docs/adr/ADR-009-partner-program-model.md.
What
The partner's client page reports what the REGISTRY says, not whether the restaurant's app is actually running. Add the per-tenant health signal the platform already has.
Current state (on
origin/develop)app/(control)/dashboard/clients/[id]/page.tsxrendersClientTenantPanelfrom the registry entry.client-tenant.tsis explicit about what "live" means there:But a registry entry proves a founder merged a PR — not that the build and provision succeeded, and not that the app is up now.
lib/tenant-liveness.tsdocuments exactly this: registrystatus: activeis "a manual follow-up commit that nothing automatic writes and nothing automatic reads".The instrument already exists
probeTenantHealthy(lib/tenant-health.ts, anunstable_cache-wrapped HTTP probe) is what the OWNER-facing surfaces already use:components/control/OwnerDashboard.tsx:176lib/go-live-notify.ts:125The partner panel simply never calls it.
The ask
Extend the partner's client page with the same earned signal — observed serving / not serving / could not check — so the person who sold the tenant sees the product they sold is actually up, not that a registry entry exists.
Design constraints already settled elsewhere, keep them:
partnerId(requirePartner()+ the scopedfindFirst) — ADR-009's security posture, unchanged.tenant-liveness.tsencodes for the owner surface ("NEVER claim ready from" an unobserved state). The three non-live branches (awaiting/unreadable/unlisted) stay as they are.Acceptance criteria
probeTenantHealthy(or an explicit "not checked" state), not from the registrystatusalone.Ref: workspace
docs/plans/BACKLOG.md, Track S queue row "Per-tenant health on the partner panel"; sofradocs/adr/ADR-009-partner-program-model.md.