fabro/lib/crates
André Mazoni 6d55875645
fix(store): keep pre-#530 runs loadable (serde default on run.prepare) (#554)
## Summary

Runs created before #530 disappear from the run list after upgrading,
because
their persisted `run.created` event can no longer be deserialized.

#530 renamed `RunPrepareSettings`'s field from `commands: Vec<String>`
to
`steps: Vec<PreparedStep>`. That struct is persisted inside the
`run.created`
event (`WorkflowSettings.run.prepare`). Events written by older versions
carry a
`prepare` object with a `commands` key and **no** `steps` key. Because
`steps`
had no serde default, deserializing such an event fails with:

```
Serialization error: missing field `steps`
```

`warm_projection_cache` catches that error per-run and **skips** the run
(`fabro_store::slate: Skipping run during projection cache warmup`), so
every
pre-#530 run silently vanishes from the run list. The event data is
intact on
disk — it just can't be read back.

This is an event-schema back-compat break: any type persisted in an
event must
stay readable across the field renames/additions that happen after it
was
written.

## Fix

Add `#[serde(default)]` at the container level on `RunPrepareSettings`,
so a
`prepare` object missing `steps` (and/or `timeout_ms`) falls back to the
existing `Default` impl (empty steps, product-default timeout) instead
of
failing the whole run. The unknown legacy `commands` key is ignored (the
struct
has no `deny_unknown_fields`).

- New runs always serialize explicit `steps`, so nothing changes for
them — the
  #530 feature is unaffected.
- Pre-#530 runs load again with an empty prepare phase, which is
faithful: those
  runs already executed; this only rebuilds a read model for display.

`#[serde(default)]` is already the evolution idiom in this same struct
tree
(e.g. `RunModelSettings.controls`).

## Test plan

- [x] `cargo test -p fabro-types` — added two regression tests that
deserialize
the exact pre-#530 event shape (`{ commands, timeout_ms }`, no `steps`)
      and an empty object, asserting both load instead of erroring.
- [x] Built the patched server and pointed it at a real
`~/.fabro/storage` that
had 119 pre-#530 runs being skipped. After the fix, 0 runs are skipped
and
      all 119 appear in `GET /api/v1/runs`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Bryan Helmkamp <bryan@brynary.com>
2026-07-07 22:20:44 -04:00
..
build-support fix(build): refresh embedded git sha on branch commits 2026-05-09 14:10:04 -04:00
fabro-acp Resolve run.prepare.steps env and interpolation at the run boundary (#530) 2026-07-01 10:31:26 -04:00
fabro-agent fix(mcp): honor inline enabled=false and per-server tool_timeout (#520) 2026-06-24 16:17:27 -04:00
fabro-api feat(server): mcp-servers HTTP API — handlers + AppState wiring (#532) 2026-06-30 15:06:24 -04:00
fabro-auth feat(llm): Amazon Bedrock provider — Converse codec, SigV4 + API-key auth (#459) 2026-06-16 11:46:49 -04:00
fabro-automation refactor(server): extract reusable git-checkout/materialization core (#523) 2026-06-24 16:17:44 -04:00
fabro-checkpoint Demote non-interpolating config fields to plain String (#492) 2026-06-16 13:16:31 -04:00
fabro-cli Resolve secret tokens at the run boundary (worker-side, fail-closed) (#545) 2026-07-02 17:00:20 -04:00
fabro-client fix(cli): use server catalog for provider login (#529) 2026-06-26 08:46:38 -04:00
fabro-config Resolve run.prepare.steps env and interpolation at the run boundary (#530) 2026-07-01 10:31:26 -04:00
fabro-core Replace bare unwrap() with documented expect() across production runtim… (#415) 2026-05-26 17:46:39 -04:00
fabro-db Move environments to SQLite storage (#539) 2026-07-01 10:31:58 -04:00
fabro-dev Resolve run.prepare.steps env and interpolation at the run boundary (#530) 2026-07-01 10:31:26 -04:00
fabro-dump feat(web): add server-managed Environments CRUD settings UI (#462) 2026-06-13 08:44:38 -04:00
fabro-environment Move environments to SQLite storage (#539) 2026-07-01 10:31:58 -04:00
fabro-github fix(github): refresh installation tokens during workflows 2026-05-06 07:15:18 -04:00
fabro-graphviz fix(graphviz): render comments with template braces (#509) 2026-06-15 15:15:01 -04:00
fabro-hooks Hooks: typed end-to-end interpolation, narrow header tokens, fail-closed resolution (#528) 2026-06-30 17:07:11 -04:00
fabro-http refactor(static): centralize env var names 2026-04-24 12:29:51 -04:00
fabro-install Move environments to SQLite storage (#539) 2026-07-01 10:31:58 -04:00
fabro-interview Replace stdin JSONL control pipe with WebSocket worker control bus (#440) 2026-05-27 20:24:25 -04:00
fabro-llm feat(llm): Amazon Bedrock provider — Converse codec, SigV4 + API-key auth (#459) 2026-06-16 11:46:49 -04:00
fabro-macros refactor(dev): simplify generated docs tooling 2026-04-24 18:41:00 -04:00
fabro-manifest Demote non-interpolating config fields to plain String (#492) 2026-06-16 13:16:31 -04:00
fabro-mcp fix(mcp): honor inline enabled=false and per-server tool_timeout (#520) 2026-06-24 16:17:27 -04:00
fabro-mcp-server feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
fabro-mcp-store feat(server): mcp-servers HTTP API — handlers + AppState wiring (#532) 2026-06-30 15:06:24 -04:00
fabro-model feat(llm): Amazon Bedrock provider — Converse codec, SigV4 + API-key auth (#459) 2026-06-16 11:46:49 -04:00
fabro-oauth Replace bare unwrap() with documented expect() across production runtim… (#415) 2026-05-26 17:46:39 -04:00
fabro-options-metadata refactor(dev): simplify generated docs tooling 2026-04-24 18:41:00 -04:00
fabro-proc refactor(static): centralize env var names 2026-04-24 12:29:51 -04:00
fabro-redact fabro-redact: add SecretRedactor for per-run exact-value redaction (#542) 2026-07-02 16:59:41 -04:00
fabro-sandbox Resolve secret tokens at the run boundary (worker-side, fail-closed) (#545) 2026-07-02 17:00:20 -04:00
fabro-server Fix web app load performance: caching, compression, and eager chunk loading (#550) 2026-07-02 16:58:47 -04:00
fabro-slack Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-spa Fix web app load performance: caching, compression, and eager chunk loading (#550) 2026-07-02 16:58:47 -04:00
fabro-static feat(llm): Amazon Bedrock provider — Converse codec, SigV4 + API-key auth (#459) 2026-06-16 11:46:49 -04:00
fabro-store feat(web): add server-managed Environments CRUD settings UI (#462) 2026-06-13 08:44:38 -04:00
fabro-telemetry Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-template Hooks: typed end-to-end interpolation, narrow header tokens, fail-closed resolution (#528) 2026-06-30 17:07:11 -04:00
fabro-test Move environments to SQLite storage (#539) 2026-07-01 10:31:58 -04:00
fabro-tool feat(web): add server-managed Environments CRUD settings UI (#462) 2026-06-13 08:44:38 -04:00
fabro-tracker fix(github): refresh installation tokens during workflows 2026-05-06 07:15:18 -04:00
fabro-types fix(store): keep pre-#530 runs loadable (serde default on run.prepare) (#554) 2026-07-07 22:20:44 -04:00
fabro-util Resolve run.prepare.steps env and interpolation at the run boundary (#530) 2026-07-01 10:31:26 -04:00
fabro-validate fix(graph): support dotted Fabro graph attributes (#324) 2026-05-20 09:31:08 -04:00
fabro-variable Move variables to SQLite storage (#537) 2026-06-30 12:17:46 -04:00
fabro-vault feat(server): add variables API (#430) 2026-05-27 11:46:36 -04:00
fabro-workflow Resolve secret tokens at the run boundary (worker-side, fail-closed) (#545) 2026-07-02 17:00:20 -04:00