0.84 — Generated servers refuse what their OpenAPI refuses, and generated UIs call their binding's routes
· 4 min read
0.84 — Generated servers refuse what their OpenAPI refuses, and generated UIs call their binding's routes | ESS0.84.0 adds no format: generated Rust servers refuse a malformed Timestamp and an undeclared JSON member at decode, authored success acts assert that no error came back, denied-grant scenarios reach ranked views and every ungranted actor, and a generated UI calls the routes its HTTP binding serves.ESSfield-noteessfield-noteadopterdevelopertry-spec-driven-developmentresearch
0.84.0 adds no source, scenario or suite format. It changes what generated servers admit, what an authored success step checks, which denied-grant scenarios synthesis writes, and how generated UIs reach a server. The changelog lists every change; this note covers each of them.
Generated servers refuse what their OpenAPI refuses
- The generated Rust codecs refuse at decode, before anything is stored, a
Timestampthat is not an RFC 3339date-timeand a member a closed JSON object does not declare. The server answers400, or the binding'srefusals.malformed, naming the member's path (#707). - Before, the server stored the text or dropped the member, while the OpenAPI document it serves
already refused the body. A struct declaring
undeclared_fields: ignoredand aJsonvalue stay open. - The same decoders read the log, so
decode_system_eventrefuses an envelope an older server wrote with a free-textTimestampor an extra member in a closed struct. - The generated Go server refuses a top-level JSON command member no input field names, on bound
and derived routes, and reads a
Timestampwith the same grammar as the Rust server. - Known limit: an
Optionalmember sent asnullis still taken as absent by the generated Rust server, while its served OpenAPI refuses the body. It is tracked as a backlog story.
An authored success act asserts no error
- An authored act whose
outcome:names a branch that declares no error now also requires that no error came back. A target answering the success branch under its own name with an error fails the step; it used to pass on the outcome name alone. - No suite format moves. A library caller assembling an authored suite by hand selects the format
with
select_fresh_format_forand runs it withRunner::run_admitted, as the CLI does.
Denied-grant scenarios
- Synthesis writes
<command>/grant/deniedfor a command acting on an existing row beside a view ranked byorder_by(#712). <view>/grant/read/deniedreads the view as every ungranted actor of the view's own domain, then as no actor. Before, it read one actor of any domain, so a target admitting an ungranted actor of the view's domain passed.
Generated UIs call their binding's routes
ess generate uiandess ui run --tuitake--http <binding>: the generated route table carries the method and path theess-http/1binding declares, so the UI calls the routes the server generated for the same binding serves (#713).- A command served on
getis sent without a body, and React refuses a path value of.or...
Renderer fixes
- The terminal renderer addresses a row action's confirm by the view's row key, and a record's actions see the row the record shows.
- An account menu entry keeps its
setsandnavigatein React.ess ui checkrefuses an entry a renderer would drop, an entry that does not read as an action, andsetsbesidedoes,navigateoropens.