Back to blog
2026-06-09 Thijs Creemers

Release: v1.0.1-alpha-28

We just tagged v1.0.1-alpha-28. This is a feature and security release. The headline is real CSRF protection across the web layer; it ships opt-in so upgrading the framework cannot break apps that do not yet emit tokens. There is one breaking change for apps that had already turned CSRF on — read the upgrade note below.

Security: real CSRF protection

boundary-platform now enforces CSRF for session-authenticated, state-changing requests (POST/PUT/DELETE/PATCH), replacing a stub that always passed (BOU-43). Tokens are signed, session-bound double-submit values (HMAC-SHA256, constant-time verification); authenticated requests bind to the session, while unauthenticated /web flows (login, register, MFA) bind to a SameSite=Strict cookie minted on the page GET.

Tokens are emitted with no per-handler wiring. HTMX requests pick up the token from (boundary.platform.core.csrf/hx-headers) merged onto an element such as <body> (inherited by all hx-* requests), or from the shared layout’s <meta name="csrf-token"> tag plus a global htmx:configRequest listener. Plain forms include a hidden field via (boundary.platform.core.csrf/hidden-field).

Enforcement is opt-in: the library default is :enabled? false, so upgrading the framework cannot start rejecting requests from consumers that do not yet emit tokens (BOU-56). Token-auth API clients that send no session cookie are not CSRF-vulnerable and are never checked.

Changed: full interceptor stack on web routes

The default HTTP interceptor stack is no longer skipped for :no-doc routes. Interceptor application is now controlled by an explicit per-route :skip-interceptors? flag (set only on genuinely-internal endpoints such as health checks); :no-doc once again means only "exclude from the Swagger spec" (BOU-43).

The most visible effect: every /web route now runs the full stack — request logging, metrics, error reporting, correlation header, CSRF, and security headers — where previously it ran none. HTML pages now carry the security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, …) they were silently missing. The shipped CSP allows 'unsafe-inline'/'unsafe-eval' for HTMX/Alpine and all UI assets are self-hosted, so rendering is unaffected.

Fixed: Redis cache serialization

The Redis cache adapter now serializes values with Nippy instead of JSON, fixing class java.lang.String cannot be cast to class java.time.temporal.Temporal for cached java.time values (BOU-47). JSON was lossy — Temporal values became ISO-8601 strings, keywords became strings, and sets became vectors — and the loss only surfaced against Redis. Nippy round-trips keywords, sets, ratios and java.time values intact, matching the in-memory adapter. Unreadable entries (old JSON bytes) are treated as a cache miss, so the cache self-heals on rollout. Flushing the cache namespace on deploy is still recommended to avoid log noise from stale reads.

Added: smarter admin list-view columns

boundary-admin now derives proportional list-view column widths from each field’s :type plus a field-name heuristic, replacing the old even distribution where a boolean column got the same width as a description column (BOU-46). An optional :width key on a field config overrides the computed default. Widths resolve deterministically at render time — no runtime AI. bb ai admin-entity was taught the same weight table and now suggests :width values in generated EDN configs for fields whose semantics differ from the default, e.g. :sku/:code/:barcode (BOU-48).

Added: unified error-code catalogue

boundary-devtools ships a single source-of-truth error catalogue consumed by both the JVM runtime and the Babashka CLI (BOU-49). bb guide error BND-201 now returns title, cause, and fix instead of "Unknown error code". The old BND-0xx codes are retired in favour of a ranged scheme: BND-1xx configuration, 2xx validation, 3xx persistence, 4xx auth, 5xx interceptor, 6xx FC/IS violations, 7xx tooling/build.

boundary-push also gained comprehensive developer documentation covering all five protocols, Integrant wiring, HTTP routes, the HMAC callback flow, and REPL smoke checks (BOU-44).

Version alignment

All libraries bumped to v1.0.1-alpha-28 to maintain lockstep versioning.

Upgrade

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

curl -fsSL https://get.boundary-app.org | bash

Breaking change (BOU-56): CSRF startup now fails loud. If an app sets :enabled? true for CSRF but leaves JWT_SECRET/:secret unset, the system wiring throws and the app refuses to boot — previously it warned and continued with CSRF silently disabled (failing open). Set the secret in the environment before upgrading. Apps that never enabled CSRF are unaffected: the library default is :enabled? false.

Feedback and issues welcome on GitHub.