Skip to content

feat(contracts): canonical /v1 OpenAPI contract — fix #106, align #109 - #116

Open
taylormade7978 wants to merge 1 commit into
mainfrom
fix/106-v1-contract-alignment
Open

feat(contracts): canonical /v1 OpenAPI contract — fix #106, align #109#116
taylormade7978 wants to merge 1 commit into
mainfrom
fix/106-v1-contract-alignment

Conversation

@taylormade7978

Copy link
Copy Markdown
Collaborator

Why

Closes the design half of #106: the PWA client and the Rust server were built to divergent /v1 shapes (different routes and different DTOs), so the data screens 404 / fail to parse. There is no shared contract enforcing either side.

Realises the #109 decision — one canonical Rust engine serves the app. The reconciliation is REST-only against crates/server; the transitional Node services/data GraphQL shim (#107/#115) is retired once every resource is migrated.

What's here

  • contracts/openapi/made-v1.yaml — OpenAPI 3.1, the single source of truth. 11 paths, 27 schemas, across catalog / collection / leaderboard / shop / story.
  • contracts/openapi/README.md — decisions + the per-resource migration plan.

No behaviour change in this PR — it's the contract + plan the follow-ups conform to.

Decisions captured

  • REST-only, no GraphQL surface (aligns Design: MADE production game — overview + core-engine spec #109; lets the Node shim be deleted).
  • camelCase, client-shaped field names (they already mirror the Rust domain aggregates).
  • Envelope matches crates/server/src/http/envelope.rs: 2xx = { "data": … }, errors = { "error": { code, message, details? } }. Path schemas describe the payload under data.

Migration plan (each step keeps main green + the app working)

  1. Contract — this PR (supersedes Frontend and backend ship divergent /v1 API contracts — data screens 404 #106)
  2. catalogGET /catalog/cards, GET /catalog/expansions + enriched DTOs
  3. collectionGET /collection/{playerId}, PUT …/decks/{deckId}
  4. leaderboardGET /leaderboard (default season)
  5. shopGET /shop/items, POST/GET /shop/orders
  6. storyGET /story/{playerId}/missions, POST …/attempts (seeded campaign served from Rust, mirroring feat(data): real story-missions campaign (#114) #115)
  7. retire — delete services/data, web/src/api/graphql.ts, graphqlUrl; close feat(data): async data service — GraphQL queries + WS subscriptions + REST mutations #107/feat(data): real story-missions campaign (#114) #115 as superseded, Frontend and backend ship divergent /v1 API contracts — data screens 404 #106 as fixed.

Un-migrated resources keep using the still-deployed shim, so nothing breaks mid-migration.

Refs #106, #109, #107, #115.

🤖 Generated with Claude Code

Single source of truth reconciling the PWA client (web/src/api/types.ts) and
the Rust server (crates/server/src/http) /v1 shapes that diverged in #106.

REST-only, camelCase, {data}/{error} envelope matching envelope.rs. Establishes
the contract the server + client conform to; retires the parallel Node
services/data GraphQL shim (#107/#115) once every resource is migrated.

Adds contracts/openapi/{made-v1.yaml,README.md} with the per-resource
migration plan that keeps main green and the app working at each step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant