Prove the runtime→cloud app visibility seam end to end
The establishing issue for this project: get one app field — health — from the runtime's entity store to the browser, and pin the contract everything else builds on.
Deliberately excluded: deltas, snapshot epochs, mark-and-sweep deletes, Valkey, deploys. Each is a separate issue that depends on the seams this one opens. Proving the seam is the deliverable here, which is why this spans both repos rather than being split.
Runtime (mirendev/runtime)
anywhere.New() returns a Connector that currently encapsulates everything a reporter would need:
Connector.clientis unexported and itsMessageRouteris created privately insideNew(pkg/anywhere/anywhere.go:43-49), so nothing outside the package can register a handler or send a message.Client.OnConnectis a single last-write-wins field (pkg/anywhere/client.go:55), and theConnectoralready claims it atanywhere.go:66for time-sync and org-info. A second caller would silently kill NTP sync — make it fan out to multiple subscribers.coordinate.go:1531builds theConnectorand hands it straight to a goroutine without keeping a reference. Hold it on theCoordinator.
Then add an app-state reporter that sends app.snapshot on each connect. The data source already exists: ReportStatus lists apps at coordinate.go:1764 (c.eac.List(ctx, entity.Ref(entity.EntityKind, core_v1alpha.KindApp))) purely to compute workloadCount. App health is classified server-side in servers/app via the apphealth package.
Cloud (mirendev/cloud)
- Atlas migration adding an
appstable: identity (cluster FK, app name), derived org, health,observed_at,last_reported_at, soft-delete marker. Upsert on (cluster, app name). Migrations live indb/migrations, queries indb/queries. - sqlc queries plus a repository following the existing
services/clusterspattern. - An
app.snapshothandler registered throughRegisterBuiltinHandlers(services/cluster_channel/builtin_handlers.go:66). Every handler already receives an authenticatedclusterXID— derive the org from cloud's ownclustersrecord, never from anything the cluster asserts. - One org-scoped read endpoint returning the app list.
- A new
appvisibilityflag ininternal/labs/features.yaml(regenerate via labsgen), defaulting off.FeatureCloudDisksis the precedent: a default-off flag gating a whole page. - A minimal Apps list page behind that flag.
The contract this pins
Everything downstream depends on this shape, so it is the real output of the issue:
{
"type": "app.snapshot",
"data": {
"observed_at": "2026-08-11T18:00:00Z",
"apps": [
{ "name": "web", "health": "healthy" }
]
}
}
Health values originate in the runtime: healthy | degraded | starting | crashed | idle | unknown.
Note there is no epoch and no delete semantics yet — this snapshot upserts only. Sweep arrives with the epoch in the app-status correctness issue.
Done when
An integration test in services/cluster_channel asserts that a snapshot from an authenticated cluster lands in apps scoped to that cluster's org, and that a cluster cannot write rows into another org. Plus the Apps page rendering real data behind the flag.
Reading
- RFD-94 (
rfds/0075/0094-app-deploy-visibility.md) — "Ownership: who is authoritative, and when", "Sync: current app state (the ephemeral tier)", "Persistence in cloud". - RFD-96 (
rfds/0075/0096-app-deploy-dashboard.md) — "View inventory" item 1.