carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

The instance-report contract (/.carlos/instances)

Some CARLOS apps are internally plural: one route on the platform, many instances inside the app (Kass and its training instances, titogo and its event routers). The platform's registry sees the route; only the app knows its insides. This contract lets an app volunteer that knowledge to the console. It is entirely optional — an app that doesn't implement it renders in the console exactly as before.

What the app exposes

GET /.carlos/instances

on its public host (the same host the platform routes to it). Response:

  • Status 200, body a JSON array of instance objects:
[
  {"slug": "riders-2026", "status": "ready",    "region": "eu-west-1"},
  {"slug": "spring-camp", "status": "ready",    "region": "eu-west-1"},
  {"slug": "trial-run",   "status": "archived", "detail": "read-only since June"}
]
  • slug (string, required): the instance's stable short name. Entries without a slug are dropped.
  • status (string, recommended): one short word — the console renders it verbatim. Use the platform's route-status vocabulary where it fits (ready, starting, failed) plus whatever the app means (archived, migrating).
  • region (string, optional): where the instance's data lives.
  • detail (string, optional): one short human sentence.
  • Unknown fields are ignored; the contract may grow additively.

Limits: at most 100 instances and 64 KiB of body are read; beyond either, the report is treated as absent.

The endpoint must serve non-secret operational metadata only. It is unauthenticated by design (the console calls through the public host, like any visitor), so anything an app would not put on a status page does not belong in it. Apps that want the console table implement the endpoint; apps that don't, 404 — both are correct behavior.

What the console does

  • Polls the app's first ready, non-static route that has not opted into hibernation (routes sort by host). Hibernatable hosts are never polled: a poll could wake them, and the console must never wake an app to draw a table.
  • Uses a 1.5 s timeout and treats anything but a fast, valid 200 — connection refused, timeout, non-200, junk JSON, oversized body — as "not reporting". Not reporting is silent: the app page shows the ordinary route-level view, nothing more.
  • Caches per host for 30 s (successes and failures alike), so page reloads don't drum on tenants.
  • Renders the instance count and a slug/status/region/detail table in an "Instances" section on the app page.