Skip to content

v0.14.0 — Stateful stubs: POST creates what GET returns

Choose a tag to compare

@omercelikdev omercelikdev released this 27 Jul 19:46

The second G19 sandbox vertical (ADR 0011): the opt-in state response directive turns matched stubs into a mini backend — dynamic CRUD state, the most-requested capability class for stub servers.

The state directive (G19b)

"response": {
  "status": 201,
  "body": "{\"id\":\"{{state.id}}\",\"order\":{{state.body}} }",
  "state": { "operation": "create", "collection": "orders" }
}
  • Five operations on tenant-scoped collections: create, read, update, delete, list
  • id/document are template expressions over the request (path segments, body, query); absent create ids are generated, an absent document stores the request body verbatim
  • Results render as {{state.id}}, {{state.body}}, {{state.version}}, {{state.count}}, {{state.list}} — declaring the directive enables templating, no transformer needed
  • Misses behave like a real API: unknown ids answer a per-stub missStatus (default 404); serve-time guards answer 413 over the body cap and 422 for non-JSON — nothing half-lands
  • State is shared with /__admin/resources and the upcoming dashboard screens — what a stub creates, the admin API sees immediately
  • Fully opt-in: no directive → zero behavior change (proven by test and by the untouched differential suites)

Architecture kept honest

The engine never interprets state: StateDirective is pure data, applied by the templating renderer behind the existing IResponseRenderer seam — the reference-parity surface does not move.

Validation (ADR 0011 addendum matrix): end-to-end wire loop with a real HttpClient (POST→GET→PUT→LIST→DELETE, tenant isolation, guard statuses, zero-change proof), 12-case semantics table, Stryker 100 % on the directive logic (44/44), 206 oracle-backed differential tests green untouched.

Docs: responses guide with copy-paste examples.

🤖 Generated with Claude Code