Licensed features can now be granted or revoked per user instead of
applying instance-wide. Resolution is layered: the instance license must
include the feature, then a per-user override, an admin-set instance
default and the built-in code default are consulted in that order.
Time tracking is the first per-user toggleable feature; admin_panel and
audit_logs stay instance-wide. New features opt in via the
perUserToggleable map in pkg/license.
- store per-user overrides in a json column on users, instance defaults
in the new pro_feature_instance_defaults table
- enforce the toggle in the v2 time-entries route gate and in the
TimeEntry permission chokepoint for non-route callers
- new admin v2 endpoints to manage instance defaults and per-user
overrides
- expose effective_pro_features on /api/v1/user; the frontend prefers it
over /info's instance-wide list once the user is loaded
- admin UI: per-user toggles on the user detail modal, instance defaults
on the admin overview
https://claude.ai/code/session_01AVt4FHWrUUhv5p6yn99pdp
On startup, if the license server was unreachable with no usable cached status, or the server rejected the key, we only logged a warning without clearing persisted license.state. On Redis/keyvalue deployments a previous run's Licensed=true could remain active even though pro features were advertised as unavailable. Route both paths through degradeToFree so the persisted state is cleared.
Implement the license validation system with:
- Server communication with retry logic and exponential backoff
- In-memory state management for feature flags and user limits
- Cached validation with 72h expiry stored in database
- Background goroutine with adaptive check intervals (24h/1h)
- Graceful degradation to community mode on failure
- Instance ID generation and persistence