BREAKING CHANGE: sup config now derives entries from package.json#exports and a server/client glob instead of manual lists; module structure follows flat + barrel convention with .server.js/.client.js runtime suffixes
Update BaseLayout imports in auth email templates to use the
`@zen/core/email/templates` module alias instead of relative paths,
improving maintainability and consistency across the codebase.
- Fix BaseLayout import paths in auth email templates from
`../../core/...` to `../../../core/...` to match correct
directory depth
- Remove unused `DatabaseError` from db.js exports
Removes all module-related logic from the admin dashboard, CLI database
initialization, and AdminPages component:
- Drop `initModules` call from `db init` CLI command and simplify the
completion message to only reflect core feature tables
- Remove `getModuleDashboardStats` and module page routing from admin
stats actions and update usage documentation accordingly
- Simplify `AdminPagesClient` to remove module page loading, lazy
components, and module-specific props (`moduleStats`, `modulePageInfo`,
`routeInfo`, `enabledModules`)
Introduce a dedicated `storage-config.js` for registering public
prefixes and access policies via `configureStorageApi()`, replacing the
previous `getAllStoragePublicPrefixes` / `getAllStorageAccessPolicies`
imports from the module registry.
Remove `getAllApiRoutes()` from the router so module-level routes are no
longer auto-collected; feature routes must now be registered explicitly
via `registerFeatureRoutes()` during `initializeZen()`.
Update `.env.example` to document separate `ZEN_STORAGE_PROVIDER`,
`ZEN_STORAGE_B2_*` variables for Backblaze B2 alongside the existing
Cloudflare R2 variables, making provider selection explicit.
Clean up admin navigation and page components to drop module-injected
nav entries, keeping only core and system sections.
Replace hardcoded `users/` path-based access control with a
declarative `storageAccessPolicies` system defined per module via
`defineModule()`.
- Add `storageAccessPolicies` field to `defineModule()` defaults with
support for `owner` and `admin` policy types
- Expose `getAllStorageAccessPolicies()` from the modules/storage layer
- Refactor `handleGetFile` in `storage/api.js` to resolve access
control dynamically from registered policies instead of hardcoded
path checks
- Add `ZEN_STORAGE_ENDPOINT` env var and update `.env.example` to
support S3-compatible backends (Cloudflare R2, Backblaze B2)
- Document the env/doc sync convention in `DEV.md`
- Simplify `sendEmail` by extracting `resolveFrom` and `buildPayload` helpers
- Remove `sendAuthEmail` and `sendAppEmail` exports, keeping only `sendEmail` and `sendBatchEmails`
- Replace hardcoded fallback sender with env-based validation (throws if missing)
- Update `BaseLayout` to resolve `supportEmail` from `ZEN_SUPPORT_EMAIL` env var instead of hardcoded default
- Conditionally render support section only when a support email is available
- Remove verbose JSDoc comments and reduce overall code verbosity
Restructure the core API to separate infrastructure routes from feature
routes. Key changes:
- Add `runtime.js` for global state: session resolver and feature route
registry
- Add `file-response.js` for streaming file responses (storage endpoint)
- Remove feature routes (auth/users) from `core-routes.js`, keeping only
true infrastructure routes (health, storage)
- Introduce `registerFeatureRoutes()` so features self-register during
`initializeZen()` instead of being hardcoded in `core-routes.js`
- Add `UserFacingError` class to safely surface client-facing errors
without leaking internal details
- Fix import path for `rateLimit.js` to use shared lib location
- Update README to reflect new two-step registration flow and clarify
the role of `core-routes.js`
- Add `ZEN_DB_SSL_DISABLED` env variable to allow disabling SSL for database connections
- Refactor database CLI to split init logic into `initFeatures` and `initModules` for modular table initialization, with graceful fallback when modules are absent
- Extract `printHelp` and `askConfirmation` helpers for cleaner CLI structure
- Ensure `closePool` is called on both success and error paths in CLI
- Add `filterAllowedColumns` utility in `crud.js` to enforce column whitelists, preventing mass-assignment of privileged fields (e.g. `role`, `email_verified`)
- Update drop command description from "auth tables" to "all tables"
Restructure the core API module to improve clarity, consistency, and
maintainability:
- Introduce `defineApiRoutes()` helper for declarative route definitions
with built-in config validation at startup
- Add `apiSuccess()` / `apiError()` response utilities; enforce their
use across all handlers (core and modules)
- Move auth enforcement to route definitions (`auth: 'public' | 'user' |
'admin'`), removing manual auth checks from handlers
- Extract core routes into `core-routes.js`; router now has no knowledge
of specific features
- Rename `nx-route.js` to `route-handler.js` and update package.json
export accordingly
- Update ARCHITECTURE.md to reflect new API conventions and point to
`src/core/api/README.md` for details
Replace raw `console.log`/`console.error` calls across CLI, API
handlers, and module files with structured logger functions (`step`,
`done`, `warn`, `fail`) from the shared logger library.
This improves log consistency, readability, and makes it easier to
control output formatting and log levels from a single place.
- Rename `getModuleMetadata` to `getModuleMetadataGenerator` in registry,
index, and client exports to clarify its purpose (returns a generator
function, not a metadata object)
- Add new `getModuleMetadata` and `getMetadataGenerator` exports from
`modules.metadata.js` for server-side metadata object retrieval
- Update route auth format in docs from `requireAuth`/`requireAdmin`
flags to a single `auth` field with values: `'admin'`, `'user'`,
or `'public'`
- Fix `isModuleEnabledInEnv` to replace hyphens with underscores in
env var names (e.g. `my-module` → `ZEN_MODULE_MY_MODULE`)
- Replace `useState` initializer in `ZenProvider` with `useRef` guard
to avoid React strict mode double-invocation issues
- Sanitize route handler errors: only surface known auth messages
('Unauthorized', 'Admin access required'); log all other exceptions
server-side and return a generic 'Internal Server Error' to clients
- Derive profile picture content-type from validated file extension
instead of attacker-controlled file.type to prevent MIME spoofing
- Always emit explicit Content-Disposition headers on file responses;
serve known image types as 'inline', force download for all others
to prevent in-browser rendering of potentially dangerous content
- Add X-Content-Type-Options: nosniff and X-Frame-Options: DENY to
file response headers
Update all references across source files, documentation, and
configuration to reflect the new package scope and name. This includes
updating `.npmrc` registry config, install instructions, module
examples, and all import path comments throughout the codebase.
Removes the `./setup` export entry from `package.json` and the
corresponding `src/features/setup/index.js` entry point from
`tsup.config.js`, eliminating the standalone setup feature module
from the public API and build output.
Move `database` and `setup` CLI scripts from their respective feature
directories into a unified `src/cli/` directory. Update `tsup.config.js`
build entries and `package.json` bin paths to reflect the new locations.
- Add `./modules/define` export path pointing to `defineModule.js`
- Implement `registerExternalModules()` to handle modules passed via `zen.config.js`, with env var gating (`ZEN_MODULE_<NAME>=true`)
- Extract `buildAdminConfig()` helper to consolidate admin navigation/page config building
- Refactor `loadModuleConfig()` to use `buildAdminConfig()` and simplify public routes check
- Improve `initializeModuleTables()` to gracefully skip modules without `db.js` instead of erroring
- Update module discovery JSDoc to reflect external module registration support