- add optional `permission` field to route definitions with type validation in `define.js`
- check `hasPermission()` in router after `requireAdmin()` and return 403 if denied
- document `permission` and `skipRateLimit` optional fields in api README
- load user permissions in `AdminPage.server.js` and pass them to client via `user` prop
- use `user.permissions` in `RolesPage` and `UsersPage` to conditionally render actions
- expose permission-gated API routes in `auth/api.js`
- simplify em-dash sentence in EmailChangeConfirmEmail footer note
- replace "notre équipe de support" with "le support" across notify/changed/admin_new variants
- shorten InvitationEmail title by removing "Bienvenue —" prefix
- reword PasswordChangedEmail body and footer note for clarity
- align PasswordResetEmail and VerificationEmail copy with same tone
- add `createAccountSetup`, `verifyAccountSetupToken`, `deleteAccountSetupToken` to verifications core
- add `completeAccountSetup` function to auth core for password creation on invite
- add `InvitationEmail` template for sending invite links
- add `SetupAccountPage` client page for invited users to set their password
- add `UserCreateModal` admin component to invite new users
- wire invitation action and API endpoint in auth feature
- update admin `UsersPage` to include user creation modal
- update auth and admin README docs
- add ZEN_TRUST_PROXY env variable in .env.example for reverse proxy config
- replace getClientIp() with getIpFromHeaders() using next/headers for ip resolution
- forward ipAddress and userAgent to login action for session tracking
- add sessions tab with active session list in ProfilePage
- fetch and display sessions with current session highlight
- implement single and bulk session revocation with redirect on self-revoke
- add session-related api helpers in auth api
- add new password field in UserEditModal with optional admin-set password on save
- add send password reset link button with loading state in UserEditModal
- add password change section with strength indicator in ProfilePage
- expose sendPasswordResetEmail utility in auth api
- remove separate `/zen/api/roles` fetch and `roleColorMap` state from UsersPage
- update SQL query to include aggregated roles array per user via subquery
- replace single role badge with multi-badge display supporting overflow indicator
- add `ConfirmEmailChangePage.client.js` for email change token confirmation
- add `emailChange.js` core utility to generate and verify email change tokens
- add `EmailChangeConfirmEmail.js` and `EmailChangeNotifyEmail.js` email templates
- update `UserEditModal` to handle email changes with password verification for self-edits
- update `ProfilePage` to support email change initiation
- update `UsersPage` to pass `currentUserId` to `UserEditModal`
- add email change API endpoints in `auth/api.js` and `auth/email.js`
- register `ConfirmEmailChangePage` in `AdminPage.client.js`
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
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.
- 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.