v0.14.0 — Stateful stubs: POST creates what GET returns
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/documentare 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/resourcesand 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