Changelog
All notable changes to Brighella are documented in this file.
Format based on Keep a Changelog and commits follow Conventional Commits. Versioning follows SemVer.
[Unreleased]
Added (2026-05-29 — Print Center complete)
- print: durable opaque QR short codes (
/s/<code>) with server-side
resolver and lazy per-tenant allocation (migration 365). Denser glyphs, re-pointable mapping; legacy /scan/<type>/<id> labels still resolve. QR error-correction raised M→Q for physical durability. See docs/qr-durability.md.
- print: thermal/roll label export — Zebra ZPL output (
lib/zpl.js) on
the item, location, and bulk pages; common roll sizes (57×32, 102×51, …).
- print: Avery sheet-label templates (L7651/L7159/L7160/L7163) in the size
selector, each validated to fit A4. See docs/label-printing.md.
- print: "Reprint Labels" hub card +
needs_reprintfilter. Labeled items
auto-flag for reprint when a label-bearing field (name/department/location/ weight) changes; (re)labeling clears the flag.
- print: box-contents location sticker — optional item-count field.
- print: sticker presets now shared across Bulk + item Print Center, and a
location preset family (migration 366) for the location page.
Changed (2026-05-29 — Print Center complete)
- print: QR batch fetching is chunked under the 100/request cap
(lib/qr-batch.js) — any selection size loads; no silent blank or full-page error past 100. Batch endpoints no longer write unused PNGs to disk.
- print: mark-as-labeled and QR-load failures now surface toasts instead of
failing silently. Fixed the dead /items?print=bulk hub card (now enters selection mode with the print-stickers action pre-armed).
Added (2026-05-19 — ADR-014 D-series sprint)
- realtime: per-channel WebSocket presence + entity updates (ADR-014 D10).
production:, person:, space: channels with cross-instance pg_notify fanout. PresenceAvatars on production and space detail headers.
- growth: server-rendered public
/changelog+/roadmapwith anonymous
vote tallying (ADR-014 D20). Backend tiny markdown subset renderer; no external markdown dependency.
- growth: first-login product tour anchored to the 3-noun mental model
(ADR-014 D21). react-joyride; dismiss stored in ui_preferences; replay available on the Help page.
- growth: referral program (ADR-014 D22). 10-char codes per user with
collision retry, 12-month total cap, idempotent on (referee_tenant_id), IP-hashed before insert. /me/referrals page + /admin/referrals endpoints.
- growth: customer health score (ADR-014 D23). Nightly cron computes a
0-100 score from 6 weighted components; surfaced as a colour-coded chip on the super-admin tenant list.
- pwa: vite-plugin-pwa with NetworkFirst runtime caching for the read
APIs, installable manifest, offline indicator banner, frontend write guard (ADR-014 D11).
- chrome: keyboard-shortcut overlay (ADR-013 #8) gets a discoverability
button next to the sidebar theme toggle + a cheat-sheet card on the Help page.
- chrome: sidebar v2 cleanup — Reports/People/Movements groups
collapsed to single hub doors; Productions sub-grouped into Scheduling, Casting, Finance, Partner; admin-only items get an "(Admin)" chip; theater-jargon items get hover tooltips; module/plan-gated items show a lock icon + "Upgrade" modal instead of disappearing silently.
- chrome: teaching empty states across 15 surfaces (touring + production
workspace tabs) — each empty page explains the concept and offers a primary action so first-run users learn the model.
Added
- docs: keep-a-changelog generator + CHANGELOG.md — WB-60 (
720745f) - docs: SECURITY.md — reporting, SLA, supported versions, hardening posture — WB-61 (
858d3ba) - docs: CONTRIBUTING.md — setup, tests, commit convention, house rules — WB-62 (
bf8ec58) - ops: declarative
.do/app.yamlspec + validator — WB-63 (22f9d7f) - docs: OpenAPI 3.0 spec + Swagger UI via router introspection — WB-64 (
ed2596f)
Security
- hsts: preload-eligible HSTS in production (
max-age=63072000; includeSubDomains; preload) — WB-65 (bb68ec8) - password-policy: HIBP k-anonymity breach check on signup, password change, reset, invite accept, and admin user create/update. 3s timeout; fail-closed on confirmed breach; fail-open on network error with logged
degradedwarning.HIBP_DISABLED=1opt-out for air-gapped deploys — WB-66
[24.1.1] - 2026-04-19 (commits 2026-03-23 → 2026-04-19)
Added
- logger: structured JSON in prod, auto-inject requestId + tenantSlug — WB-27 (
23ac151) - env-gate: validate 9 PROD_RECOMMENDED vars with boot-time warning — WB-22b (
5d3cf60) - health: enrich /readyz with pool stats + config flags — WB-19 (
4540b10) - storage: tenant-namespaced key helpers (namespaceKey, isPublicKey) — WA-A6.2 (
7e6b889) - uploads: centralize MIME+extension+magic-byte filtering — WA-A6.1 (
6bda468) - observability: capture frontend unhandled rejections — W1-H12 (
b675d5f) - observability: thread request-id into logger via ALS — W1-H11 (
fbfd424) - health: add unauthenticated /livez + /readyz endpoints — W1c-09 (
3fee107) - companies-admin: server-side filter/sort/paginate + quota bars + plan catalog (
f39c49f) - guardrails: diff-based silent-catch check (W4-6) (
05829a5) - id-card + gating: virtual ID card + per-user module gating (#14 + #29 Phase 2) (
c904acd) - print: task-first hub + filter dropdowns + value slider + per-sticker text size (#31b) (
de046b8) - nfc: Web NFC writer + iPhone/USB fallback + batch CSV (#34) (
a22b2b7) - returns: scan-on-return + nightly reminder cron (#32 + #33) (
a883a24) - modules: canonical module registry on the backend (#29 Phase 1) (
148ed38) - wave2-ui: budget placeholder UI, safety editor + tab, channel prefs, digest mode (
3989c3f) - safety: safety flags on items + production safety endpoints (#18 v1) (
7aa2ec8) - budgets: mark-purchased + one-click placeholder item (#23 v1) (
6d5fda0) - notifications: defensive tenant binding + delete endpoints (#27 v1) (
9ee69d3) - exports: branded XLSX header + no-store cache on every export (#17b) (
ca7bd31) - help: static help hub + contextual ? icons on core pages (#16) (
d10fa1d) - print: field-visibility picker + multi-select category filter (#20) (
5b8e765) - landing: add Brighella story section (#19) (
25f1077) - import: add dry-run preview to items import (#24) (
2bf1b50) - print: location stickers with QR — print sheet + scan flow (#20b) (
346ec98) - scan: gate scan beep on user preference, extend to more surfaces (#15) (
1d14e47) - i18n: rename "Season Overview" to "Hours & Planning" (#26) (
215f47a) - admin: force-logout-user endpoint + UI button (
55c787a) - frontend: redirect to login on SESSION_REVOKED (
1718ece) - auth: increment session_version on revocation paths (
45f33c3) - auth: verify session_version on every authenticated request (
2ee8522) - auth: add session_version column to users (migration) (
a5a2693) - frontend: verify-email flow + i18n keys (
4ef999f) - auth: grandfather invite-accept as auto-verified (
822bd1f) - auth: verify-email + resend-verification endpoints (
9ae5fa7) - auth: signup sends verification email, login rejects unverified (
0b89cff) - auth: email-verification helper + mailer template (
a6711d4) - auth: add email_verified column + verification_tokens table (migration) (
516ec36) - auth: logout-all-devices endpoint (B4) (
c2e0d56) - observability: Sentry breadcrumb + captureException per cron fire (
43206f9) - phase4: damage photo reporting on checkout return (B17) (
3e22822) - phase4: insurance expiry tracker + crew conflict detection (
53e4d88) - security: Phase 1+2 security hardening & infra improvements (
e073aac) - A15: add AI usage summary endpoint and dashboard card (
a8d39fc) - A14: flesh out production template clone-to-production (
0c0afd7) - A11: add bulk checkout & allocation endpoints with UI (
2a240bc) - budgets: add variance endpoint and Var% column to budget line table (A9) (
f3b5b3b) - health: add /api/live and /api/ready for separate liveness/readiness checks (
db223b3) - middleware: add x-request-id correlation ID + morgan format update (
69734c2) - mailer: add email_log table + lib/mailer.js observability layer (
b9615ef) - jobs: add job-runner wrapper + job_runs log table for cron observability (
c287081) - db: migrate budget tables to migration runner (remove ensureBudgetTables) (
3e0ecc1) - platform-admin: add MFA login flow to PlatformLogin (
60f9ccd) - security: harden global admin login with mandatory TOTP MFA (
1974bc3) - add /api/health/storage diagnostic endpoint for global admin (
53a120b) - collapsible admin sidebar section with localStorage persistence (
8286d8c) - brighella-rename: fix remaining brand-string misses in pages, components, AI prompts, e2e tests (
9c48884) - brighella-rename: update TOTP issuer + webhook test payload (
5c60c52) - brighella-rename: migrate default app_name to Brighella for existing tenants (
8e75415) - brighella-rename: fix server.js log banner brand string (
263b186) - brighella-rename: update default app-name strings + onboarding (slugs preserved) (
edc226f) - brighella-rename: rename data export filename in UserProfileModal (
bcc9d53) - brighella-rename: rebrand landing, layout, login/signup, branding components (WhyStagewise→WhyBrighella) (
1175ce2) - brighella-rename: rebrand HTML root, landing, SEO assets (llms.txt, sitemap, robots) (
ca4ae2b) - brighella-rename: rebrand iCal PRODID, export filenames, PDF footers (UIDs preserved) (
e734178) - brighella-rename: rebrand email sender display name, subjects, footers (
0246fa2) - spaces: pre-fill booking form from URL params and auto-open when navigated from calendar (
844a5eb) - spaces: show date range banner and book-for-dates button when navigated from calendar (
ce7185f) - productions: auto-open ProductionFormModal with pre-filled dates from URL params (
d4e3998) - productions: add initialDates prop to ProductionFormModal for calendar pre-fill (
fa84fd9) - events: add initialDates prop to EventFormModal for calendar pre-fill (
abde1d8) - global-calendar: add hover preview to all five calendar views (
9d09189) - global-calendar: add type-based navigation, permissions, Escape key, hover preview state (
fdb21e0) - global-calendar: refactor BookingModeOverlay with type buttons and day count (
6b7ed09) - i18n: add booking mode type picker keys to all 5 locales (
7f99a1e) - demo: show toast on DEMO_READ_ONLY 403 response (
6223306) - demo: wire DemoSidebar into AppLayout and DemoLanding into App root (
13d3fc2) - demo: add DemoLanding two-mode entry modal (
a083614) - demo: add DemoSidebar role-switcher panel (
0752590) - demo: add i18n keys for demo role switcher in all 5 locales (
9466a24) - demo: add switchDemoRole and demoLogin actions to authStore (
bcb680a) - demo: register demoReadOnly middleware and demo route in app.js (
a69640a) - demo: add POST /demo/switch-role endpoint (
a518e5a) - demo: add POST /auth/demo-login for permanent demo auto-login (
0776b06) - demo: add demoReadOnly middleware — blocks writes on permanent demo (
816f493) - events: add event name column to events overview table (
f04a2d5) - global-calendar: add View Production deep link in DayDetailDrawer expanded item row (
acb93e8) - admin: add calendar feeds section to site-type locations in admin (
23ad7f0) - frontend: add Subscribe button and wire CalendarSubscribeModal in GlobalCalendar (
6856d15) - frontend: add CalendarSubscribeModal for venue iCal feed management (
c3b816c) - security: rate limit public iCal feed to 60 req/hour per IP (
ab91bc4) - api: add GET/POST/DELETE venue token management routes (
fd0c46e) - ical: extend feed endpoint to serve venue/org-wide calendar feeds (
037a410) - frontend: add useCalVenueFeeds hook for venue iCal feed management (
e5d4035) - global-calendar: add CSS layout for calendar-specific grids and chips (
ebe6ca7) - i18n: add calFeed* keys for venue calendar subscription UI (
71bc173) - db: add cal_venue_feeds table for per-venue iCal subscriptions (
dd8c1ef) - routing: register /calendar/overview route in routeNames config (
d92bc26) - backend: add site_id filter to /spaces/bookings/all and range to /venue-closing (
51a6ec9) - global-calendar: wire full GlobalCalendar page with all views, drawer, booking mode (
c1b14c9) - global-calendar: add BookingModeOverlay for inline booking staging (
25aabce) - global-calendar: add persistent DayDetailDrawer (
d5f6cad) - global-calendar: add ListView with RehearsalGrid-style density (
92ff8ac) - global-calendar: add WeekView with hour timeline (
67d2b03) - global-calendar: add YearGridView with heat coloring (
aa843ae) - global-calendar: add YearTableView with expand/collapse rows (
2148732) - global-calendar: add MonthView and bg-stripes CSS utility (
149b2ce) - global-calendar: add FilterBar and MoreFiltersTray (
2beb56f) - global-calendar: add TimeJumpControl, ViewSwitcher, GlobalCalendarHeader (
0925d2c) - global-calendar: add route, nav entry, and skeleton page (
73215fe) - global-calendar: add useGlobalCalendarData parallel-fetch hook (
224dc5e) - global-calendar: add normalize-items, group-by-day-venue, calendar-range utils (
91e0aac) - ui: add reusable MultiSelect component (
5ad29af) - i18n: add global calendar translation keys (
b66daa4) - arch: unify server.js — delegate all Express config to app.js (
1641a28) - ai: implement photo_id capability with vision model support — completes all 11 enterprise AI stubs (
4eb0c97) - ai: implement allocation_recommendations, conflict_resolution, load_optimizer (
523087c) - ai: implement fatigue_warnings, crew_conflicts, cost_forecasting, notification_routing (
0a5e3b9) - ai: implement meeting_notes, brief_parser, onboarding_assistant capabilities (
f434a24) - i18n: complete DE/SV/NO locale coverage — 882 keys added per locale (
3e98338) - release: optional invite codes + E2E authenticated flow tests (
bc6753e) - security: add rate limits for GDPR self-service endpoints (
47fdbd0) - domain: replace hardcoded stagewise.app with VITE_HOST_DOMAIN env var (
e9e5bf9) - kiosk: add Remove PIN and Set PIN buttons to display cards (
58fff06) - i18n: add kiosk PIN management translation keys (
280898d) - release: Phase 1 GDPR gate + Phase 2 Sentry & feedback channel (
33635f8) - add PrintCenter route name entry (
9b010f5) - register /items/print-center route and add to inventory nav (
36ee860) - add PrintCenter page with split-panel item browser and A4 sticker preview (
159171a) - sticker: add manual mark-as-labeled button to legacy bulk sticker page (
5c4b845) - sticker: add onafterprint labeled confirm banner to single sticker page (
4c50ac9) - items: add physical label toggle to item detail page (
b44fef8) - items: add labeled filter to GET /api/items (
595f64e) - items: add labeled status badge and filter to items list (
44c7e5f) - i18n: add labeled status and print center translation keys (
9c49bbc) - items: add POST /api/items/bulk-label endpoint (
9c68990) - items: add is_labeled field to schema, updatable fields, and PUT handler (
45cbf0a) - db: add is_labeled + labeled_at columns to items (
97cd5d9) - arch: phase 1 architecture improvements — route parity, helpers split, new tests (
7e99c46) - seed: expand develop seed to Bølgescenen — 40 staff, 12 productions, full feature data (
6e89ebc) - external-offers: add /external-productions route + nav link (
77d001c) - external-offers: ExternalProductions page with offer list + detail view (
a404058) - rehearsal-templates: Save as Template + Apply Template UI in CrewSchedule (
b8574de) - rehearsal-templates: RehearsalTemplateLibrary component (
e84a21c) - external-offers: register /api/external-offers in app.js and server.js (
5d6d5b9) - external-offers: full CRUD, convert-to-production, PDF export route (
2984be2) - external-offers: add external_offers, line_items, attachments migration (070) (
59570f4) - rehearsal-templates: register /api/rehearsal-templates in app.js and server.js (
ae08bac) - rehearsal-templates: CRUD + from-entries + apply route (
ad3d58e) - rehearsal-templates: add rehearsal_plan_templates migration (069) (
5ce9fde) - venue-closing: manager closing schedule editor in KioskHome (
3861a54) - venue-closing: manager closing schedule editor in KioskHome (
ace47a0) - kiosk-alerts: mount PushMessageBanner in KioskDisplay (
39913ec) - kiosk-alerts: PushMessageBanner component with 30s polling (
d1e2e17) - venue-closing: VenueClosingCard kiosk component + card type registration (
067214f) - kiosk-alerts: add kiosk-alerts route with active endpoint + auto-expiry (
cce13f3) - venue-closing: register /api/venue-closing in app.js and server.js (
4ecf2cd) - venue-closing: add venue-closing route with CRUD + today endpoint (
88b256a) - venue-closing: add venue_closing_schedule migration (
ebb7939) - show-reports: notify dept members when dept remark is added/changed (
62eb5d7) - db: migration 068 — enable AI chat capability for default tenant (
f94b51b) - ai: wire chat bubble to DO Gradient AI via new chat capability (
5559ec5) - landing: landing page selector in profile settings (
d5f8abd) - landing: redirect to preferred_landing after login (
fc8d69c) - landing: store preferred_landing in ui_preferences, expose in /me (
42d9e2a) - landing: add central APP_ROUTES registry (
2e7c79e) - todos: all-user selector + assigned-to-me filter chip (
466abaa) - todos: filter by direct user assignment in GET, allow null dept on POST (
b940abf) - ai: add audit log summarizer capability — Phase 2 complete (
bf5d955) - ai: add predictive maintenance alerts capability (
f7d6325) - ai: add duplicate item detection capability (
6bbf320) - ai: add budget variance explainer capability (
a54f42e) - ai: add item description generator capability (
76ba602) - ai: add auto-tagging and categorization capability (
08def6a) - ai: add natural language search capability (
c3d1561) - ai: add global kill switch + capability loader (
774b089) - ai: add pgvector migration for Phase 2 semantic search (
c3177e9) - ai: wire admin AI settings page into router + add tenants/me/ai endpoints (
caf35fe) - ai: add admin AI settings page with feature toggles and usage bar (
faf2029) - ai: register AI routes at /api/ai in app.js and server.js (
136b312) - ai: add AI route with structured error handling (
ec29dd8) - ai: add capability registry with plan/toggle/credit gates and caching (
708b9ef) - ai: add DO Gradient AI client wrapper (
f138cda) - ai: add ai_features column and ai_usage/ai_cache tables (
1e5debf) - export: full tenant backup with uploaded files (
e7d8741) - profile: let users choose their default landing page after login (
21fb5e2) - export: full tenant backup with uploaded files (
3c494a0) - kiosk: limit production feed card to 3 most recent posts (
ca4facc) - kiosk: add per-card text size expand panel in settings (
05b83a1) - kiosk: use CSS custom properties for card heading/body font sizes (
03bef09) - kiosk: wrap RenderCard with KioskCardWrapper for size + scroll (
e309425) - kiosk: add KioskCardWrapper with CSS vars and auto-scroll (
85e7cb1) - kiosk: add SIZE_MAP and headingSize/bodySize to ensureCards (
83343a9) - kiosk: add Production Feed card to kiosk display (
049c4b4) - productions: replace custom equipment search with ItemCombobox (
53fcdfb) - items: ItemCombobox — allocatedIds prop + pass item to onChange (
f3632ed) - events: replace equipment select with ItemCombobox (
9dbfa91) - items: add ItemCombobox component with dept/category chips (
f11b9fc) - qa: tenant-admin QA mode toggle + qa_tester checkbox (
f29dd58) - i18n: add item combobox translation keys (
d6ecc13) - events: spreadsheet-style overview table with grouped rows, expand, delete confirm (
d2133ad) - qa: qa_mode toggle on the QA Reports page header (
d355b3f) - i18n: add events overview table translation keys (
e6b6ed9) - api: add staff_names array to GET /events list response (
16105a8) - db: add capacity and tickets_sold to events (
79042db) - qa: i18n for all overlay and reports strings (
0127850) - qa: QA Reports admin page + route + nav (
51ed6f0) - qa: admin bug list, card, and screenshot modal (
0d3aad6) - qa: tree builder and QAReportsTree component (
2976b79) - qa: qaStore for admin reports page (
98088df) - qa: QAOverlay wrapper and AppLayout mount (
a358fc4) - qa: QAFab and QABugDrawer components (
f38ed83) - qa: QABugForm component (
5520bc0) - qa: store fields for qaMode and qa_tester (
bf2b92b) - qa: screenshot capture utility (
ac16993) - qa: generator script for route names (
d9bd8e9) - qa: admin toggles for qa_mode and qa_tester (
8c3f1be) - qa: expose qa_mode and qa_tester to frontend (
3002f8c) - qa: GET /api/qa/bugs/export endpoint (
20471b7) - qa: export service for markdown + zip bundle (
a8314ed) - qa: PATCH and DELETE /api/qa/bugs/:id (
f2d128f) - qa: GET /api/qa/bugs list and :id endpoints (
16fa84f) - qa: POST /api/qa/bugs endpoint (
46f2a57) - qa: add requireQaAccess middleware (
461e73f) - qa: add bug payload validator (
9b013df) - qa: add migration for qa_bugs table and flags (
3f698ad) - invite-codes: store and display sent_to_email (
dd67274) - rehearsal: rebuild overview with phases, performances, rehearsals, meetings cards (
4496901) - rehearsal: scrollable grid with extended date range and auto-scroll (
4c86274) - rehearsal: scrollable calendar with auto-scroll and planning phase (
3ec7ec2) - rehearsal: add i18n keys for meetings, overview cards, planning phase (
1dad74e) - rehearsal: include planning_start in production CRUD (
4a7728c) - rehearsal: add meeting entry type (
6179dd8) - rehearsal: add shared entry categories utility (
5ec00a5) - rehearsal: add planning_start column to productions (
3c3a8ad) - comms: Phase 1 quick wins — timestamps i18n, nav badge, edit, read receipts (
bdedcc6) - comms: add edit functionality for posts and comments (
646750d) - comms: add unread dot badge on Comms nav item in sidebar (
fa60389) - comms: add permanent General channel as default feed (
8f8cb61) - comms: add optional headline to posts for better visibility (
5af0292) - comms: show newest comment always, expand to see rest (
ebc5c77) - comms: limit to 1 reaction per post, replace View with Pin button (
32332f3) - comms: add unread dot indicator on channels with new activity (
5abfc7d) - comms: add delete for chat messages and entire chat rooms (
7107d80) - comms: show chat room name in header with back arrow (
688a81b) - comms: add delete/pin actions to posts, restyle document cards (
aae2dcc) - seo: add AI discoverability with llms.txt, JSON-LD, robots.txt, sitemap (
4840ecf) - comms: add guest role elevation — guests can optionally be invited as managers (
b034363) - profile: add profile completion modal on first login with department self-assignment (
a4a6391) - comms: rename Onboarding tab to Info Hub (
9cac9e9) - comms: make chat room channel optional for DMs and general chat (
dae3935) - comms: allow staff role to post to feed (
ef9e930) - billing: restrict messaging feature to Enterprise plan only (
04e7302) - comms: add custom group CRUD and chat room creation (
1fa9e1c) - billing: implement finalized 4-tier pricing with location and loan limits (
5c7ec38) - comms: add reaction counts, comment count, and user reactions to announcement list (
3f69c4a) - comms: rewrite Comms page with social feed layout and floating right panel (
e4d6afb) - comms: add PostComposer with inline expansion and channel selector (
dd37f72) - comms: add PostCard component with reactions, comments, and social layout (
8a587e5) - comms: add ReactionBar and CommentThread components (
12cdbb5) - comms: add hooks for comments, reactions, and contacts (
b388a7d) - comms: add i18n keys for social feed, groups, contacts (
da9cd67) - comms: add contacts endpoint and channel sync (
798e0e5) - comms: add reaction endpoints for announcements, comments, and chat (
dc7dc78) - comms: add comment endpoints for announcements (
a16053a) - comms: add migration for comments, reactions, and channel auto-sync (
aca8bf4) - billing: refine plan limits and add location/loan limit checks (
41da952) - comms: add routes and sidebar navigation for messaging module (
fba13e3) - comms: add Comms, CommsPost, CommsChatRoom, and CommsGuestJoin pages (
63c2c50) - comms: add DocumentCard and DocumentUpload components (
37eb7d9) - comms: add ChatMessage and ChatInput components (
cc0bc59) - comms: add AnnouncementCard and AnnouncementForm components (
58e89ec) - comms: add shared UI components (GuestBadge, ChannelFilter, ReadStatus, PollDisplay) (
d831393) - comms: add frontend data hooks for all messaging subsystems (
ffeb262) - comms: add messaging module config and i18n keys (en + da) (
696de55) - comms: mount messaging routes in app.js (
d6060b2) - comms: add guest invite and join routes with tests (
4de84ac) - comms: add document sharing route with tests (
a297cf2) - comms: add chat rooms route with WS broadcast and tests (
c1fe080) - comms: add announcements route with polls, read tracking, and tests (
c98ad72) - comms: add channels route with tests (
408dd5f) - add database migrations for internal messaging module (
4fdf476) - iCal calendar feed, Slack/Teams webhook UI, settings integration (
a45cf9e) - smart reminders, Slack/Teams webhooks, cal feed migration (Phase 1) (
8c16332) - barcode product lookup, parent-child items, module rename (
5bb0e2a) - add Why StageWise sales page at /why-stagewise (
edb9296) - enterprise-only full features with tiered plan gating (
e83591f) - update pro plan to 5 users / 5000 items, align landing page with actual pricing (
c86eacc) - starter tier + inventory-only gating for free/starter plans (
d469ef9) - update billing page pricing to DKK, add upgrade prompt modal (
dc060a3) - platform metrics dashboard with P&L projections calculator (
b0993cf) - plan tier limits enforcement — Free/Pro/Enterprise with item add-ons (
17c5225) - localized onboarding templates — seed data in user's language (
a385330) - sponsor modal with plan and duration selection (
2c6b188) - require invite code for signup — prevent bot account creation (
7908659) - admin support tab in settings with source-tagged tickets (
a729e19) - sponsored subscriptions — free-for-life Pro/Enterprise access (
a4f3e4a) - add instructions to invite codes admin page (
03fd097) - confirm password field on signup form (
ec7cb4b) - hybrid signup — open free tier + invite codes with plan selection (
95dd704) - email invite codes from platform admin with optional message (
e53e6ed) - flyout menus for collapsed sidebar nav groups (
5822714) - multi-department user membership (N:N junction table) (
48b84d7) - connect weekly hours (actuals) to season overview (plan) (
cbc7264) - cross-browser e2e testing — add Firefox and WebKit (Safari) (
fef66c6) - support ticket system with threaded replies and email notifications (
221e408) - custom message in invite emails + platform admin invite (
3438442) - custom fields for onboarding wizard steps (
3c15531) - progressive disclosure on ItemFormModal — simplified create mode (
ff980b6) - sortable Table columns + server-side loan search (
1ef6c8f) - season-style rehearsal grid with day tags, crew calls, and legend (
5084be5) - TOTP 2FA authentication + Playwright E2E test suite (
4acd86d) - Network Marketplace — buy/sell/give-away between connected venues (
3aad900) - pull sheet mobile UX, scan feedback, utilization analytics, 95 new tests (
57586d0) - Production Hub enhancements — timeline, conflicts, reminders, collapsible (
4ee9457) - calendar persistence, sticker print, recurring events, hours notifications (
eb54d0b) - remember-me, user search, notifications, audit log, i18n, tests (
2e94902) - add participants (users + external names) to rehearsal entries (
91c175e) - require PIN to exit kiosk display or access settings (
d144f47) - kiosk broadcast alerts for cancelled rehearsals + calendar default view (
6260651) - server-side kiosk displays with PIN lock, sharing, and timezone setting (
fc736f8) - show company logo in kiosk display header (
61ea80d) - clickable dashboard stat cards + kiosk header date layout (
adccd4b) - replace total value stat card with My Open Tasks on dashboard (
fd4f90d) - two-level sidebar customization — group toggles + individual items (
5d72277) - vertical calendar view for rehearsal plan with side panel editor (
3055d21) - crew workload heatmap, depreciation report, notification triggers (
ef4ce37) - QA fixes + 2 new reports (utilization, cost comparison) (
fe1cdfa) - kiosk display redesign — full-viewport 2x2 grid, rehearsal plan card (
8022d42) - show selected production name, venue and dates in kiosk top bar (
ff367cc) - multi-preset kiosk dashboards + navigation links (
1dd8c33) - add kiosk display mode — customizable TV/backstage dashboard (
317feb2) - add Simple Mode — simplified 6-button inventory UI (
37570d9) - configurable feature modules per venue (
e51aa3b) - add i18n keys for feature module settings (
179bd67) - rental gear tracking per production with budget integration (
9881945) - add rehearsal & show plan tab to production detail (
5acb7b3) - scan-to-import with OCR label reading for equipment migration (
c0cbc5c) - quick scan mode with inline item editing on Scan page (
b38f16b) - add Manuscript tab with versioned file uploads per production (
92553b0) - add German, Swedish, Norwegian translations + language dropdown (
085673d) - add venue room/space management with bookable resources (
d88d1b6) - add Save button next to Change Photo in profile modal (
f29bf5c) - complete retire system with bulk, undo, export, reasons, item actions (
598004e) - production overview tab with phase timeline, stats, quick actions (
dfa393f) - custom app name branding + "Powered by Stagewise" subtitle (
140f10c) - retire items + fix crew crash, event spacing, login i18n (
65f977c) - budget edit/delete + improve MyHours readability (
6a9fa7b) - add grid/list/timeline view toggle to Productions page (
daa6487) - show reports — nightly production reports with email & PDF (
2d824e5) - Nordic Dark theme — teal accent, deeper blue-gray palette (
eb13566) - reusable Tabs component with ARIA + refactor Admin page (
5c5ed73) - convert all confirm() to useConfirm + kiosk export (
30ff2ce) - kiosk scan log export (XLSX) + verify cron overlap protection (
c0e8d9c) - replace browser confirm() with app Confirm + tab validation (
550bbdc) - holiday management UI in season settings modal (
2d31de0) - hours-based utilization with per-annotation hour input (
f585310) - configurable work year norm for season utilization (
1d2b4c3) - drag-to-select bulk annotation + utilization bar in season grid (
906b15b) - configurable activity code labels + season grid polish (
698ddad) - rewrite season grid — true 52-week layout + major UX improvements (
abd88fb) - add single and bulk delete for bundles (
a0acac6) - create new bundle directly from bulk action dropdown (
02d6155) - add selected items to bundle from bulk action bar (
90dadb8) - integrate bulk print page into standard StageWise layout (
31d1e11) - add sticker/QR toggle and A4 sheet layout for bulk print (
e21b79e) - bulk print QR stickers from item list (
dbf5410) - add budget visibility toggle in admin settings (
4406ca7) - configurable onboarding wizard from platform admin (
a3126f8) - show equipment value rollup on production overview (
857d70c) - add toggle to show/hide images in items grid view (
439a16a) - redesign season overview with uniform 4-week months, per-site RMS, and improved readability (
c09a868) - expand depreciation system with multiple methods, schedules, and lifecycle tracking (
d7f5490) - add phase-specific notes for productions (load in, show, load out) (
1fbfb3f) - add required site/location field to user creation form (
76a99e5) - replace paid checkbox with custom realized amount input and diff column (
6066e10) - add grid/list view toggle to Items and Browse Catalog pages (
19a6f54) - seed network connections for ephemeral demo sessions + yellow signout button (
94774ca) - error states on 28 pages, search keyboard nav, bulk loan return UI (
fb2d8f5) - add season planning & balance module (AKOS replacement) (
1062a57) - add expand all / collapse all buttons to locations page (
3594577) - redesign maintenance dashboard with modal form and item picker (
5f64c68) - add site/location field to productions (
8290025) - add global site/venue filter across all major views (
6ff965e) - add contextual tips to 22 additional pages (
a61aaca) - add Events module under Productions with full CRUD, staff, and equipment linking (
b37ad06) - add develop test company seed with all features populated (
96da5a8) - add partial returns, handoff confirmation, and borrow notifications (
63801c4) - add lending tip to ItemFormModal and update Loans tip (
71c527d) - add per-item lending configuration with network catalog sync (
cd42230) - add Zod validation middleware and structured API errors (
ef9e206) - update import template to match user's modified layout (
0ed0a49) - add select all checkbox to items list (
c03fa2e) - convert all exports from CSV to XLSX (
e4d8467) - receipt upload when creating budget lines (
e38d447) - over-budget indicators for individual budgets and budget overview (
9b9013a) - add Budget Overview link to sidebar under Productions (
54a64dc) - import template now generates proper XLSX with grid layout (
1301935) - remove logo button, storage limits per plan, billing UI (
4b0d5ef) - enrich demo seed data for new features, move AI button into FAB group (
63d5460) - new StageWise logo — implemented across all brand touchpoints (
9b56e94) - Network enhancements, real Stripe billing, contextual helper text (
88815bb) - Call Sheet, Calendar sync, Webhooks, Onboarding templates + tests (
db98a34) - Pull Sheet + Utilization & Cost Reporting — features #2 and #3 (
254c5a9) - Production Hub — tabbed mission control for production managers (
9121a06) - Lucide icons, inline style extraction, responsive polish, i18n, page tests (
9f69fe9) - superadmin billing overview + fix admin tabs and financial table CSS (
ccc37eb) - budget receipts, editable lines, realized checkbox, PDF redesign (
a2ffb62) - budget VAT support — country/custom rate, excl/incl columns, totals (
0d8f4bf) - budget PDF export + fix cache invalidation and tenant isolation (
8fa32c9) - fix budget page — add i18n translations, create budget modal, fix search (
1e8aa0f) - theme toggle on Landing/Login pages + prevent theme flash on load (
1e5873e) - skeleton loaders on data-heavy pages + i18n for maintenance & loans (
7873285) - fix budget page crash + add budgets listing with sidebar nav (
5e51158) - seed demo sessions with budgets, notifications, guest links (
623b1ef) - batch scan mode — scan multiple items, assign to production/location (
cae2482) - budget and notification preferences frontend pages (
0a370b1) - department budget tool per production (
689668a) - Eventbrite ticketing integration (
be037db) - QR mobile checkout, maintenance reminders, call sheets (
07be764) - add product screenshots for landing page (
3bff4b8) - redesign landing page with modern SaaS layout (
d58c95c) - error handling, accessibility, search, notifications, CI/CD pipeline (
44ad601) - security hardening, 75%+ test coverage, DO Spaces migration, feature brainstorm (
93bf407)
Changed
- a11y: extract useDialogA11y hook, migrate DeleteCompanyDialog — WB-25 (
7544061) - api: standardize pagination envelope across 25 list endpoints — WC-§5.5 (
c0c30ac) - routes: split items.js (786 LOC) into concern-scoped files — WC-§5.3 (
8588918) - routes: split tenants.js (1225 LOC) into concern-scoped files — WC-§5.3 (
9db02ee) - routes: split auth.js (1369 LOC) into concern-scoped files — WC-§5.3 (
3cc746c) - jobs: migrate 5 crons to forEachActiveTenant helper — WC-§5.1 (
ee48481) - auth: extract data layer to services/auth.js — WC-§5.4 (
a3970ae) - productions: extract data layer to services/productions.js — WC-§5.4 (
c4d9fcc) - items: extract detail orchestrator + list SQL to services/items.js — WC-§5.4 stage 2+3 (
c5e7cd4) - items: extract Tier A + Tier B + shared helpers to services/items.js — WC-§5.4 stage 1 (
c7a503a) - billing: push MRR/ARR/churn aggregates into SQL — WC-§5.6 (
cb4249a) - files: extract file-serving from app.js — WC-§5.8 (
4afb2e8) - loans: extract reminder cron to jobs/loan-reminders.js — WC-§5.2 (
0f94137) - jobs: forEachActiveTenant helper + migrate 3 crons — WB-11 (
590ca1d) - config: consolidate hardcoded domains behind app-domain helpers — W1c-11 (
56a1c8f) - routes: migrate marketplace-listings to runWithTenant — W1-H07 (
8e60dff) - services: migrate borrow-notifications to runWithTenant — W1-H07 (
02cfbe2) - env: strip FRONTEND_URL fallbacks (C17) (
f7394c5) - crons: maintenance + production reminders → runWithTenant (
6a387e0) - insurance-alerts: use runWithTenant + query instead of pool.query + quoteIdent (
35bdc4c) - items: extract DETAIL_SUB_QUERY_LIMIT constant for detail sub-queries (
cd26c56) - plan-limits: extract logFailOpen helper + harden test NODE_ENV (
26b7762) - rename guest share links to "share" (Part B) (
c61ebca) - remove permanent shared demo tenant (mode #2) (
6a8141e) - kiosk: move PIN input inside canManage block, add non-manager test (
8e7fbb9) - productions: remove manual equipment search state — replaced by ItemCombobox (
609bf35) - decompose 7 oversized components into sub-components (
6847986) - split ProductionDetail, Calendar, CrewSchedule into sub-components (
6b2707f) - split Admin.jsx into 11 sub-components (
485eb15) - split i18n monolith into JSON translation files (
9771f67) - convert export templates to column/row/cell table layout (
261733e)
Fixed
- ops: §6.5 route health probes through queryPublic + enrich payload — WB-26 (
81b93c5) - security: §2.7 set X-Content-Type-Options: nosniff on file proxy — WB-24 (
2afe40b) - a11y: §8.4 add role=dialog + focus restore to 3 bespoke modals — WB-53 (
6556a98) - a11y: §8.11 keyboard support for 3 remaining clickable divs — WB-55 (
f38af44) - a11y: §8.10 announced ErrorBanner + migrate 10 consumers — WB-54 (
698cee3) - i18n: §8.6 localise ExportPDFModal output + modal descriptions — WB-50 (
2e25851) - auth: tighten §2.9 apex tenant-slug match — WB-23 (
50bc68b) - share: distinct public prefix + startup auth guard — WB-22 (
1671aef) - rate-limit: §2.6 shared Postgres store + horizontal-scale guard (
dd253c3) - shutdown: §9 stop crons on SIGTERM before HTTP drain (
b12e678) - errors: §9 Express error handler — Sentry capture + stack logging (
66e91fe) - a11y: §8.7 aria-labels on 11 icon-only buttons (
dc177d7) - reviews: §6.12 pg_dump kill-on-disconnect + §8.8 CommsPost notFound i18n + §9 remove stale build markers (
60d9619) - wave-c: 11 frontend correctness bugs + Zustand selector migration — WC-04 (
7987df5) - domain: fail-fast in production when HOST_DOMAIN unset — WB-22a (
bb64956) - files: tear down upstream Spaces fetch on client disconnect — WB-21 (
d89d711) - shutdown: await HTTP drain before closing DB pool — WB-20 (
8abd2c1) - i18n: replace hardcoded button/loading text with t() — WB-17 (
b407fd6) - i18n: add 67 missing keys across 5 locales + CI gate — WB-16 (
2a865c5) - mailer: AbortSignal.timeout so Resend cannot hang the caller — WB-15 (
fbf2b62) - cal-feed: fold iCal lines by UTF-8 octets, not code units — WB-09 (
623bbe5) - ai: checkCredits reads plan via resolvePlan, not ctx.tenant.plan — WB-06b (
1008765) - kiosk: public mirror table for share tokens — WB-08 (
89c3afe) - jobs: null-check free plan + per-tenant try/catch in trial-expiry — WB-07 (
d44474a) - ai: fail closed to 'free' when subscription lookup errors — WB-06 (
8d81495) - jobs: use UTC day math in production-reminders — WB-05 (
207f5fe) - jobs: per-admin NOT EXISTS dedup for maintenance reminders — WB-04 (
30edd7e) - productions: windowed aggregate catches N-way overbookings — WB-03 (
a20581c) - allocations: wrap reserve in transaction with FOR UPDATE — WB-01 (
682b3be) - loans: await overdue email before flagging sent — WB-02 (
94cf068) - files: reject cross-tenant namespaced-key reads — WA-A6.5 (
ed527b1) - storage: tenant-namespace backfill script for legacy flat keys — WA-A6.4 (
b52ac57) - storage: tenant-namespace uploads + rewrite public-file regex — WA-A6.3 (
7b49fa6) - guest-join: use raw tenant slug + emit session_version claim — WA-A8 (
3fd6b44) - share: require staff + gate on visibility, strip sensitive fields on public GET — WA-A7 (
95989b2) - migrations: reconcile tenant.loan_snapshots 010/011 split — WA-A5 (
a95e60a) - db: enforce server-side statement/idle timeouts on every pool connection — WA-A10 (
adff6d0) - loans: drop JSON.parse on jsonb snapshot — WA-A4 (
a914f1f) - search: alias items table so itemVisibilityFilter fragments resolve — WA-A3 (
f711270) - billing: use tenants.slug (not non-existent schema_name) on subscription cancel — WA-A2 (
2927397) - users: bind target user id via \$1 placeholder in force-logout — WA-A1 (
d0ef4f9) - db: remove unused tQuery param from runWithTenant callbacks (
6663764) - security: per-user rate limit on /api/files — W1c-06 (
d4c8f08) - security: assert trust-proxy configuration in prod — W1c-05 (
b7e6517) - security: use .pgpass instead of PGPASSWORD for pg_dump — W1c-04 (
d475715) - security: harden /api/files response headers — W1c-03 (
1c739e6) - security: add magic-bytes check to items upload — W1c-02 (
7b89177) - security: upgrade kiosk PIN bcrypt cost to 12 — W1c-01 (
df13011) - security: verify JWT iss/aud on decode — W1-H03 (
e1cf867) - jobs: wrap refresh-tokens-cleanup in runJob — W1-H06 (
cefa320) - jobs: wrap return-reminders in runJob — W1-H05 (
09f546f) - jobs: wrap loan-reminders in runJob — W1-H06 (
400c59a) - jobs: wrap digest-sender daily+weekly in runJob — W1-H06 (
e64655a) - security: consolidate webhooks.js module.exports — W1-H01 (
cf00642) - server: handle uncaughtException and unhandledRejection — W1-H04 (
ce286af) - jobs: wrap demo-sessions-cleanup in runJob — W1-H06 (
7e39a02) - tenants: prevent load-bearing tenant deletion + apex fallback (
1e608d6) - quality-sweep: wave-2 critical bugs, security, observability (
fddf7e1) - branding: logo delete/upload now updates sidebar immediately (
58a912c) - uploads: cache-bust image keys with timestamp suffix (
6fdfce6) - nginx: /api/ prefix must be preferential (^~) to win over .jpg regex (
8094234) - a11y: overlay + search-result rows are now buttons (W4-5) (
258e254) - frontend: kill 7 silent catches (W4-2) (
4415a3e) - security: log silent catches + wrap data-retention cron (W4-1) (
fbbc391) - storage: fail-fast on bad SPACES_ENDPOINT + health check (W4-0) (
1a07d2e) - print: location batch placeholders + invalid CSS gap units (#31 bugs) (
14e496d) - xlsx: use res.end instead of res.send — prevents 304 empty body (
b0af861) - import: template download returned 304 on second click, silent failure (
aa3b2bd) - demo: unlock every module + restore role switcher (#21) (
3c0568d) - migrations: pre-create tenant schema_versions to avoid public-table shadowing (
c726d6a) - audit: backfill-redact existing audit_log rows (B5 followup) (
6304a5e) - audit: redact secrets and PII values from audit_log.diff (B5) (
597fd60) - session: disconnect WebSocket on session revocation (B3) (
1abebb1) - logs: redact sensitive values across backend loggers (
9ec4f5a) - websocket: fail-closed Origin check on upgrade (
6a0b5d2) - mfa: enforce single-use on MFA challenge tokens (
fd6ec50) - seed: remove plaintext admin password from log (
36ef330) - authz: tighten financial aggregate endpoints to manager/admin (F1 MEDIUM) (
e75b28d) - authz: require staff on network cross-tenant mutations (F4 MEDIUM) (
d50e126) - authz: require ownership or admin on events mutations (F3 HIGH) (
001262e) - authz: enforce department scope on items mutations (F2 HIGH) (
ca24279) - frontend-docker: relocate nginx PID + chown conf.d for non-root (
18a864a) - loans: iterate active tenants in reminder scheduler (
986c3ca) - migrations: self-heal tenant schemas missing schema_versions (
1fc15ec) - env: drop FRONTEND_URL '|| http://localhost:8888' fallbacks (
2841526) - domains: serialize Traefik config via js-yaml (C6 hardening) (
9edbbff) - crew-schedule: useCrewConflicts hook + surface fetch errors (
a963b6b) - uploads: magic-byte MIME validation on damage photos (
1d077c4) - checkouts: preserve damage fields on plain checkin (
41c1acc) - insurance-alerts: escape item name, fix plural, absolute link (
7181cb7) - advisory-lock: hold one client across acquire + fn + unlock (
dac0e9f) - jobs: pg advisory locks on all crons and 4 setInterval sites (
44e8d8d) - insurance: compute days_remaining in SQL (
aeb6d5c) - files: route damage photos through fileAuth (C1) (
1ba0e47) - reminders: enumerate active tenants (same as Task 5 insurance-alerts) (
0754e10) - insurance-alerts: enumerate tenants via public.tenants WHERE status = 'active' (
96538a3) - checkouts: 404 before multer parses uploads (
8f190da) - checkouts: wrap damage checkin UPDATE + maintenance INSERT in txn (
4ca48ed) - tenant: alias _default to default inside getTenant() (
c3d9dd0) - env-gate: trim NODE_ENV, tighten tests, document console.error (
e860872) - boot: remove dead _prodWarnings now covered by env-gate (
8db1eb4) - boot: consolidate requiredEnvVars gate (C8) (
19c58ca) - docker: create /var/run dir before nginx PID file touch (
1e38994) - stores: reset settingsStore on impersonate transitions + log billing failures (
3a80ca7) - health: mount /api/live and /api/ready before tenantMiddleware (
3679162) - plan-limits: emit structured log event when failing open on DB error (
68e3939) - middleware: morgan logs sanitized req.id not raw client header (
ef642be) - auto-progress: use canonical tenant filter (
ef269c5) - frontend: add ModalErrorBoundary to isolate modal crashes (
411727f) - startup: warn when MULTI_TENANT=true and DEFAULT_TENANT_SLUG is unset (
467346d) - tests: update mocks for quoteIdent and correct trial-expiry expected status (
11527b1) - super-admin: remove redundant i18n fallback string per project convention (
2e85af0) - admin: update test to match dynamic version string instead of hardcoded v24.0 (
e8261cb) - super-admin: show error message when tenant stats fail to load (
ad64bd7) - vite: restrict allowedHosts to prevent DNS rebinding attack against dev server (
303c62b) - platform-login: append anchor to DOM and defer blob URL revoke to prevent download race (
5095fdc) - admin: remove hardcoded database/auth/stack details from system info panel (
4752758) - frontend: add loading state check to RequireAdmin/RequireGlobalAdmin guards (
0e5d64d) - nginx: add Content-Security-Policy header (
727452b) - jobs: quote schema identifiers in reminder jobs to prevent SQL injection via crafted slug (
ae9601d) - migrations: quote schema identifier in SET search_path (
b8f74de) - migrations: break migration loop on failure to prevent applying to partially-migrated schema (
00a116a) - productions: extract explicit limitIdx/offsetIdx for LIMIT/OFFSET params (
a742262) - loans: update tests to mock transaction instead of query for single-item return handler (
db05ffa) - checkouts: store relative storage key for condition photos, not absolute URL (
676060a) - crew: include phase-only assignments (NULL dates) in team availability view (
ab60546) - data-retention: skip deleted tenant schemas to prevent silent GDPR erasure failures (
e05b5db) - productions: compute LIMIT/OFFSET param indices explicitly to avoid evaluation order dependency (
dd8aaf7) - loans: wrap single-item return in transaction so FOR UPDATE lock is effective (
61f05ea) - budgets: track ensureBudgetTables per-schema to prevent DDL skip in multi-tenant mode (
6c63c3e) - budgets: use = ANY() for deptFilter array comparison in production budget route (
a6fd889) - domains: use domainSafeName instead of path.basename for Traefik config path sanitisation (
65bb90a) - audit: validate since query param as ISO 8601 before SQL use (
4de2736) - trial-expiry: set status to active instead of free on downgrade to avoid feature gate lockout (
1adc7f7) - tenants: apply full password policy to global admin account creation and update (
bfce1f4) - auth: record failed attempt on invalid MFA/recovery code to trigger account lockout (
210c44b) - auth: apply mfaLimiter to mfa/verify-setup to prevent TOTP brute-force during enrollment (
c55ecba) - exports: correct checkouts export column from checked_out_by to created_by (
0a5c9f8) - ai: guard against null tenant context in checkToggle, checkCredits, cacheKey (
3b8256b) - auth: remove _default tenant mismatch exemption — closes cross-tenant access gap on root domain (
b78d1ef) - async-handler: document err.status convention to prevent accidental message exposure (
49a463e) - checkouts: wrap checkout creation in transaction with FOR UPDATE to prevent overbooking (
9d0f996) - platform-admin: improve recovery code contrast (
3d0334a) - platform-admin: send MFA tokens in request body, not Authorization header (
c76dd30) - tenant: add DEFAULT_TENANT_SLUG env fallback for apex-domain login (
b941b44) - add startup warning when SPACES_ENDPOINT contains bucket name (
35d3a58) - add proxy headers to nginx /uploads/ location block (
b2ef01e) - log warning on unresolvable photo_url; align urlToKey mock with real contract (
1696587) - use urlToKey() for photo deletion instead of fragile split('/').pop() (
841a5d3) - rate-limit health/storage endpoint; safe error message; guard getS3Client (
205ebd3) - add s3Res error listener; move https require to module top (
b5c2794) - add logging and timeout to /api/files/:key proxy handler (
42b3030) - hide Kiosk Mode dashboard button when kiosk module is disabled (
3a0d30b) - add Monitor icon for kiosk module in admin Feature Modules section (
d15deb3) - modules: fix messaging toggle persistence and kiosk module gating (
363a3a6) - hide Global Calendar sidebar item when productions module is disabled (
745bc5e) - correct stale path comment in featureModules.test.js (
4f40d31) - register externalProductions in productions module gate (
489310f) - rbac: gate create/edit controls behind canEdit() in 4 frontend pages (H-10/H-11/M-10/M-11) (
c61a335) - comms: fix isManager to include global_admin and gate room creation (H-12/M-12) (
66d3266) - demo: exempt POST /auth/logout from demoReadOnly block (L-13) (
1dff17f) - rbac: restrict productions PUT and items DELETE to manager+ (M-2/M-3) (
1d54dd5) - auth: add rate limiters for forgot-password, signup, and mfa/verify (H-3/H-4) (
0afaae0) - ai: add requireAdmin to usage endpoint and requireStaff to capability routes (H-7/H-8) (
1d0cf51) - spaces: add requireStaff + ownership check to booking routes (H-5/H-6) (
15c0dcd) - backup: restrict GET backup download to global_admin (M-1) (
6f99352) - storage: use extension-to-MIME map to prevent cross-type spoofing and add octet-stream support (
deb59a0) - storage: remove SVG upload and add MIME type validation (H-2/M-5) (
1508abb) - guest: remove X-Tenant-Slug header fallback — resolve tenant from subdomain only (
79dd90c) - tenant: update stale slug resolution comments after X-Tenant-Slug removal (
8beb8dd) - security: strip client-supplied X-Tenant-Slug header to prevent tenant spoofing (H-1/M-8) (
3bcfdab) - brighella-rename: fix i18n key call sites, User-Agent, package description (post-review) (
95cb7ec) - auth: include tenant.settings in all auth responses (
21b94f2) - spaces: fix SearchInput onChange to receive string value not event (
39d39a2) - spaces: use canEdit() permission gate for book-for-dates button (
7b52324) - global-calendar: fix hover guard logic in YearGridView and ListView (
52b0e56) - events: prevent initialDates from overriding existing event dates in EventFormModal (
6629ac3) - global-calendar: fix BookingModeOverlay displayRange, hover preview logic, and canEdit dedup (
81a7e79) - global-calendar: fix BookingModeOverlay ARIA live region and emoji accessibility (
ed5a29e) - demo-role-switcher: apply post-implementation review fixes (
9bc74d2) - demo: limit settings exposure and use SESSION_TTL_DAYS in demo-login (
113c325) - demo: limit settings exposure and set 1-day TTL in demo-start (
7d473a7) - rbac: align canUserSeeItem with itemVisibilityFilter — add canManage bypass for managers (
2e1842f) - rbac: add requireStaff gate to announcements PUT/DELETE; fix canModerate SQL condition (
ee02c35) - rbac: restrict GET /financial/utilization-stats to local_admin+ (
7debb5d) - rbac: restrict GET /audit/feed to local_admin+ (
4d0aeed) - rbac: restrict GET /billing/status to local_admin+ (
db4cc98) - demo: strictness fix and null-settings test for demoReadOnly (
ae71034) - global-calendar: wire booking-mode highlight in WeekView and ListView (
f076e61) - global-calendar: fix empty calendar, populate FilterBar dropdowns, staged styling, phase labels, error UI (
8cf68f7) - ui: replace font:inherit with fontFamily:inherit in MultiSelect dropdown panel (
e9a8ed1) - global-calendar: fix SearchInput onChange signature; define gc-page--with-drawer CSS (
49ce2eb) - global-calendar: portal BookingModeOverlay to document.body to escape animation stacking context (
95dd05b) - global-calendar: portal DayDetailDrawer to document.body to escape animation stacking context (
8c55e93) - ui: remove width:100% from MultiSelect root so it sizes naturally in flex rows (
8039299) - global-calendar: collapse filter dropdowns into single horizontal row (
25c67fb) - frontend: fix CalendarSubscribeModal error handling, copy fallback, revoke i18n key (
ca82de5) - api: validate public_only boolean and venue-token id at boundaries (
558c8fb) - ical: exclude soft-deleted events from location-filter in venue feed (
8b54bde) - global-calendar: restyle DayDetailDrawer and BookingModeOverlay (
a385492) - global-calendar: restyle all 5 view components (MonthView, YearTable, YearGrid, WeekView, ListView) (
3e71227) - global-calendar: FilterBar uses .filter-bar + MoreFiltersTray uses gc-more-filters-tray (
3d557cc) - ical: fold long lines in production calendar download per RFC 5545 (
cafd0e5) - global-calendar: restyle header/nav components (Header→PageHeader, ViewSwitcher→Btn, TimeJump→gc-time-jump) (
2f2889d) - global-calendar: replace Tailwind page shell with StageWise primitives (
46c780b) - ical: fold lines at 75 chars in buildIcal per RFC 5545 (Outlook compat) (
472dc6f) - ui: restyle MultiSelect to use StageWise tokens (was Tailwind, inert) (
1715281) - plan: replace Tailwind classes with CSS custom properties in Tasks 9+10 (
e51f4ea) - global-calendar: replace hardcoded strings in Drawer and BookingMode overlay (
462f331) - global-calendar: wire useLocations for venue filter data (
77ac5e2) - global-calendar: remove unused useLanguage import from YearGridView (
97f5e7a) - global-calendar: YearTableView memoize range, guard kind.replace, i18n headers (
ff43764) - global-calendar: MonthView useMemo, accessible aria-label, i18n DOW labels (
ad88f32) - global-calendar: default props, aria-expanded, de/no/sv translations (
3aed8f2) - global-calendar: use i18n keys for event type and status filter options (
ddfabff) - global-calendar: a11y + key stability fixes in header components (
420f4f6) - ui: improve MultiSelect accessibility, i18n, keyboard nav, selectAll filter (
ba98f3a) - i18n: rename gcNoData→globalCalendarNoData, filterProduction→filterProductions (
fd4774e) - routing: correct dashboard path from /dashboard to / to eliminate post-login 404 (
15a0f47) - comms: eliminate post flash by deferring fetch until channel is known (
6a86c95) - comms: prevent post flash on initial channel selection (
cbe5354) - domain: update stagewise.app fallbacks to stagewise.eu (
4506f38) - storage: fix condition photo uploads and public-asset regex (
070738a) - items: align label badge in fixed column independent of item name length (
ad28e80) - kiosk: gate PIN input inside canManage guard (
a2fc7f3) - print-center: fix afterprint ordering, QR race condition, memoize params (
e54667a) - print-center: fix selectAllVisible interpolation, refetch after label mark, align fallback (
fb895e8) - items: add error handling to label toggle; verify i18n keys (
af3089f) - items: use CSS variables in label toggle (no hardcoded colors) (
9dbbe62) - ai: remove invalid plan column ref in migration, fix plan resolution in ai service (
38e4266) - tests: update Login tests to expect preferred_landing redirect path (
8886767) - avatar: resolve profile picture not displaying in production (
1cfc9ec) - ai: correct tenant ID lookup in /me/ai routes; add i18n to AISettings (
beed80f) - ai: return real UTC midnight timestamp for resetsAt (
b52fb9e) - ai: skip credit check for uncapped plans; use safe interval SQL (
01eb692) - ai: add env guards and SMART_MODEL test to ai-client (
3895779) - ai: remove redundant runTenantMigrations call in migrate.js (
c032a5f) - kiosk: constrain cards to grid cell so overflow triggers auto-scroll (
d1c897e) - kiosk: keep size panel open on selection + cards fill viewport (
fb015ef) - dev: persist uploads volume across container restarts (
df32a19) - dev: persist uploads volume across container restarts (
1feddfc) - uploads: normalize legacy absolute file URLs across all upload routes (
551d58c) - avatar: make avatar files public + normalize legacy absolute URLs (
2d4b76e) - kiosk: reset expanded state on preset switch, hoist SIZE_STEPS, clarify RenderCard fallback (
6c2f3f9) - avatar: use relative URLs and proxy Spaces files to fix broken profile pics (
ad6270d) - kiosk: add pointercancel listener and clean up test imports in KioskCardWrapper (
b559cfe) - items: i18n violations in ItemCombobox — avail, allCategories (
d636deb) - i18n: move showingNofM to correct alphabetical position (
3157df6) - i18n: correct Danish noItemsFound translation (
31901fa) - qa: global-scope qa_mode toggle + global-admin bypass (
1fbee49) - qa: surface toggle errors inline + force backend rebuild (
ddd7317) - events: normalize useProductions response to array (
be4030d) - events: code quality fixes from review (
a6ff17b) - qa: make entire QA mode toggle area one clickable button (
f946b24) - events: hover-opacity actions, delete animation, i18n day key (
cd6ee5b) - tests: update stale staff_count mock fixture to staff_names (
4fa8cae) - qa: register /api/qa and /api/version in server.js (THE ACTUAL FIX) (
6bd643b) - deploy: truthful version banner + restructured COPY (
d7a280b) - deploy: hard cache-bust — bumped base image + RUN marker (
99898e8) - deploy: cache-bust Dockerfile + add /api/version fingerprint (
a460f64) - qa: banner-style error UI, helpful 404 message, fixed layout (
e6a9ed4) - qa: polish QA Reports admin page UI (
1b0998d) - qa: split migration by schema and use tenant query for users (
df6eb6f) - qa: split migration by schema and use tenant query for users (
10a07d2) - qa: add QA Reports nav item to SuperAdminLayout sidebar (
d41d417) - qa: use site_id (singular int) to match backend schema (
1ac482e) - qa: handle wildcard route and escape regex chars in matchRouteName (
6edcbcb) - qa: use Buffer.from for exact base64 size (
a24d33b) - migrations: add migration 061 for sent_to_email column on invite_codes (
7c0afdf) - equipment: restore Add Equipment toggle, fix case-sensitive search (
006802d) - profile: gate completion modal behind onboarding, persist skip, add department to profile (
94fcb95) - migrations: catch-up DDL for skipped migrations 039-044 (
6a8d0be) - rehearsal: custom type option now shows text input when selected (
b6e3039) - migrations: move season planning indexes to tenant schema (
83d0bca) - migrations: move performance indexes to tenant schema (
824466f) - migrations: add missing schema_name to public migration version inserts (
fcb6d58) - migrations: detect and fill version gaps in public schema migrations (
022d328) - invite: show actual server error instead of generic 'Save failed' (
968729a) - comms: show planned production channels, protect General from deletion (
f42ced7) - comms: close post menu on click outside (
8fb7f4b) - audit fixes — i18n keys for de/no/sv, BalancePanel z-index, semantic z-index, aria-label i18n (
13b6d76) - rehearsal: add responsive 2-col layout and phase count to overview cards (
efe3081) - rehearsal: audit fixes — duplicate entries, planning_start form, grid phase dividers (
6f1ffc3) - tests: add rehearsal hooks to smoke test mock (
60dd58e) - comms: use i18n for relative timestamps instead of hardcoded Danish (
87649ba) - comms: back button returns to chat tab, not feed (
d8fa756) - comms: fix column reference in chat messages query (first_name → username) (
a71283d) - comms: show both fetch and send errors in chat room (
eea8b7d) - comms: restyle chat room, input, and messages from Tailwind to inline styles (
a2bdd5e) - comms: show error message when chat room creation fails (
f8c0b5a) - comms: join users table in announcements query to show author name (
75064ca) - comms: drop unique index blocking custom group creation (
1badac8) - comms: show error message when group creation fails instead of silently ignoring (
d504cac) - comms: improve groups panel readability — larger fonts, accent colors, better contrast (
48ccd12) - comms: populate filename/original_name columns when uploading documents (
c91220b) - comms: add toast on copy, remove onboarding card from contacts (
fc3f71a) - migrations: fix all comms migrations that failed in production (
6c51ec2) - comms: create all missing comms tables (migration 048 had rolled back) (
3d7b07d) - comms: improve contacts readability with separate email/phone lines and copy buttons (
b3ead30) - comms: restyle DocumentUpload with inline styles matching dark theme (
c8330d9) - comms: auto-create channels table if missing, expose error messages for debugging (
8b0900b) - comms: mount comms routes in server.js (production entry point) (
a8aa88f) - storage: add missing @aws-sdk/s3-request-presigner dependency (
ee84818) - comms: resolve 6 bugs in communications section (
58b0efb) - tests: mock plan-limits middleware in locations and qr tests (
e9c6896) - i18n: translate all hardcoded strings in BillingOverview and MetricsDashboard (
0e9561a) - i18n: translate all hardcoded strings in tenant detail and admin components (
0915ae7) - i18n: translate all hardcoded strings in UsersTab (
efbbbee) - billing: switch all platform admin metrics from USD/EUR to DKK (
4ca2cd6) - sidebar: persist nav group open/close state across route changes (
e4de4f6) - resolve remaining audit findings — i18n, F28 hours display (
259a5a2) - comms: resolve 18 audit findings — props, hooks, UX, i18n (
cf9372c) - billing: update PLAN_PRICES to match new pricing tiers (
6200e73) - i18n: localize landing page prices per language/currency (
df66b8a) - comms: align feature flag from internal_messaging to messaging (
681e29c) - i18n: update landing page prices to DKK in sv, no, de locales (
ca5b666) - migrations: add missing column ALTERs to migration 050 (
8aa8a72) - billing: plan changes via tenant detail page now persist (
68edac0) - billing: plan selection and sponsor display in SuperAdmin (
1b1674e) - security,perf: resolve Tier 2 findings — XSS, validation, query perf, caching (
fa6c322) - security: resolve 8 critical/high findings from comprehensive code review (
5badd3c) - migrations: rename migration files so the runner discovers them (
af3891c) - modules: eliminate sidebar flicker and add Comms icon (
9934a97) - comms: resolve audit findings — hooks, security, i18n, input validation (
44dcd02) - modules: stop billing status from overwriting admin module config (
32d2a9d) - comms: restore original chat.js, rename comms chat to comms-chat.js (
2076595) - enforce plan-tier module restrictions server-side (
c9d411c) - show reports security hardening, PDF XSS fix, fmtNum consolidation (
11a037e) - add barcode tests, consolidate fmtDate, fix 62 pre-existing test failures (
4cf79c1) - update metrics dashboard to EUR pricing with 4-tier model (
8f509d7) - free plan limited to 1 user (
538aea2) - plan-limits audit — fail-open on DB errors, remove stale starter plan (
532a95d) - add Stripe payment processing fees to projections calculator (
7dace88) - audit fixes — race condition, error logging, input validation (
7f68221) - InviteCodesAdmin JSX syntax — send form inside card wrapper (
73983ef) - center-align sidebar logo with nav icons when collapsed (
908aa54) - CI passes despite Jest --forceExit open handle warning (
89f353c) - reduce sidebar divider gap — less prominent separator (
3a886fd) - marketplace shows connection guidance — explains how to see listings (
325d904) - UI/UX quick wins — focus trap, unsaved warnings, Lucide icons, print styles (
83898b0) - remaining i18n — loading states, error messages, GuestView empty state (
271b592) - replace hardcoded error strings in admin pages with i18n keys (
7307388) - QA audit — crash fix, broken Unicode, i18n strings, QR RBAC (
e1352c5) - item buttons broken emojis, inconsistent sizing, sticker print layout (
c00295e) - useUsers hook crashes rehearsal plan — API returns {data:[]} not [] (
e60ffb7) - rehearsal plan route ordering, field mismatches, and grid save logic (
77d2b07) - file auth now verifies refresh token via DB instead of JWT decode (
faa24a3) - marketplace hardening, rehearsal audit fixes, 112 new tests (
47c698d) - marketplace migration uses public schema_versions format (
0fd48e5) - revert DB SSL to accept self-signed certs by default (
3929e24) - use ref for serverDisplay in kiosk PIN handlers to avoid stale closure (
02e74bf) - kiosk PIN check used stale closure — buttons bypassed PIN guard (
507404a) - comprehensive security, i18n, and quality audit fixes (
be37523) - document upload audit — webp support, ILIKE search, delete order (
bad01c4) - free text type input in bulk add and side panel rehearsal forms (
273fdc9) - replace rehearsal type dropdown with free text input + suggestions (
94a040d) - register kiosk-displays and rehearsal routes in server.js (
e869748) - bulk add modal missing input styling, fields, and i18n keys (
da278ff) - kiosk logo transparent bg + larger size, admin-only dept card (
67cc6d1) - kiosk logo uses theme background color and larger size (
3c7fdb3) - kiosk logo adapts to any shape with spacing from clock (
8987444) - kiosk logo white circular background for dark theme contrast (
c7a0876) - use named import for useSettingsStore in kiosk display (
af03cbd) - improve kiosk logo visibility on dark background (
2e89422) - responsive kiosk header title for long show names (
020c949) - make rehearsal form inputs visible on dark theme (
81eada0) - use correct 'lang' property in all rehearsal plan components (
6bb8269) - codebase audit — i18n, a11y, DB indexes, security, useFormState (
c31b599) - increase kiosk headline to 6.6rem (300% of 2.2rem) (
4c2c693) - increase kiosk production headline to 2.2rem (200% larger) (
e9108af) - extract productions array from paginated response in kiosk (
63bf096) - rewrite KioskDisplay with defensive data handling throughout (
7eb2e3c) - remove static landing page redirect — use React SPA for all routes (
2906c3d) - add 'unsafe-inline' to nginx CSP style-src — fixes unstyled pages (
4c7eeb7) - add Array.isArray guard on visibleCards useMemo (P.filter crash) (
32c71ce) - guard against non-array cards in kiosk presets (P.filter crash) (
9793b2d) - use correct 'lang' property from useLanguage (was 'language') (
c8ca6c8) - kiosk display audit — 15 issues resolved (
4d0dc64) - add unsafe-inline to CSP style-src — fixes unstyled landing page (
99d5fbf) - QA items F31/F32/F35 — i18n wrapping, rememberMe removal, audit log names (
1a0b03c) - replace axios with native Fetch API for supply-chain security (
54c5421) - full-codebase audit — 23 bug fixes, 36 i18n keys, variable shadowing cleanup (
cbf3302) - audit P6+P7 — +210 tests, coverage improvements, performance & quality fixes (
a559281) - audit P5+P7 — new tests, shared year validation, audit logging, regex fix (
65503b3) - audit P1-P4 — security hardening, infra fixes, query optimization, bug fixes (
cc31c1e) - support comma-separated CORS_ORIGIN for multiple allowed origins (
adeabf5) - page refresh losing auth — race condition between fetchMe and AppLayout API calls (
9640d38) - full project audit — mount orphaned routes, fix N+1 queries, i18n, security, refactor (
0163348) - center-align logo with menu icons in collapsed sidebar (
3a5aa8c) - rehearsal plan crash (missing isStaff) + rental popup positioning (
9069774) - prevent checkbox overlapping department dot and title in grid cards (
55eecc5) - item photo auth bypass in app.js + show upload errors in form modal (
52b4bc4) - audit Simple Mode — use i18n for all labels, replace buttons with Tasks (
3f05207) - center collapse button, taller mobile nav, Simple Mode on dashboard (
75f87f7) - collapsed sidebar alignment, mobile bottom padding, hide demo btn (
d2691d4) - center-align expand button and site filter in collapsed sidebar (
9eb16b0) - increase mobile bottom padding to fully clear bottom nav bar (
63575fd) - move theme/language toggles inside login card for mobile (
62031e3) - "Try Again" on error screen causing blank blue screen (
e758c36) - remove picture frame icon button from items grid/list selector (
8457e73) - ensure all overviews and stats auto-refresh on navigation and tab focus (
773895b) - mobile scroll cutoff and iOS auto-zoom on input focus (
da77cf6) - demo login redirecting to landing page instead of dashboard (
394bef8) - prevent spontaneous logout from expired in-memory access token (
010fa23) - comprehensive QA audit — 25 bug fixes across 15 feature areas (
7f51b8d) - add missing i18n keys for batch scan section (
f0ab389) - phase colors, auto-status progression, DA phase names, sticker (
db5e536) - add missing QuickEditCard component for Quick Scan mode (
e603518) - UX improvements — toast types, skeleton loading, z-index scale (
ab8d605) - sticker redesign, select-all spacing, scan assign modal (
3fe2b21) - open Sticker page in same tab to preserve auth session (
ed9c91d) - give Mark Defective and Retire buttons visible borders (
7ad1382) - widen language dropdown on landing page for 3-letter codes (
54b0da8) - add language dropdown to Login and Landing pages (
4fe6985) - show short language codes in dropdown (DK, EN, SWE, NWE, DE) (
91200fc) - add missing Description field to New Space form (
2d0d699) - codebase cleanup — i18n, dead code, backup, rate limiting, ratings (
af0d3a0) - make sidebar collapse icon 50% larger (14px → 21px) (
40f4340) - sidebar footer — stack user name above utility buttons in two rows (
b567917) - comprehensive mobile audit — touch targets, layout, feedback (
569320c) - CSS variable aliases, memory leak, timezone shift, api error handling (
755f972) - 7 more bugs — null guards, conflict checks, validation, localStorage (
197a13f) - add 'retired' to Zod validation schema (was only in routes) (
6b7656f) - retire items cache invalidation + block retired/sold from allocation (
7589c2e) - 7 bugs + align MyHours dates grid (
7d30cf1) - show report routing, duration calc, dashboard label, spacing, i18n, auth debug logging (
1b03cf2) - duration calc for dot-separated times + error handling in report form (
51c124b) - add 35 missing i18n keys for Show Reports feature (EN + DA) (
490f791) - add 168 missing i18n keys + translate Utilization page (
ba48c11) - standardize section spacing across all pages (
92be3a1) - move filter-bar styles to global ui.css for consistent spacing (
ed5e6ea) - add ARIA to Items status tabs + DashSection helper (
4f2868c) - repair 6 failing tests + add Loans search + clickable contacts (
eeafab9) - repair 6 failing frontend tests (
33365ed) - position toasts to the left of floating buttons (
8f685a9) - render toasts via portal at bottom-right next to floating buttons (
432a66b) - site workload uses hours-based calculation (
f027751) - align holiday add button flush with input fields (
2024e7c) - add all missing i18n keys for season settings modal (
0701cc1) - collapse button smaller + staff header overflow hidden (
6c0a29c) - utilization % now uses Danish net available weeks standard (
a6e6681) - annotation menu now stays open + move collapse button to header (
02df5e2) - cell click annotation menu not appearing — race with global mouseUp (
42785da) - cell click not showing annotation menu + bigger gear icon (
f2d9151) - audit fixes for season module + bulk endpoint tests (
9de4c35) - remove holiday highlighting from season overview (
36e513f) - align site workload section with main grid scroll (
ee98218) - season grid rows extend full width + departments start collapsed (
a0403a7) - match bundles page layout to Items page design (
d012593) - send selected items when creating new bundle from bulk action (
34881ef) - default items page to list view instead of grid (
516b4d7) - responsive A4 preview with proper sticker/QR layout (
5f7e94a) - use same-tab navigation for bulk sticker page (
368e4d5) - prevent season grid month headers from shrinking (
03f42a9) - align season grid month headers with week columns (
588b35f) - improve Gantt chart accessibility for screen readers and keyboard (
f3ab1d4) - render annotation menu via portal to prevent overflow clipping (
58ef77f) - add trust proxy and widen refresh cookie path to fix session loss on page refresh (
c9e9315) - add HOST_DOMAIN to backend container env to fix session loss on page refresh (
e589abb) - broaden refresh cookie path and add auth refresh diagnostics (
e4c640e) - deduplicate fetchMe to prevent StrictMode refresh token race (
8c5cabe) - correct budget line difference calculation for API numeric strings (
d85d730) - convert production env var guards from fatal exit to warnings (
7ed6194) - support comma decimal separator in budget realized amount input (
d4ff4df) - use Blob URL for PDF export to preserve styles in Safari/Chrome (
c578e7a) - default to accepting self-signed SSL certs for managed databases (
fb68c1f) - rewrite budget PDF export with inline styles for reliable print rendering (
4a779fc) - bump production-location migration to 018 so it runs after 017 (
05be3d1) - add revoked column to refresh_tokens to prevent startup crash (
158d607) - rename migration files so runner discovers them on deploy (
e3d04ca) - skip tenant migrations for schemas without schema_versions table (
e4f3292) - handle '_default' slug in slugToSchema to unbreak local dev queries (
0a15e06) - add missing i18n keys for error states (failedToLoadData, retry) (
8340b49) - location hierarchy, input validation, and security hardening (
69146e8) - run tenant migrations in single-schema mode so calendar/schedule tables are created (
7b232a5) - 4 critical bugs in season planning module (
b85e7a0) - season overview resilience, user site assignment, remove hour edit window (
fef4c21) - collapse all location tree nodes by default on page load (
625417c) - add zebra striping to event table rows for better visibility (
2013e06) - add missing maintenance dashboard i18n keys (en + da) (
0d745c4) - comprehensive audit — i18n, a11y, error handling, security, dead code (
d2103c0) - event form location dropdown now shows only sites, not all locations (
b9cf94f) - add i18n translations for site filter dropdown (
c06d9d0) - update stale tests to match current implementation (
4e8bbab) - redesign Event Detail Overview to proper 2-column grid layout (
9928823) - back button navigation and redesign EventDetail with responsive card grid (
011a34f) - resolve stale UI on event mutations and add events to calendar view (
88cbfbf) - run tenant migrations on ALL tenants at startup, handle migration failures gracefully (
671ddac) - move /conflicts/check route before /:id and clean up events route (
87c1a6a) - remove dark overlay background from all modals and overlays (
31cef6e) - wrap remaining bare Unicode escapes in JSX expressions (
aa63581) - render Unicode arrows correctly in Calendar and ProductionDetail (
34b13b4) - exclude demo sessions from admin summary stats (
39195f0) - XLSX import header detection matches first column only (
063e07c) - import ON CONFLICT errors for tags and item_tags (
ffb755a) - item photos, stickers, history crash, dashboard logo, network guide, translations (
7ba6a9b) - pull sheet alignment, missing translations, logo fallback, import errors (
9dda20d) - add missing BudgetOverview page to fix production build (
fc5397c) - remove non-existent updated_at column from seedGlobalAdmin query (
e251700) - UX dead-ends, broken navigation, and budget PDF redesign (
99f99ea) - match width of theme and language toggle buttons on landing page (
449872d) - i18n missing keys, button formatting, and platform admin login (
0c9133d) - feedback modal freezes mouse after backdrop click (
c9dea39) - feedback modal unclickable after backdrop click, form class names (
f3aede6) - mark-all-read button calls wrong API endpoint (
680bdb4) - AI assistant close button not working (
91411d3) - move demo countdown timer to bottom of sidebar, centered (
8392df9) - EndDemoButton not clickable, uneven FAB spacing (
c9512e6) - reduce lockout to 5min, fix feedback modal freeze on outside click (
59035e0) - hide AI chat bubble and panel on mobile (max-width: 768px) (
1acb47e) - logo links to dashboard from anywhere in the app (
cc3cf78) - rename chat to Assistant, update welcome text (
a8c0dcb) - space floating action buttons evenly — no more overlapping (
312418b) - add missing chat component + remove i18n duplicate keys (deploy fix) (
872d2d9) - add missing i18n keys (general, remaining) for EN and DA (
91a98f2) - admin tabs and financial tables — move inline <style> to CSS files (
bb28561) - department table grid layout — add min-width and gap to prevent column collapse (
dcf0e5d) - typography, layout consistency, and export formatting across all pages (
23f996d) - production detail phases use inline styles for reliable rendering (
76497a5) - budget routes — remove non-existent tenant_id column, auto-create tables (
886b8ce) - remove tenant_id check from budget creation — column doesn't exist (
198376f) - production cards use inline styles for reliable rendering (
c137117) - production card layout — better spacing, structure, and readability (
cf08d6f) - mobile menu sub-items left-aligned to match desktop sidebar (
12a130e) - UI/UX polish — mobile overflow, button styling, text alignment (
5f9da4a) - admin settings tabs overflow + missing deleteUser hook (
26cd986) - budget creation — validate production exists, handle duplicate constraint (
03a728e) - match theme and language toggle button sizes on landing page (
9841f97) - Stripe webhook race conditions + mobile menu focus trap (
348cb1b) - standardize error handling — asyncHandler on all routes, stop leaking err.message (
fbebe2f) - move crew action buttons below section title (
3632633) - redesign scan page for clarity (
59c77e8) - redesign production phase blocks for clarity (
05240b8) - restructure crew schedule cards for better readability (
cf67bf4) - UI audit — notifications, loans, financial, landing page (
5274c92) - replace social proof pills with clean dot-separated line (
f5fbac1) - rename screenshots to lowercase for Linux case-sensitive filesystem (
d481db4) - resolve demo session duplicate username error in single-schema mode (
081cbec) - prevent DigitalOcean platform hostname from leaking as tenant slug (
f2f0e0b) - run tenant SQL statements individually in single-schema mode (
ff1fc10) - add single-schema mode for managed databases (
7a684b7) - strip schema_versions from tenant SQL when using public schema fallback (
3cd7620) - fall back to public schema when CREATE SCHEMA is not permitted (
a1e2874) - replace citext with TEXT for managed database compatibility (
217fb2d) - handle citext extension permission error on managed databases (
da3c0d5) - strip sslmode from DATABASE_URL to fix self-signed cert rejection (
45ad365) - remove Redis dependency, use PostgreSQL for all persistence (
491142c) - optimize dashboard queries, add i18n and accessibility (
f1118db) - make frontend nginx config work on DigitalOcean App Platform (
45769ec) - add SSL support for DigitalOcean managed database (
dfa693c)
Performance
- super-admin: collapse /stats N×4 → N×1, add /:slug/stats + 60s cache (
cdd109a) - productions: move bulk auto-progress from GET handler to 15-min cron (
e65774b) - build optimization — chunk splitting, lazy XLSX, remove unused deps (
0dcfe32)
Security
- add CSRF origin check middleware as defense-in-depth (
5f4cc88) - escape LIKE wildcards in all search inputs, harden bulk update (
141046a) - fix medium-severity issues from audit (
c012a62) - fix critical XSS, auth bypass, JWT algorithm, MIME validation (
656eefa)
Reverted
- roll back v24.1.0 due to prod migration failure (
a3f31b9)
Docs
- quality-sweep: Wave 1 verification report (
ab30bd6) - audits: Wave 0 synthesis and six-domain audit reports (
e240d91) - readme: rewrite for current Node/PG/DO stack — W1-H08 (
faf0cec) - tenant: flag settings.js as a
_defaultalias landmine (32cc3d1) - wave3: spec captured from 2026-04-17 brainstorm (
364c65c) - legal: add GDPR + App Store compliance drafts for pre-launch review (
79a98cf) - mobile: add design spec + PWA foundation plan + capability roadmap (
83d5e7b) - #17a: export audit — inventory of every PDF / XLSX / ZIP / CSV / ICS export (
4f45d21) - feature #14-29 brainstorm, implementation plan, and state-of-brighella (
36f9b4c) - claude: require plan approval before implementing (
c443027) - claude: add Subagent Patterns section from Phase 4 lessons (
acceb76) - app: remove stale 'condition photos' mention after C1 fix (
0860472) - review: add Phase 4 review and fixes plan (
e501fd6) - plan: annotate Task 4 as skipped — N+1 premise was incorrect (
029d3a4) - add Phase 1-6 implementation plans + AI prompting guide (
594d18f) - add 2026-04-14 code review fixes implementation plan (
57baff0) - migrations: document DDL+DML violations and version prefix collisions (
2c2ff99) - add superpowers audit reports and implementation plans (
a93d1ee) - add design spec for sidebar settings flash fix (
5c3f3c1) - add implementation plan for collapsible admin sidebar section (
dfb381c) - add spec for collapsible admin sidebar section (
536c856) - brighella-rename: add release notes (
d3db320) - brighella-rename: rebrand README, CLAUDE.md, security-assessment (
e660183) - brighella-rename: rebrand legal pages (ToS, Privacy, DPA) — emails/domains preserved (
1f59df8) - brighella-rename: add implementation plan (
7c81150) - add brainstorm artifacts — founding vision, calendar plan, venue calendar feeds spec (
7a0907b) - add booking mode type picker implementation plan (
3e08e63) - add booking mode type picker design spec (
d92f42a) - rbac: add RBAC gate fixes implementation plan (
15e97b1) - add demo role-switcher implementation plan (
7df2411) - add demo role-switcher design spec (
9906c76) - add kiosk PIN management implementation plan (
4b8aa14) - add kiosk PIN management design spec (
24ee039) - add bulk sticker printing + labeled status implementation plan (
8ad9628) - add bulk sticker printing + labeled status design spec (
07b9964) - crosscheck plans — mark completed tasks, fix migration number conflict (
f1fc9ec) - ai: add Phase 1 foundation implementation plan (
bc7859b) - ai: add StageWise AI integration design spec (
83f3d0b) - add kiosk per-card text size implementation plan (
c132c2b) - add kiosk per-card text size spec (
56fd1a1) - add equipment item combobox implementation plan (
c6054bb) - add equipment item combobox design spec (
31c955c) - events overview table implementation plan (
a3776eb) - events overview table design spec (
b0214e6) - qa: manual test checklist for bug-hunt companion (
9743476) - plans: add QA bug-hunt companion implementation plan (
6c08088) - specs: add QA bug-hunt companion design spec (
d02721b) - rehearsal: add implementation plan for meetings, scrollable calendar, overview cards (
e228ce1) - rehearsal: add design spec for meetings, scrollable calendar, overview cards (
f7d7a9d)
Tests
- flake: §9 freeze time in date-sensitive tests — WB-59 (
9204b6e) - data-export: §7.4 assert ZIP contents, column sets, no secrets (
6e59ecc) - storage: mock logger to prevent winston File transport init under mocked fs (
8385ebe) - manuscripts: push coverage to 80%+ — W1c-12 (
9febcf8) - rehearsal-entries: push coverage to 80%+ — W1c-12 (
89d66f9) - kiosk-displays: push coverage to 80%+ — W1c-12 (
784e171) - a11y: add useConfirm to ui mocks in ItemFormModal, ProductionFormModal, Comms tests (
da92b8f) - mfa: full TOTP + recovery-code coverage — W1-H10 (
9eb33a0) - webhooks: cover sendWebhook + SSRF guard integration — W1-H09 (
871d105) - auth: cover fetchMe cookie-refresh path + add IdCard route (
7bdcf7d) - integration: insurance tenant isolation (closes B9 spec) (
09936fe) - integration/tier2-3: tenant isolation sweep for support, notifications, documents, tenants/me/ai (
80de0d6) - integration/tier1: tenant isolation sweep for items, productions, allocations, crew, loans (
f52ad0a) - support: real 401 rejections + both ownership branches (
7b845df) - cover guest-join and support routes (
1692128) - isolation: harden cleanup + override MULTI_TENANT in integration (
3cc4d62) - isolation: throw on missing JWT_SECRET, scope npm test to unit (
d5764d1) - isolation: real-DB harness + cross-tenant checkouts test (
8c6a562) - checkouts: restore transaction mock for POST /:id/checkin test (
a5adef0) - email: add queryPublic to email.test.js mock for mailer delegation (
3e92fed) - budgets: remove stale ensureBudgetTables comments (
df2b281) - csrf-origin: cover Origin: null and Referer fallback attack vectors (
9e2b1ce) - add featureModules tests for externalProductions gate (
14c0b1e) - rbac: add gate regression tests — endpoints ungated (red) (
98f3329) - frontend: add hook/store/util coverage — 524 → 786 tests (
141b772) - frontend: add smoke/unit tests for SuperAdmin, Landing, PrivacyPolicy, TermsOfService (
25c3b34) - kiosk: add failing PIN management tests (TDD) (
76a0988) - fix pre-existing ProductionOverview + CommsGuestJoin failures (
758f22e) - rehearsal: add tests for entry categories utility (
c3dc671) - rehearsal: add planning_start backend tests (
bf9c48f) - add frontend tests for ItemDetail, ProductionDetail, Utilization, PullSheet (
c3da20b) - add frontend tests for Admin, Calendar, EventDetail, Financial, SeasonOverview (
6a066f0) - add page tests for Loans, Todos, Documents, MyHours (
d195b14) - comprehensive coverage expansion — backend 78% → 90%, frontend 1% → 11% (
514be13) - add full-stack test suite — 573 tests across 69 files (
17070d1)
Chore
- migrations: DDL/DML split linter + CI gate — WB-13 (
6d0943b) - errors: annotate remaining silent catches — W1b-10 final pass (
953b118) - errors: annotate silent catches in frontend — W1b-10 (
6c7360d) - errors: annotate silent catches in develop seed — W1b-10 (
9180bbd) - tests: remove orphaned backend/tests/ directory and expand plan-limits coverage — W1c-13 (
966f08e) - errors: annotate silent catches in infra + demo-sessions — W1b-10 (
db759cd) - errors: annotate silent catches in auth routes — W1b-10 (
b0cd6f0) - sentry: configure source-map upload via vite plugin — W1c-10 (
02b10f1) - nginx: add body limit + rate limit + security headers — W1c-08 (
1870233) - docker: switch npm install to npm ci — W1c-07 (
8717901) - security: rotate .env.test secrets and gitignore — W1-H02 (
f07e0a2) - authz: TODO comment on crew availability mutation (F5 LOW) (
c69b73d) - gitignore: widen .env coverage to .env.* (
8033615) - brighella-rename: rename npm packages to brighella-* (
7100036) - ignore .worktrees/ directory (
84f47ef) - seed: upgrade develop demo tenant to enterprise plan (
65ac165) - qa: regenerate routeNames.js with qa-reports entry (
8409f47) - qa: remove dead test file outside jest roots (
609ea9e) - consolidate hardcoded z-index values to CSS variables (
f8d9911) - review: Tier 3 — dead code removal, i18n, frontend tests (
1fda29c) - i18n fixes, error handling, DB indexes, page tests (
435def6) - add docs, config, scripts, Pi setup, code architecture map (
c595272) - landing page copy tweak + Dockerfile.dev npm ci (
a673449) - add build target + postcss/autoprefixer dev deps (
1c2e485) - move remove button inline with hours input, make compact (
deb5e80) - restyle toast notifications to match floating action buttons (
79aeda9) - make all checkboxes 40% larger globally (18px) (
f9363ac) - remove unused Redis from Docker Compose (
9563ce7)
Misc
- nav: add skip-to-content link in layouts — W1b-07 (
5d2f914) - modal: restore focus to trigger on close — W1b-06 (
4f3760d) - interactions: add keyboard handlers to div onClick — W1b-05 (
6eb64e5) - extract hardcoded aria-label/title/button text — W1b-09 (
2898d63) - tables: add scope="col" to 200+ <th> elements — W1b-04 (
61d629d) - ui: migrate window.confirm/alert to useConfirm — W1b-03 (
2f4a03b) - translate identical keys in de/no/sv — W1b-08 (
d308d7c) - i18n: wire setDateLocale + setNumberLocale — W1b-02 (
19db0e4) - html: reactive document.documentElement.lang — W1b-01 (
e1e1849) - fix(tests) + feat(digest): fix checkouts-damage + wire digest email via Resend (
0938d69) - brighella-rename: rebrand 5 locales (en/da/de/no/sv) to Brighella (
a4e5a24) - add rehearsal template keys and external productions keys (all 5 locales) (
fe5c32e) - add kioskHeadingSize and kioskBodySize keys (all 5 locales) (
877b141) - add task user assignment keys (all 5 locales) (
e0dc0d8) - qa: loud logging around /api/qa registration (
ace42db) - v24.1.1 — fix v24.1.0 prod migration failure (
4c66882) - v24.1.1 — fix v24.1.0 prod migration failure (
127fddc) - Revert "revert: roll back v24.1.0 due to prod migration failure" (
d5bbac3) - v24.1.0 — QA Bug-Hunt Companion (
ae57431) - onboarding: redirect to home after wizard completion (
312c30a) - signup: remind users to check spam folder for welcome email (
185a3db) - equipment: always-visible search bar with direct add to production (
5741927) - rehearsal: replace type text input with select dropdown + custom option (
fc843a9) - comms: show active channel name as headline next to Comms title (
9129f97) - add aria-labels to icon-only buttons across frontend (
6a15dcf) - add aria-live regions for search result counts (
00742ec) - filter-aware empty state messages across search pages (
5cc4d62) - migrations: split DDL/DML to fix production startup crash (
d1ef07e) - remove dead route imports from server.js (
159e90f) - add inline error boundary to RehearsalPlan to show exact crash (
316fad4) - test+fix: comprehensive audit — 251 new tests, coverage thresholds met (
13e934a) - shorten landing badge text (
79e1eaf) - expand landing badge to list all venue types (
5e9b703) - Seed default tenant row in tenants table on startup (
ebdb013) - Fix tenant middleware breaking login on DigitalOcean + add test suite (
b981460)