Phase 2 of the edge + control-plane architecture. A per-team local stack can now mirror its state UP to a central instance so judges get a fleet view — outbound-only, so it works from behind the room NAT. Central ingest (same api/, central-mode): - POST /instances/register + /instances/:id/heartbeat (fleet-secret gated) + an `instances` table and GET /instances (admin) fleet read. - PUT /teams/:id and POST /submissions accept an optional `site` tag; `site` column added to teams + submissions (grouping/filtering). - WS snapshot now carries instances; instance:update broadcast added. Reporter sidecar (deploy/lan/reporter/, opt-in `federated` compose profile): subscribes to the local WS feed and replays team/submission writes up to central, namespaced by SITE_ID (ids never collide) and site-tagged. Registers + heartbeats; failed writes queue in an in-memory outbox and backfill on reconnect. Proven end-to-end (local→reporter→ central) before commit. Also fixes a latent bug: listSubmissions selected snake_case columns but mapped camelCase, so GET /submissions summaries were missing teamId/ teamName/submittedAt. Aliased the columns; added a regression assertion. Co-Authored-By: Claude Opus 4.8 <[email protected]>
9 lines
270 B
Docker
9 lines
270 B
Docker
# APESS reporter sidecar — tiny outbound-only state mirror (edge → central).
|
|
FROM node:22-alpine
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production
|
|
COPY deploy/lan/reporter/package.json ./
|
|
RUN npm install --omit=dev
|
|
COPY deploy/lan/reporter/index.mjs ./
|
|
CMD ["node", "index.mjs"]
|