feat(api): a host can say it is alive, and is told how often to

Second half of G1's "neslet registers against api.nestri.io and heartbeats".
Registration already worked; there was no heartbeat endpoint at all — grep for
it across apps/api and packages/core returned nothing, and neslet's own
main.rs says the same from its side.

POST /machine/heartbeat, machine credentials only. Two decisions worth stating
because neither is obvious from the diff:

**It returns the interval.** The auth middleware already touches lastSeen on
every authenticated machine request, so an endpoint that only did that would
add an endpoint and no capability. What a host cannot know on its own is how
often the control plane wants to hear from it, so the response carries the
cadence. A fleet whose interval can only change by shipping a new agent is a
fleet whose interval never changes.

**It takes no body.** neslet has a HostSummary ready to send, and week 2 owns
box state reporting. Accepting fields nothing acts on yet would mean a wire
shape we would have to keep, chosen before the thing that consumes it exists.

Online-ness is derived from lastSeen rather than stored: a host that stops
beating goes offline through the passage of time, which is the one mechanism
that cannot itself fail. Three missed beats, not one — a single missed beat is
a lost packet, and treating that as offline would make placement flap.

Also: the machine actor's teamID stops being optional. It was `...(teamId ? {}
: {})` in the middleware, a branch for a state that cannot exist now that
machine.team_id is notNull.

134 tests, 0 fail.
This commit is contained in:
Wanjohi
2026-09-03 21:42:15 +03:00
parent 6c1d407985
commit 4315510de8
5 changed files with 222 additions and 5 deletions

View File

@@ -80,7 +80,7 @@ export const auth: MiddlewareHandler = async (c, next) => {
properties: {
machineID: machine.id,
ownerUserID: machine.ownerUserId,
...(machine.teamId ? { teamID: machine.teamId } : {})
teamID: machine.teamId
}
},
next