1.2.0 is mostly a security release. If you run Wagoe with more than one tenant (:wagoe/tenant), upgrade. If you don’t, upgrade anyway: new apps now have CSRF protection and rate limiting switched on, and the CSP no longer allows inline scripts. That last one can break a page of yours, so read the upgrade notes at the bottom.
There is also one new library: Wagoe’s database layer on its own, without a web server attached.
Security
Multi-tenancy was the weakest part of Wagoe, and the homepage already said so. For this release I went through every path where a tenant could reach another tenant’s data. There were more than I’d like. Every 1.x release before 1.2.0 is affected if you use :wagoe/tenant.
What was wrong, in short:
-
Any signed-in user could run requests in another tenant by naming it in a header or the host (BOU-982).
-
A tenant’s admin could manage other tenants, make themselves admin of another one, and see or edit other tenants' users, roles and groups (BOU-983, BOU-953, BOU-984, BOU-954).
-
Background work ignored the tenant. A job enqueued in a tenant ran on the public schema, events and push messages reached every tenant, a realtime topic like
order:123reached every tenant’s subscribers, and a webhook subscription without a tenant received everyone’s events (BOU-985 to BOU-990, BOU-946, BOU-947). -
User listings and search could show other tenants' users, and a suspended tenant kept serving for up to an hour from cache (BOU-948, BOU-992).
-
With
:expose-http? true, storage was too trusting: download, delete and signed URLs acted on any key a signed-in user named, an upload to a named path could overwrite someone else’s file, and a signed local URL kept working after its file was gone (BOU-945, BOU-950, BOU-991).
All of these are closed. Roles and groups don’t carry a tenant yet, so for now only a platform admin can edit them. These are the gaps I know of; keep testing isolation in your own app, and tell me when you find one I missed.
Defaults that were too loose:
-
CSRF and rate limiting were off in apps made by
wagoe newand in profiles written bybb setup(BOU-940, BOU-951). They’re on for new apps now, and the boot warns while CSRF is off. An existing app keeps its config, so turn it on yourself (see below). -
The CSP allowed inline script and
eval(BOU-898).script-srcis'self'now. -
A plaintext secret in
config.ednpassedbb doctor(BOU-942). It fails now, outside the test profile.
And one about trust: you could not check the installer before running it (BOU-938). Each release now has install.sh and its SHA-256 attached, and the installer pins and checks the Clojure, Babashka and bbin installers it runs.
Wagoe’s database layer without the HTTP stack
com.wagoe/wagoe-platform-sql is new. It holds platform’s database, migration, lease and transit namespaces, under the same names. wagoe-platform depends on it, so nothing changes for a full Wagoe app.
It matters if you have an app already and want Wagoe’s jobs or search in it. wagoe-jobs and wagoe-search now come with next.jdbc, HoneySQL, HikariCP and Migratus, and no Jetty, Reitit or Muuntaja. The homepage used to claim more than that was true; I said zero lock-in. Then I ran clojure -Stree tells that story, and what is still not true.
To get there, a few libraries lost dependencies they never needed. wagoe-search no longer brings wagoe-admin or wagoe-shared-ui, and wagoe-jobs no longer brings wagoe-tenant. If you got one of those through search or jobs, declare it yourself.
Stricter architecture checks
bb check:fcis keeps core/ pure, and it got stricter:
-
honey.sqlincore/now fails. Build queries in the shell, or list the file under:allow-sqlin.wagoe/check-fcis.edn. -
Requiring a shell namespace that happens to be called
…shell.core,.schemaor.portsfrom core now fails too (BOU-964). -
println,tap>and friends, and reads of the clock or a random number incore/, now warn. They will fail from 2.0. Read the value in the shell and pass it in. If a namespace really needs it, mark it^:wagoe/allow-printor^:wagoe/allow-clockwith a reason.
Smaller things
-
Push sends were retried after every success and so delivered twice (BOU-987). Fixed.
-
A missing or short
JWT_SECRETnow saysWGE-103, andbb guide error WGE-103explains it. -
Scaffolded repositories return the schema’s types instead of the driver’s (BOU-877). Copy
→entityfrom a freshbb scaffoldinto older modules. -
The admin sidebar is wider and you can drag it. Sign-in, registration and MFA pages now look like the admin.
Upgrade
curl -fsSL https://get.wagoe.org | bash
If you’d rather check the installer first, download it from the release and compare the checksum:
curl -fsSLO https://github.com/wagoebv/wagoe/releases/download/1.2.0/install.sh
curl -fsSLO https://github.com/wagoebv/wagoe/releases/download/1.2.0/install.sh.sha256
shasum -a 256 -c install.sh.sha256
Then pin 1.2.0 for every com.wagoe/* dependency. All 34 artifacts are on 1.2.0. Run wagoe doctor afterwards; it names anything that moved.
What you may need to change in an existing app:
-
Inline scripts. An inline
<script>,onclickorhx-onstops running under the new CSP. Move it to a.jsfile, or set your own CSP. -
CSRF. Set
:security {:csrf {:enabled? true}}under:wagoe/http. -
Admin users. Add
:scope {:tenant-id :tenant-id}to youradmin/users.edn. -
Search. Mark an index that holds no tenant’s data
:global? true, or a tenant’s caller gets a 403. -
Secrets. Move plaintext secrets in
config.ednto#secretor#env. -
Push. Devices registered before 1.2.0 have no tenant. Re-register them.
-
Tenant schemas.
sync-tenant-schemas!now runsmigrations-tenant/. If your tenant tables came from its old fixed list, move their DDL there.
The full list is in the CHANGELOG, and the migration notes are in UPGRADING.md.