Back to blog
2026-09-21 Thijs Creemers

Release: v1.0.0-rc-3 — scaffold a relation, and a workflow that lets the right people through


A day of fixes on the release candidate, most of them found by trying to give a conference demo with it. Nothing here changes how you write an application.

One correction to rc-2 first, and it is the same correction rc-2 made to rc-1. That post said the breaking list was four and closed again. It is five. bb scaffold generate --cli is gone — it named an interface the scaffolder has never had a generator for, so no value of the flag ever produced one. A break lands after rc-1 only where the candidate turns one up, and then in a candidate rather than in 1.0.0, so you meet it before the tag.

Breaking: --cli named something that was never generated

bb scaffold generate --cli is removed. Passing it asked for a CLI interface the scaffolder has no generator for, so it did nothing either way. Only a script that passes the flag is affected — drop it from the command line and the output is identical.

Fixed: a transition with required permissions refused everyone

A workflow transition guarded by :required-permissions was refused for every user, including the ones who had the permissions. It read the actor from a request key that nothing has set since BOU-373, so it saw nobody and denied accordingly. Guarded transitions work now.

A malformed body to a workflow POST answered 500. The routes declare their body schema, so a bad request is a 400 that says what was wrong with it.

Fixed: generated services call the protocol

A generated service reached its repository reflectively — (.find-by-id repo id), a Java interop call against whatever object happened to be there. It calls the protocol functions now. Regenerate the module, or replace (.find-by-id repo id) with (ports/find-by-id repo id) in the service you already have.

Fixed: InvoiceLineItem is invoice_line_items

A multi-word entity lost its word boundaries on the way to the database: InvoiceLineItem scaffolded a table called invoicelineitems. It is invoice_line_items now, which is what you would have written.

In the same area, generated persistence queried a table nobody created. It used the PascalCase entity name — :Products — where the migration had created products, so a freshly scaffolded module failed on its first query.

Fixed: a scaffolded module’s web page shows its own rows

The generated web page rendered, but not from your table. web-routes mounts the generated handler now, and new projects declare hiccup so the page has something to render with.

i18n/render also accepts a nil t-fn, rendering each marker as its key name. Callers had to carry their own fallback for the case where translations are not wired yet; they do not.

Fixed: --http and --web were read and ignored

bb scaffold generate accepted both flags and generated everything regardless, so core/ui.clj and shell/web_handlers.clj landed in every module with nothing mounting them. Use --no-web to skip them.

Added: a foreign key is a field flag

bb scaffold field order customer:relation:references=customer

generates the customer_id column, the REFERENCES clause and the index. on-delete= defaults to cascade; name something else if that is not what you want.

Added: :migrate-on-start? applies migrations at boot

Set :migrate-on-start? true on the database config and pending migrations run when the application starts. Generated dev and test configs set it, so a fresh checkout boots with its schema in place. It is off everywhere else, and off in the config you already have — nothing changes for an existing app unless you ask for it.

Version alignment

All 31 artifacts bumped to v1.0.0-rc-3 to maintain lockstep versioning.

Upgrade

Re-run the installer to pick up the latest release:

curl -fsSL https://get.wagoe.org | bash

Coming from rc-2, three things to check:

  1. Drop --cli from any script that calls bb scaffold generate.

  2. Look at your generated services for (.find-by-id repo id) and friends. Regenerate, or switch them to ports/.

  3. Check your table names. A multi-word entity scaffolded before this release has a run-together table name, and its migration and its queries agree with each other — so it works, and renaming it is a migration you write yourself.

Coming from a beta, work through the rc-1 upgrade list first — it is longer, and the breaking changes are in it.