All notable changes to the Boundary Framework will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
boundary-tools — 4 new developer helper toolsbb doctor — Config Doctor (rule-based)config.edn and project files — no AI required.env-refs (error): detects #env VAR references in the :active section without #or fallback that are not set in the environment.providers (error): validates :provider values against known sets (logging, metrics, error-reporting, payments, AI, cache).jwt-secret (error): verifies JWT_SECRET is set when the user module is active.admin-parity (warn): checks that admin entity EDN files exist in both dev/admin/ and test/admin/.prod-placeholders (error): flags placeholder values (company.com, example.com, TODO, CHANGEME) in prod/acc configs.wiring-requires (warn): verifies active Integrant modules have their module-wiring require in wiring.clj.bb doctor [--env dev|prod|acc|all] [--ci]. --ci exits non-zero on any error for CI pipelines.boundary.tools.doctor.bb setup — Config Setup Wizard (templates + optional AI)--database postgresql --payment stripe), or AI-powered natural language (bb setup ai "PostgreSQL with Stripe").resources/conf/dev/config.edn, resources/conf/test/config.edn, and .env.example from template fragments.boundary.ai.shell.cli-entry setup-parse; falls back to interactive if no AI provider is available.boundary.tools.setup.bb scaffold integrate — Module Integration (rule-based)bb scaffold generate: patches deps.edn (source/test paths), tests.edn (per-library suite), and wiring.clj (module-wiring require).--dry-run mode previews all changes without writing files.bb scaffold integrate <module> and bb scaffold:integrate <module>.boundary.tools.integrate.bb ai admin-entity — Admin Entity Generator (AI-powered)bb ai admin-entity "products with name, price, status").resources/conf/dev/admin/ and includes them as examples in the prompt for style consistency.--yes flag for non-interactive use.resources/conf/dev/admin/<entity>.edn and resources/conf/test/admin/<entity>.edn.#include directive).boundary.tools.admin_entity. Clojure-side additions:
boundary.ai.core.prompts: admin-entity-messages, setup-parse-messages prompt builders.boundary.ai.shell.service: generate-admin-entity, parse-setup-description orchestration functions.boundary.ai.shell.cli-entry: cmd-admin-entity, cmd-setup-parse subcommands.bb.edn: 3 new tasks registered (doctor, setup, scaffold:integrate) + 3 new requires (boundary.tools.doctor, boundary.tools.setup, boundary.tools.integrate).bb ai help text and dispatch updated with admin-entity and setup-parse subcommands.bb scaffold help text and dispatch updated with integrate subcommand.AGENTS.md (root): new tools added to Quick Reference and namespace table.CLAUDE.md: new commands added to Scripting section.boundary-tools/AGENTS.md: comprehensive documentation for all 4 tools with examples, tables, and workflow guides.libs/ai/AGENTS.md: features list updated to 7, service API examples added, 3 new pitfalls documented (#9–#11).boundary-realtime — Ring WebSocket handlerboundary.realtime.shell.handlers.ring-websocket): bridges Ring's map-based ::ring.websocket/listener response to the existing IRealtimeService connect/disconnect lifecycle. JWT authentication via token query parameter; on-open creates adapter and registers connection, on-close/on-error triggers disconnect cleanup.websocket-handler accepts keyword options: :token-param (default "token") and :on-message for optional client→server bidirectional messaging.ring/ring-core 1.15.3 added to libs/realtime/deps.edn.boundary-payments — new libraryIPaymentProvider protocol in boundary.payments.ports with create-checkout-session, get-payment-status, process-webhook, and verify-webhook-signature methods. Implementations: StripePaymentProvider, MolliePaymentProvider, MockPaymentProvider (development/tests).CheckoutRequest, CheckoutResult, PaymentStatusResult (:pending/:paid/:failed/:cancelled), WebhookResult (:payment.paid/:payment.failed/:payment.cancelled/:payment.authorized).boundary.payments.core.provider): cents->euro, normalize-event-type, mollie-status->event-type, mollie-status->payment-status, stripe-event->event-type.payment_intent_data[metadata][checkout_id] for webhook correlation, HMAC-SHA256 signature verification with constant-time comparison, 300s timestamp tolerance, graceful handling of malformed Stripe-Signature headers.get-payment-status, form-POST webhook processing with payment fetch-back verification.:boundary/payment-provider with :provider (:mock/:mollie/:stripe), :api-key, :webhook-secret, :webhook-base-url.payments-module-config in boundary.config, boundary.payments.shell.module-wiring loaded via platform wiring, boundary/payments dependency added to libs/platform/deps.edn.^:unit + ^:integration).libs/payments/deps.edn: standalone library with clj-http, cheshire, malli, integrant, tools.logging.boundary-ai — new library (Phase 19 of Boundary Roadmap)IAIProvider protocol in boundary.ai.ports with complete, complete-json, and provider-name methods. Implementations: OllamaProvider (offline-first, no API key), AnthropicProvider, OpenAIProvider, NoOpProvider (test stub).:fallback provider in :boundary/ai-service; if the primary fails, the fallback is used transparently.bb scaffold ai "<description>" [--yes]): parses a natural language module description into a validated ModuleGenerationRequest spec and delegates to the existing scaffolder pipeline. Preview + confirm by default; use --yes for non-interactive generation.bb ai explain, (ai/explain *e)): reads a Clojure/Boundary stack trace, extracts referenced source files, and returns a structured root-cause + fix-suggestion using framework-specific system prompts.bb ai gen-tests <file>): reads a source file, detects test type (:unit for core/, :contract for adapters/, :integration otherwise), and generates a complete Kaocha-compatible test namespace.bb ai sql "<description>", (ai/sql "...")): translates a natural language query description into HoneySQL map + explanation + raw SQL preview. Auto-discovers schema context from schema.clj files.bb ai docs --module <path> --type agents|openapi|readme): generates AGENTS.md developer guides, OpenAPI 3.x YAML, or README.md from source files.boundary.ai.shell.repl): (ai/explain *e), (ai/sql "..."), (ai/gen-tests "path/to/file.clj") — bind service once with (ai/set-service! system-service).:boundary/ai-service with :provider, :model, :base-url/:api-key, and optional :fallback sub-config.Message, AIRequest, AIResponse, ProviderConfig, AIConfig.boundary.ai.core.*): prompts.clj (system + user prompt builders for all 5 features), context.clj (module name extraction, stack trace parsing, function signature discovery, schema context), parsing.clj (JSON response parser, module spec → CLI args converter, SQL + test code extractors).^:unit + ^:integration).libs/ai/AGENTS.md: 7-section developer guide covering provider setup, REPL usage, CLI reference, common pitfalls (8 patterns), testing commands.libs/ai/deps.edn: standalone library with clj-http, cheshire, malli, integrant, tools.logging..github/workflows/ci.yml: test-ai job added (needs: lint); libs/ai/src added to the lint step; test-ai wired into test-summary..github/workflows/publish.yml: boundary-ai added to Layer 4 (standalone, no inter-library dependencies); updated release body and step summary.scripts/ai.clj: new Babashka script — bb ai explain, bb ai gen-tests, bb ai sql, bb ai docs.scripts/scaffold.clj: bb scaffold ai "<description>" subcommand added.bb.edn: ai task added.AGENTS.md and CLAUDE.md: ai added to library listing, test command reference, Babashka commands, and Library-Specific Guides table. Version bumped to 3.5.0.resources/conf/dev/config.edn: :boundary/ai-service added (Ollama primary, Anthropic fallback).resources/conf/test/config.edn: :boundary/ai-service {:provider :no-op} for test isolation.boundary-calendar — new library (Phase 2 / Q3 2026 roadmap)defevent macro and in-process registry (atom-backed, same pattern as defreport in boundary-reports): register named event type schemas at load time; get-event-type, list-event-types, clear-registry!.boundary.calendar.schema: Malli schemas — EventData, EventDef, OccurrenceResult, ConflictResult; helpers valid-event?, explain-event, valid-event-def?.boundary.calendar.core.event: pure helpers — duration, all-day?, within-range?.boundary.calendar.core.recurrence: DST-aware RRULE expansion via ical4j 4.x Recur with ZonedDateTime seeds; recurring?, occurrences, next-occurrence, expand-event.boundary.calendar.core.conflict: pairwise conflict detection — overlaps?, conflicts?, find-conflicts (returns ConflictResult maps with :overlap-start/:overlap-end).boundary.calendar.core.ui: pure Hiccup calendar views — event-badge, day-cell, month-view, week-view, mini-calendar.boundary.calendar.ports: CalendarAdapterProtocol (export-ical, import-ical).boundary.calendar.shell.adapters.ical: ICalAdapter backed by org.mnode.ical4j/ical4j 4.0.3; TZID extracted via regex from property text (ical4j 4.x creates synthetic zone IDs internally).boundary.calendar.shell.service: public API — export-ical, import-ical, ical-feed-response (returns Ring response with Content-Type: text/calendar; charset=utf-8).^:unit + ^:integration round-trip).libs/calendar/AGENTS.md: 11-section developer guide covering DST pitfalls, RRULE examples, ical4j 4.x API notes, registry pollution warning, REPL smoke check.docs-site/content/guides/calendar.adoc (weight 68): user-facing how-to guide.docs-site/content/api/calendar.adoc (weight 50): complete function API reference.dev-docs/adr/ADR-011-calendar-library.adoc: architecture decision record (7 decisions, alternatives considered).boundary-reports — added to CI (was missing)test-reports job added to .github/workflows/ci.yml; libs/reports/src added to the lint step..github/workflows/ci.yml: test-calendar and test-reports jobs added (both needs: lint; standalone, no inter-library dependencies). Both wired into test-summary.AGENTS.md and CLAUDE.md: reports and calendar added to library listing, test command reference, and Library-Specific Guides table. New "Adding a New Library to CI" checklist section in AGENTS.md.boundary-workflow — new library (Phase 2 / Q3 2026 roadmap)defworkflow macro and in-process registry: declare state machine definitions as data; get-workflow, list-workflows, clear-registry!.boundary.workflow.schema: Malli schemas — WorkflowDefinition, WorkflowInstance, TransitionDef, AuditEntry; state/transition validation at definition time.boundary.workflow.core.machine: pure state machine logic — can-transition?, find-transition, permission checks against :required-permissions, guard evaluation.boundary.workflow.core.transitions: available-transitions-with-status — returns all candidate transitions with :enabled?, :label, :reason for a given state and actor-roles.boundary.workflow.core.audit: pure audit entry constructors.boundary.workflow.ports: IWorkflowStore, IWorkflowEngine, IWorkflowRegistry protocols.boundary.workflow.shell.persistence: DB persistence via next.jdbc + HoneySQL (IWorkflowStore implementation).boundary.workflow.shell.service: orchestration — load → validate → persist → side-effects; create-workflow-service factory accepts optional job-queue and guard-registry.:context map; return boolean.TransitionDef (:side-effects [:notify-user]); enqueued via boundary-jobs after successful transition; silently skipped if no job queue configured.boundary.workflow.shell.http: REST API — POST /workflow/instances (start), POST /workflow/instances/:id/transition, GET /workflow/instances/:id (state + availableTransitions), GET /workflow/instances/:id/audit.boundary.workflow.shell.module-wiring: Integrant :boundary/workflow key; depends on :boundary/database-context (required) and :boundary/job-queue (optional).libs/workflow/AGENTS.md: developer guide covering defworkflow syntax, guards, side effects, auto-transitions, hooks, and Integrant wiring.docs-site/content/guides/workflow.adoc: user-facing how-to guide.boundary-workflow — lifecycle hooks, auto-transitions, available-transitions:hooks map on WorkflowDefinition: supports :on-enter-<state>, :on-exit-<state>, and :on-any-transition keys. Hooks receive the updated WorkflowInstance and fire synchronously after each successful transition (after the audit entry is saved). Exceptions are caught and logged; they do not roll back the transition.:auto? true on TransitionDef: marks a transition as system-initiated. process-auto-transitions! port method fires all eligible auto-transitions for a given workflow; uses [:system] actor-roles (no user permission check). Returns {:attempted :processed :failed} counts.available-transitions port method: returns candidate transitions with :enabled?, :label, and :reason fields for the current state and actor-roles. Exposed on the GET /api/workflow/instances/:id HTTP response as availableTransitions.:label on TransitionDef and :state-config map on WorkflowDefinition for human-readable display names.available-transitions-with-status pure function in boundary.workflow.core.transitions.boundary-search — filter support:filters key on SearchDefinition: declares filterable keyword dimensions (e.g. [:tenant-id :category-id]).:filter-values opt in index-document! and build-document: stores filter data as compact JSON in a new filters TEXT column.d.filters::jsonb->>'key' = ?; H2/SQLite uses INSTR(filters, '"key":"val"') > 0 (H2 2.4.x has no JDBC JSON function support).filter-key->json-key utility in boundary.search.core.index (kebab → snake conversion for JSON storage).resources/migrations/20260312000000-search-filters.{up,down}.sql.boundary-admin — tenant entity + dashboard statsresources/conf/{dev,test}/admin/tenants.edn — list/search fields, status enum filter (active/suspended/deleted), field groups (Identity, State, Settings), readonly system fields.admin-home-handler now calls count-entities for each registered entity and passes the stats map to admin-home, so entity tiles show real counts instead of always displaying "0".#{:users :tenants}).boundary-tenant — convenience functions and protocol extensiontenant-provisioned? public function in boundary.tenant.shell.provisioning: checks if a tenant's schema exists in PostgreSQL; returns false for non-PostgreSQL databases; throws on missing :schema-name.list-tenant-schemas public function in boundary.tenant.shell.provisioning: lists all tenant_* schemas in PostgreSQL; returns empty vector for non-PostgreSQL databases.ITenantSchemaProvider protocol extended with tenant-provisioned? and list-tenant-schemas methods; TenantSchemaProvider record updated to implement both.dev-docs/adr/ADR-020-tenant-database-scope.adoc: decision to keep tenant provisioning PostgreSQL-only; MySQL/SQLite version promises removed from README.boundary-tenant promoted from "Active" to "Stable" in PROJECT_STATUS.adoc. All convenience functions documented in README are now implemented; 70 tests, 474 assertions, 0 failures.boundary-tenant README: fixed middleware naming (wrap-tenant-resolver → wrap-tenant-resolution), removed non-existent wrap-require-tenant (use :require-tenant? true option instead), clarified middleware locations (platform lib vs tenant lib), replaced MySQL/SQLite roadmap promises with ADR-020 reference.boundary-tenant integration tests: removed stale "DEFERRED" comment — tests pass with mock observability services and H2 in-memory DB.boundary-external promoted from "In Development" to "Active" (Twilio, SMTP/IMAP adapters production-capable). Stripe moved to boundary-payments.AGENTS.md updated: workflow and search added to library structure, test commands, and Library-Specific Guides table. Version bumped to 3.3.0.libs/workflow/AGENTS.md and libs/search/AGENTS.md updated to document all new features.docs-site/content/guides/workflow.adoc and docs-site/content/guides/search.adoc updated with new API examples, filter DDL, migration notes, and hook/auto-transition reference.clojure -M:test:db/h2).workflow.core.transitions-test (available-transitions-with-status), workflow.shell.service-test (hooks, auto-transitions), search.core.query-test (filter SQL), search.shell.persistence-test (filter round-trip).The first production-ready release of the Boundary Framework - a batteries-included web framework for Clojure that brings Django's productivity and Rails' conventions with functional programming rigor.
core/ namespaces (no side effects)shell/ namespacesports.clj for dependency injectionboundary-core (0.1.0)Foundation library with essential utilities:
boundary-observability (0.1.0)Multi-provider observability infrastructure:
boundary-platform (0.1.0)HTTP and database infrastructure:
boundary-user (0.1.0)Authentication and authorization:
boundary-admin (0.1.0)Auto-generated CRUD admin interface (Django Admin for Clojure):
deleted_at columnsboundary-storage (0.1.0)File storage abstraction:
boundary-scaffolder (0.1.0)Production-ready module generator:
boundary-cache (0.1.0)Distributed caching:
boundary-jobs (0.1.0)Background job processing:
run-at timestampboundary-realtime (0.1.0)WebSocket-based real-time communication:
boundary-tenant (0.1.0)Multi-tenancy infrastructure:
boundary-email (0.1.0)Email infrastructure:
boundary-external (0.1.0) - In DevelopmentExternal service adapters:
:field-order:field-groups/api/auth/mfa/setup, /api/auth/mfa/enable, /api/auth/mfa/verify:enter (request), :leave (response), :error (exception){:path "/api/admin"
:methods {:post {:handler 'handlers/create-resource
:interceptors ['auth/require-admin 'audit/log-action]
:summary "Create admin resource"}}}
(defn create-user [this user-data]
(service-interceptors/execute-service-operation
:create-user
{:user-data user-data}
(fn [{:keys [params]}]
;; Business logic here - observability automatic
(let [user (user-core/prepare-user (:user-data params))]
(.create-user repository user)))))
limit and offset parametersfirst, prev, next, last relationsdev, test, prod)#include support: Modular config files per moduleBND_ENVresources/conf/{env}/admin/{module}.edn:test alias)clojure -M:migrate uphttps://thijs-creemers.github.io/boundary/hugo server in docs-site/ directorydocs/cheatsheet.html with client-side search, copy-to-clipboard:password-hash, :created-atpassword_hash, created_atpasswordHash, createdAtsnake-case->kebab-case-map, kebab-case->snake-case-mapWhy: Recent bug caused authentication failures because service layer used :password_hash but entities had :password-hash. This convention prevents such mismatches.
:unit metadata):integration metadata):contract metadata)clojure -M:test:db/h2 # All tests
clojure -M:test:db/h2 :core # Core library
clojure -M:test:db/h2 --focus-meta :unit # Unit tests only
clojure -M:test:db/h2 --watch :core # Watch mode
clojure -M:repl-clj <<'EOF'
(require '[boundary.shared.tools.validation.repl :as v])
(spit "build/validation-user.dot" (v/rules->dot {:modules #{:user}}))
(System/exit 0)
EOF
dot -Tpng build/validation-user.dot -o docs/diagrams/validation-user.png
resources/public/css/tokens-openprops.css).github/workflows/publish.yml (304 lines)v*io.github.thijs-creemersthijs-creemers (password via GitHub Secrets)boundary-core → io.github.thijs-creemers/boundary-coreboundary-observability → io.github.thijs-creemers/boundary-observabilityboundary-platform → io.github.thijs-creemers/boundary-platformboundary-user → io.github.thijs-creemers/boundary-userboundary-admin → io.github.thijs-creemers/boundary-adminboundary-storage → io.github.thijs-creemers/boundary-storageboundary-scaffolder → io.github.thijs-creemers/boundary-scaffolderboundary-cache → io.github.thijs-creemers/boundary-cacheboundary-jobs → io.github.thijs-creemers/boundary-jobsboundary-tenant → io.github.thijs-creemers/boundary-tenantboundary-email → io.github.thijs-creemers/boundary-emailboundary-external → io.github.thijs-creemers/boundary-external (skeleton, not production-ready)Use the boundary-starter template:
git clone https://github.com/thijs-creemers/boundary-starter
cd boundary-starter
export JWT_SECRET="change-me-dev-secret-min-32-chars"
export BND_ENV="development"
clojure -M:repl-clj
In REPL:
(require '[integrant.repl :as ig-repl])
(ig-repl/go) ;; Visit http://localhost:3000
What you get:
;; deps.edn
{:deps {io.github.thijs-creemers/boundary-core {:mvn/version "1.0.0"}
io.github.thijs-creemers/boundary-platform {:mvn/version "1.0.0"}
io.github.thijs-creemers/boundary-user {:mvn/version "1.0.0"}
io.github.thijs-creemers/boundary-admin {:mvn/version "1.0.0"}}}
clojure -T:build clean && clojure -T:build uber
java -jar target/boundary-*.jar server
Use provided Dockerfile in boundary-starter template.
export JWT_SECRET="production-secret-min-32-chars"
export BND_ENV="production"
export DB_PASSWORD="secure_password"
export DATABASE_URL="jdbc:postgresql://localhost:5432/boundary"
tx (15 occurrences)tx-ctx (5 occurrences)These are false positives from clj-kondo's static analysis and do not affect runtime behavior.
let expressions: 3 warnings in test files (cosmetic issue)This is the initial 1.0.0 release. No migration from previous versions.
Copyright 2024-2025 Thijs Creemers. All rights reserved.
feat/boundary-workflowCan you improve this documentation? These fine people already did:
Thijs Creemers & thijscreemersEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |