KDS was seeded with the same theme_color as kitchen (#0d9488) — the two
Kitchen-category portal tiles were indistinguishable. Changed to #ea580c
(orange). See kitchen-port-log.md E17.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a third capability 'edit' (Edit Directors Forecast) for the reports
app to gate pickup/dry/wet override saves and snapshot creation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Used by the settings UI so operators can securely copy the shared session secret
into Hosted Tables without ever exposing it in logs or config files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Seeds restaurant_bookings as inactive (active=false) so it stays hidden until the
settings service configures the Hosted Tables URL. Adds PATCH /api/auth/internal/apps/:slug
so settings can update base_path and active without auth restarts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
history is a portal alias for /forecasting/history, not its own service.
Setting internal_host=NULL prevents spurious health-check failures and
deploy attempts against /opt/history on LXC 113.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a 'history' app slug that deep-links to the forecasting app's
History page, allowing it to appear as a standalone tile in the portal.
Admins grant it alongside the 'forecasting' app via the Roles UI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings service calls POST /api/auth/internal/cache-bust (Bearer SETTINGS_SECRET)
after saving workforce or smtp integrations, so location/credential changes take
effect immediately without waiting for the 5-minute TTL or restarting the container.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
If a bearer_token is stored in settings, getWorkforceToken() returns it
immediately without doing an OAuth password grant. Validation accepts
either bearer_token or email+password.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GET /api/auth/users?app=<slug> — non-admin user list for task allocation
(requester must have access to the app; returns active users with access,
minimal fields). Seed row for the maintenance app (LXC 121).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Splits the old 'reports' cap into reports + cash_summary,
'floats' into floats + safe_count, and adds a new 'history' cap.
Existing installs get the three new caps added to the Staff role
via an additive per-cap seed so admin-managed configs are unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Schema:
- app_capabilities: capabilities each app exposes (<app>:<slug>)
- role_capabilities / user_capabilities: grants via roles and direct
- Seed cashup caps (count, finalise, reports, floats, settings)
- Non-breaking migration: default Staff role gets all cashup caps
except settings (previously only is_admin reached settings)
Resolution:
- getUserCapabilities(): admins get all; others get union of
role + direct grants, as "<app>:<cap>" strings
- caps[] added to JWT payload (login + register)
- /verify returns live capabilities for the requested app (bare slugs)
Admin API:
- GET /admin/capabilities catalogue
- grant/revoke capability on roles and users
- roles/users GET responses now include their capabilities
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>