0094 — API-first playability¶
Status¶
Folded — points 1–3 closed against tip 02c99117 (LEG-258). Point 1 (every action
REST-reachable, WS push-only) and point 3 (headless playthrough suite,
test_core_loop_playthrough.py, auth→first-login→move→dock→trade→contract→combat) remain
shipped; the README design-pillars section carries the pillar. Point 2 (one canonical endpoint
per action): the ADR's named genesis-deploy twin was removed 2026-08-04 — sole live deploy is
POST /planets/genesis/deploy (api/routes/planets.py:1869-1872 documents the removal;
api/routes/genesis.py retains only GET /status/{planet_id}, /available, /quote).
Systematic sweep (WO-CANON-SWEEP-ADR-0094, 2026-08-10) inventory + later residual closures:
| Overlap | Canonical | Overlap / note |
|---|---|---|
| Citadel defense construct | POST /planets/{id}/grid/place |
✅ Shipped — player-client migrated (PR #581 / tip 02c99117); citadelAPI.constructBuilding posts /grid/place; overlap /buildings/construct / /defense/construct have zero PC callers |
| Genesis deploy | POST /planets/genesis/deploy |
✅ Retired — twin POST /genesis/deploy removed 2026-08-04 (zero callers); planets path is sole deploy (planets.py:1869-1872; tip 02c99117) |
| Single-drone deploy | POST /drones/deploy (batch) |
POST /drones/{id}/deploy — retired cycle-44 (WO-CLEANUP-DRONE-DEPLOY-ORPHAN-ENDPOINT, PR #539) |
| Admin vs player twins | n/a | /admin/fleets/* vs /fleets/*, /admin/drones/* vs /drones/*, etc. — intentional dual surface (admin scope ≠ player); out of point-2 scope |
Exact same-path mounts still present (prefix-collision hygiene, not player-action dups):
GET /sectors + planet/port variants on both admin.py and admin_comprehensive.py.
Scope covers the API-first enabling property, the endpoint-canonicalization and test-guard
commitments, and the text-only-client / player-crafted-UI horizons (non-normative, no build
claim). The bring-your-own-ARIA horizon is split out to ADR-0096,
which remains Proposed pending an automation-policy ruling. No Distributed-fold residual
remains — point 2 complete (genesis twin retired; citadel construct PC ✅ #581; single-drone
overlap retired #539). (re-verified 2026-08-17 — tip 02c99117, LEG-258)
Context¶
The original design intent of SectorWars 2102 is that the entire game can be played via the API — a raw HTTP client, with no web frontend, can reach playable state and drive the full core loop. Until now this intent was stated nowhere in canon: no design pillar, ADR, or FEATURES note names it, and nothing protects it.
A 2026-07-10 audit of the shipped route surface found the property already holds in practice: all 16 sampled core-loop areas (auth, first-login, movement, docking, trading, haggling, combat, contracts, colonization, citadel-grid building, ship purchase, ship upgrades, genesis, mining, regional governance, teams/fleets) are fully drivable through documented REST endpoints, with the WebSocket bus remaining push-only exactly as SYSTEMS/realtime-bus.md prescribes ("the REST API is the request/response channel"). The property emerged from the thin-client rule (ARCHITECTURE/services.md — "No business logic — all state changes round-trip through the API") rather than from an explicit decision — which means a future rich-client feature or WS-only mutation could silently break it.
Motivating horizons (non-normative)¶
The pillar exists to keep a family of possible futures open, none of which is itself committed by this ADR: a first-party text-only client that plays the game purely through API calls, and player-crafted third-party UIs built against the same surface. A third horizon — a player attaching their own external intelligence to the game through API calls of their own — stands on this same pillar but raises an automation/fair-play question this ADR does not resolve; it is tracked separately in ADR-0096. These are exploratory directions, recorded here so the reason for the pillar survives alongside the rule. What this ADR decides is only the enabling property: the API surface is the complete game.
Decision¶
- Every shipped gameplay action is performable via the REST API without any web client. The WebSocket bus stays push-only: no gameplay mutation may be WS-only.
- One canonical endpoint per action. Where overlapping routes exist for the same action (e.g. genesis deploy, building placement), one is designated canonical and the others carry deprecation pointers.
- The property is test-guarded: a headless playthrough suite drives the core loop via API calls only (auth → first login → move → dock → trade → contract → combat), so a regression of this pillar fails a gate instead of shipping.
- Boundary — this does not bless unattended autonomy. ADR-0092's session-live rule stands: ARIA delegation acts only while its player's session is live, and offline autonomy remains rejected as a botting surface. API-first playability means a live, authenticated client acting on its own behalf — human at a terminal, script, or otherwise — has full access to the game's verbs; it does not change what any client may do while its player is absent.
Consequences¶
- Review posture: "does this change keep the action reachable via REST?" joins the review checklist for gameplay features.
- First-login remains the one path where API-reachable ≠ trivially scriptable — the guard-persuasion exchange takes free text — but the difficulty matrix's Escape Pod fallback guarantees a playable state is always reachable, which satisfies this pillar.
- The headless playthrough suite (point 3) and the endpoint-canonicalization pass (point 2) are tracked as work orders.
- The README design-pillars section gains this pillar.
- The bring-your-own-ARIA horizon is tracked separately in ADR-0096, gated on an automation-policy ruling for player-operated external automation acting through the API.
Related docs¶
SYSTEMS/realtime-bus.md— REST/WS channel separationARCHITECTURE/services.md— thin-client mandate- ADR-0092 — session-live / anti-botting boundary
- ADR-0096 — bring-your-own-ARIA horizon, gated on the automation-policy ruling