A large candidate, and not the one rc-3 promised. Its post said the breaking list was five. It is twenty-five: this release adds twenty. Most come from two passes over the framework before 1.0.0 — one asking what an anonymous caller can reach, one asking what a production boot accepts that only makes sense on a laptop. The answer to both was "too much", and closing it changes behaviour you may rely on. Better you meet that in a candidate than in 1.0.0.
Every break below is under # Breaking in the changelog, with what to do about it. The upgrade list at the end puts them in the order to work through.
Breaking: nothing answers an anonymous caller unless you say so
-
Routes require login unless they carry
:public true. A webhook or a public page needs the flag now. -
The workflow API answers
401without a session or bearer token. It was open. The auth middleware’s own401now has a JSON body. -
Scaffolded APIs and list pages require a signed-in user. Pass
--public-apito open them. An older module keeps its open routes until you regenerateshell/*http.cljor add the guards by hand.
Breaking: a prod boot refuses what only works in dev
-
:wagoe/payment-providerhas no default, and:mockboots only in dev and test. The mock accepts any webhook as paid, andwagoe add paymentsused to write it into prod. If your prodconfig.ednhas{:provider :mock}, remove it and name:stripeor:mollie. -
Redis with no host fails the boot outside dev and test. It quietly connected to localhost. Set
REDIS_HOSTfor events, cache, jobs and realtime, even when Redis is on the same machine. -
:wagoe/tenantrefuses SQLite, and H2 without:allow-h2? true. Schema-per-tenant needs PostgreSQL; a test profile on H2 adds the flag. -
bb setup --prod truechanges prod only, merging into what is there, and refuses--payment mockand--ai-provider. Run it without--prodfor dev.
Breaking: the database holds the rules the code assumed
-
One workflow instance per workflow and entity. A second start returns the first.
migrate uprefuses a table that already has duplicates and names them: keep one of each, then migrate. -
Tenant slugs, schema names, memberships and invite tokens are unique. Boot stops, naming the table, if rows already duplicate one.
-
Workflow’s tables ship as a migration, with
TIMESTAMP WITH TIME ZONE. Stop every replica and runmigrate upbefore starting rc-4; seed timestamps as#inst. -
Admin hard-deletes by default, and refuses to delete a parent with has-many rows unless the relation says
:on-delete :cascade. Set:soft-delete truewhere you relied ondeleted_at. -
An unknown or misplaced admin entity-config key stops startup, naming the path. It used to be ignored, which is how a typo’d
:hide-fieldswent unnoticed. -
A scaffolder
datefield is aDATE. Usedatetimefor a timestamp.
Breaking: the rest
-
sortable-thandpaginationswapouterHTML, so a table refresh stops nesting a second container inside the first. A handler that returns only the target’s contents passes:hx-swap "innerHTML". -
The workflow API speaks kebab-case JSON — send
workflow-id,entity-type,entity-id; readcurrent-state— and a refused transition answers{"error": {…}}like the scaffolded APIs. Drop checks onsuccess. -
:wagoe/logging :levelsets Logback’s root andwagoeloggers, overlogback.xml. -
register-userthrows:validation-errorfor a password-policy refusal;:violationsis unchanged. -
Scaffolder field specs refuse an unknown modifier, and
requiredtogether withoptional.indexednow writes an index andoptionalis honoured. -
bb setupexits 1 on a closed stdin instead of accepting every default — a script passes flags,bb setup --database sqlite— and in an existing project it creates no missing config file.
Fixed: what leaked
-
Password hashes, MFA secrets and session tokens were written to the application log. Nothing to rotate, but purge any logs you retain.
-
Open redirect after login via
?return-to=/\evil.com. Backslashes, control characters and encoded slashes are refused, in admin’sreturn_totoo. -
An admin entity’s
:hide-fieldscould un-hide password hashes and API keys. Detected secret columns stay out of list, search and edit. -
A new tenant could take a deleted tenant’s slug, and with it that tenant’s schema and data. A slug is never reused now. Upgrade if you delete tenants.
-
User, MFA, storage and workflow pages and APIs showed exception messages, and
/health/readyshowed database and cache errors. They log the cause and answer something generic.
Fixed: a scaffolded module works the first time
-
A scaffolded GET returns the children POST created and the workflow instance; the list takes
?include=. -
bb scaffold field --requiredgives the generated tests' rows a value instead of failing them. -
Scaffolded migrations kept their indexes on SQLite and ran on PostgreSQL.
-
A scaffolded API’s
400names the field, and a reference to a missing row is a400on that field rather than a500. -
Creating an entity with an enum field no longer answers
500, and repository tests round-trip a row instead of asserting nothing. -
bb scaffold ai --dry-runwrites nothing, and one description names its module the same way every run. -
migrate upmigrates only the modules in:active, and works on a database that never booted. -
bb create-admintakes one piped password instead of looping on it.
Fixed: the CLI
Every wagoe command answers --help. Config keys that bb setup, bb scaffold integrate and wagoe add append follow the file’s indentation. bb setup changes only what you answer, lists each change first, and no longer tells you to copy .env.example over a .env that holds your JWT_SECRET. The (go) box shows the dev dashboard’s URL at the port it actually bound.
Added: a status that is a workflow
bb scaffold generate --module-name invoice --entity Invoice \
--field number:string:required --workflow 'status:entered>delivered>paid'
Quote the spec — unquoted, the shell reads each > as a redirect. The status becomes a workflow that API and admin creates both start, moved by POST /invoices/:id/transition. bb db:seed starts a seeded row’s instance in the state the row names.
Around it:
-
bb scaffold entity --belongs-to invoice --min 1— the invoice API creates its line items in the same request and transaction, and refuses fewer. The admin gets one form for the parent and its first children. -
bb scaffold subscriber --module-name m --event :admin/entity-createdwrites an event subscriber, its handler and its test. -
GET /api/v1/workflow/instances?entity-type=invoice&entity-id=<id>finds an entity’s workflow instances. -
Workflow guards see the instance, and can load its entity through an
:entity-loader. -
With the admin on,
generateandentitywrite each entity’s admin config, with secret columns hidden.
Version alignment
All 31 artifacts bumped to v1.0.0-rc-4 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-3, in this order:
-
Purge retained application logs if you keep them — they may hold password hashes and session tokens.
-
Stop every replica and run
migrate upbefore starting rc-4. If it refuses on duplicate workflow instances or tenant rows, it names them; remove the extras and run it again. -
Fix prod config: remove
{:provider :mock}from payments, setREDIS_HOST, and move tenancy off SQLite. -
Mark public routes with
:public true, pass--public-apifor scaffolded APIs that must stay open, and give workflow API clients a session or token. -
Workflow API clients send and read kebab-case keys, and stop checking
success. -
Admin config: set
:soft-delete trueor:on-delete :cascadewhere you relied on the old delete, and fix whatever key startup names. -
Scripts that drive
bb setuppass flags; scripts that pass an unknown field modifier drop it.
Coming from a beta, work through the rc-1 upgrade list first.