The release candidate for 1.0.0. Three breaking changes ship here, they are exercised in this release first, and that is the complete list — nothing further lands as Breaking before the 1.0.0 tag. Deprecations are deferred to 2.0, so what warns today keeps working.
If you are running a beta in anything you care about, this is the release to move to. Two of the fixes are security fixes in the storage module, and the upgrade notes at the bottom are longer than usual.
Breaking: three changes
:wagoe/user-http-handler is removed. It has thrown on init since it was deprecated, so nothing was running on it — use :wagoe/user-routes with the top-level :wagoe/http-handler.
Ten methods are dropped from the user repository ports. None of them had a caller. If you implement the ports by hand, delete them; wagoe.user.ports lists what remains.
An unknown :provider on :wagoe/cache or :wagoe/realtime now throws. It used to fall back to an in-process adapter, which is the worst possible failure: a typo in production ran a node-local cache or a node-local event bus across your cluster, and nothing said so.
Deprecated: one provider vocabulary
Provider names were three vocabularies wearing one keyword. They are now :memory and :redis everywhere, and :db where a module has one. :in-memory, :redis-streams and :database warn until 2.0.
wagoe.jobs.shell.adapters.db/enqueue-in-tx! is deprecated — call wagoe.jobs.ports/enqueue-in-tx! on the queue component. The :wagoe/admin and :wagoe/auth-user-repository Integrant components are deprecated too; drop them from hand-written wiring, and keep :wagoe/admin in :active, which is still the module switch.
Fixed: two ways local storage could be abused
The local storage adapter let a caller escape :base-path. A key containing ../, or a symlink under the root, could read, write and delete outside it. Upgrade if you accept storage keys from users.
Signed download URLs were never verified. The route served the file without checking expires or signature, so a signed URL was a suggestion. It enforces both now; point :http-base-path at wherever you mount the routes. Those routes can also be mounted deliberately with :expose-http? true — they carry no authorization of their own, so the mounting application has to guard them.
Fixed: modules you could enable but not run
Nine modules were documented, published, and absent from a generated project’s deps.edn — jobs, events, push, realtime, reports, calendar, geo, audience and email. They ship in it now. Around that, the modules themselves:
-
Audience could not boot.
IUserDataSourcehad no implementation and nothing wired the service. It segments your users table now. Saved segments and compositions also resolved to the wrong users, because filters lost their keywords through JSON; audiences ran on H2 only; and its cache never hit, so every resolve recomputed. -
Scheduled pushes were never delivered.
schedule-push!enqueued into a nil queue with no registry holding its handlers. Enable:wagoe/jobsand both are wired. -
Configured APNs push never reached Apple. The generated config wrote
:key-filewhere the code reads:key-path, and half-configured push fell back to the mock in silence. It now refuses to boot instead. -
wagoe add pushcreated no tables — its migrations ship a manifest, sobb migrate upfinds them.wagoe add reportsandwagoe add calendarswitched nothing on at all: both had an empty config snippet, so the library landed indeps.ednand:activestayed untouched. -
Email’s queued mode was documented and never built.
:wagoe/email-queueships over the sender you configured. Configured FCM push no longer throws at boot either — set:fcm-credentials {:project-id … :credentials-path …}. -
service <module>now works for nine more modules, andservice tenantandservice pushanswer over RPC. Every other service records why it offers nothing remote rather than leaving the question open.
Fixed: Java 21 is the baseline everywhere
The production image built and ran on JDK 17 while the installer demanded 21. One baseline now — Java 21 — held by a gate that reads the package names people actually install. Rebuild your images.
Fixed: your database session ran in the host’s timezone
Every alias and launcher sets -Duser.timezone=UTC, so zone-less columns re-read in UTC instead of in whatever the host was set to. Push, geo and audience timestamps carried no timezone at all; a migration widens them on PostgreSQL and H2, and it assumes the stored values are UTC.
MySQL sessions also ignored their timezone and charset settings — a sql_mode MySQL 8 rejects aborted the rest of the session setup.
Fixed: adapters that could not connect
MySQL could not open a connection and SQLite reported every table as absent; SQLite was also handed PostgreSQL column types. Upgrade if you run either.
The S3 adapter threw on every S3-compatible endpoint, so MinIO, Spaces and the like could not be used despite being named as supported. Set :endpoint and it works.
Added: libraries carry a stability tier
Eight libraries are marked incubating: published, usable, and outside the breaking-change guarantee. wagoe list modules shows the tier, and so do the library pages. Knowing which eight matters more at a release candidate than at any point before it.
Expired sessions are now pruned — :wagoe/session-pruner deletes them 30 days after expiry; set :enable-pruning false to keep the rows. And worker mode actually runs jobs: enable :wagoe/jobs {:provider :memory}, modules contribute handlers, and :workers {:count 0} gives you a web-only node.
Fixed: deployment blueprints that deployed nothing
The Render and Fly blueprints built a container that served nothing. Both build the root Dockerfile now and set ERROR_REPORTING_PROVIDER=no-op. The dev image ignored its own JAVA_OPTS — -Xmx512m never applied and it ran on 1960MB; rebuild if you use resources/conf/dev/Dockerfile.
Changed: dependencies, and knowing when they drift
34 coordinates across 34 deps.edn files are up to date, jedis 8 and the Google Cloud bundle among them. Re-pin if you override any. bb upgrade-outdated was also under-reporting drift: it read an index that lags, which hid the H2, MySQL, PostgreSQL and SQLite drivers, and it no longer offers prereleases.
Two build-side fixes worth naming because they affect what you get: a locally built library jar could carry a previous build’s namespaces — jar cleans first now, and the published artifacts were checked and are unaffected. And a pre-release could again outrank the release it precedes; pre-releases are cut from the next minor, and both bb bump and the publish guard refuse a patch pre-release.
Removed
docs-site/ is gone — the published site is built from the same .adoc sources, and this was a second renderer nothing ran. The per-engine query, metadata and utils namespaces under adapters.database are removed along with config-factory; build adapters with factory/db-context.
Version alignment
All 31 artifacts bumped to v1.0.0-rc-1 to maintain lockstep versioning.
Upgrade
Re-run the installer to pick up the latest release:
curl -fsSL https://get.wagoe.org | bash
Coming from a beta, work through this list:
-
Rebuild your images. Java 21 is the baseline; a JDK 17 image is no longer supported.
-
Replace
:wagoe/user-http-handlerwith:wagoe/user-routesplus the top-level:wagoe/http-handler, and drop:wagoe/adminand:wagoe/auth-user-repositoryfrom hand-written wiring. -
Check every
:provider. An unknown one throws at boot now instead of quietly running in-process. Rename:in-memoryto:memory,:redis-streamsto:redis, and:databaseto:db. -
Delete the ten dropped methods from any hand-written user repository port implementation.
-
Run
bb migrate up. The push, geo and audience timestamp migration assumes the stored values are UTC — check that before you run it if your host was not. -
Re-pin any dependency you override, and upgrade if you accept user-supplied storage keys or serve signed storage URLs.