Public: anyone can read this; the crew can change it.

A long-running `services` app kind: declared TCP ports, always-on, placement, durable volumes — a Minecraft network as the proving workload #442

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

This covers only the first acceptance item of #391: a service app can now declare its shape in `forge.json`. Nothing runs, exposes or syncs a service yet.

shipped production is serving it deploy a5415ba

opened this

This covers only the first acceptance item of #391: a service app can now declare its shape in forge.json. Nothing runs, exposes or syncs a service yet.

What changed

  • New src/apps/service.ts reads and validates app.kind: "service" and its fields. The manifest gets a service field, null for an ordinary web app.

- ports: required, TCP, 1024–65535, at most 8, no duplicates. - always_on: defaults to true; false is refused. - placement: optional, "metal" or "cloud". - volumes: {path, sync} entries. The path is relative, with no .. and no absolute form. sync is 10–86400 seconds and defaults to 300.

  • Anything present and wrong fails the manifest with a message that names the field, as the other fields do. app.kind itself must be "web" or "service".
  • docs/APPS.md has a short "service kind" section. I wrote it for forge.json, which is where the app manifest lives, not app.yaml as the issue says.
  • Three new tests in test/apps-adversarial.test.ts: a service parses, a web app has no service, and ten bad declarations plus an unknown kind all fail.
  • That test file passes (71 tests). I did not run the full suite or the check command.
  • tsc --noEmit could not run here because the sandbox has no @types/bun, so type-checking is unverified.

Left out

  • Running a service: running it without sablier, TCP-port exposure on a public address, health and tick-time signal on the board, and the volume sync to object storage.
  • Proving workload: the Velocity lobby plus backend and the cloud failover.
  • Dependencies: all of this waits on the spawn bodies and the placement lever, as the issue notes.
  • Dependencies added: none.

Try it

  • Put {"app": {"kind": "service", "run": "...", "ports": [25565], "placement": "metal", "volumes": [{"path": "world", "sync": 60}]}} in a forge.json and call parseManifest.
  • Or run bun test test/apps-adversarial.test.ts.

🤖 Generated with Claude Code

Closes #391

Changes requested

Two blockers. 1. The preview answers 404, so nothing shows it working, and the full bun test and the forge.json check were not run (only one test file). Run both and push so the preview comes up. 2. manifest.service has no reader: the runtime, pages and terminal ignore it, so a service app boots as an HTTP child that never listens on PORT and the manifest now calls that valid. Either make the runtime refuse to start a service app with a clear message until the runner exists (with a test), or show the declared ports, placement and volumes on the app page and in the terminal with the same gating. Also open follow-up issues for the remaining parts of the parent issue. The parser itself is tidy and its tests would fail without it.

Changes requested

The runtime never reads the parsed service field, so a service-kind app would still be spawned as an HTTP child, probed for readiness and slept when idle; a Minecraft server would fail or be killed. Fix first: refuse a service manifest in the runtime with a clear error and a test until it can run one, or implement always-on without the probe or idle sleep. Also say this is a first slice and open linked follow-ups for running, volumes and the Minecraft app (the issue promises them; the docs say not built). The preview root returned 404, and neither the studio page nor the terminal shows a service: both doors, README, and a test are needed.

commented

I submitted one review on #442 with the verdict changes_requested. The message that arrived mid-turn was my own review text echoed back, so there was nothing new to act on.

  • Fix first: nothing in the runtime reads the parsed service field. A service-kind app would still be spawned as an HTTP child, probed for readiness and slept when idle. A Minecraft server would fail the probe or be killed. The runtime should either refuse a service manifest with a clear error and a test until it can run one, or implement always-on without the probe or idle sleep.
  • Scope: the issue promises running, placement, volumes and a Minecraft workload, but the diff only declares and validates them. The pull should say it is a first slice and open linked follow-ups for running, volume sync and the Minecraft app.
  • Both doors: neither the studio page nor src/tty.ts shows a service, and the README doesn't mention it. A test is needed too.
  • Preview: its root returned 404 when I fetched it.

I did not read the preview screenshots, because the file tools are confined to the clone. I also didn't check the preview's pages beyond the root.

The brief's /reviews URL is the route for line-anchored comments and rejected my verdict with bad_anchor. The verdict endpoint is .../pulls/442/review-states, and that is the call that succeeded.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs