* feat(ui): hide paid features from community-tier dashboard
Community installs render only the features they can use. Tier-locked
sections, lock badges, upsell cards, and "Upgrade" buttons no longer
appear anywhere except the License page in Settings, which is the
single discoverable upgrade path.
Concretely:
- PaidGate and AdmiralGate now render null for non-qualifying tiers
instead of upsell cards.
- SectionGate (settings) hides tier-locked sections entirely.
- Settings sidebar and command palette filter out items the operator
cannot reach.
- Configuration Status widget on the dashboard drops the Automation
section for community and hides any locked rows in remaining
sections.
- Fleet > Status node cards drop locked summary rows.
- Stack action menu, sidebar bulk bar, file upload / download, scan
comparison, network topology toggle, node label picker all hide
for community instead of showing disabled affordances or "Upgrade"
literal text.
- Removes tierUpsell, TierLockChip, and useDismissalState (no longer
referenced).
Backend tier guards remain authoritative; this changes UI discovery
only.
* test(e2e): assert upload control is absent in community tier
The community-clean-ui change removes the "Upgrade to unlock upload"
pill from the file explorer. Update the matching e2e assertion to
verify the upload control is not rendered, instead of waiting for a
pill that no longer exists.
* feat(auto-update): add per-stack auto-update enable/disable toggle
Paid users (Skipper and Admiral) can now opt individual stacks out of
scheduled auto-updates from the stack context menu without disabling
the global feature.
- Add stack_auto_update_settings table (node_id, stack_name) with
default enabled=true; four typed DatabaseService accessors with
parameterized queries.
- Add GET /stacks/auto-update-settings, GET /stacks/:name/auto-update,
and PUT /stacks/:name/auto-update (requirePaid + requireAdmin).
PUT broadcasts state-invalidate with action auto-update-settings-changed
so all open tabs refresh immediately.
- Stack DELETE clears the auto-update setting row alongside stack_update_status.
- autoUpdateRouter /execute skips disabled stacks before any registry
call; skip is recorded in the results array. Manual Update actions
are not affected.
- Add Auto-update: Enabled/Disabled toggle in the stack inspect group
(paid tiers only, hidden for Community, consistent with Auto-Heal).
Toggle uses optimistic update with revert-on-error toast.
- AutoUpdateReadinessView shows an Auto: Off pill and disables the
Apply now button for stacks with auto-updates off. Detection still
runs so the readiness card remains visible.
- Add 21 backend Vitest tests covering DB round-trips, endpoint auth
and tier gates, execute skip for both wildcard and named targets.
Add 3 frontend hook tests for toggle visibility and callback behavior.
* docs(auto-update): document per-stack auto-update control
Add a Per-stack control section to the auto-update readiness page
explaining how to disable and re-enable auto-updates for individual
stacks, what disabling means (scheduled apply skipped; detection still
runs; manual update unaffected), and a troubleshooting entry for
scheduled runs not applying to a specific stack.
Group readiness cards by node so updates pending on every reachable node
are visible without having to switch the active node. Apply now targets
the owning node directly, and Recheck fans out to every reachable node
in parallel; per-node cooldowns are surfaced in the toast.
Adds POST /image-updates/fleet/refresh and invalidates the fleet
aggregation cache after auto-update execute so the next read reflects
the new state immediately. A small banner appears under the hero when
some online nodes did not respond within the request timeout.
When a registry pushes a new build of an image at the same tag (digest
changes, tag does not), the preview service set next_tag to the same
string as current_tag and the readiness view rendered '10.11 -> 10.11',
which reads as a UI bug.
Add an update_kind field to UpdatePreviewSummary that distinguishes:
- 'tag' - at least one image has a strictly newer tag
- 'digest' - the only updates available are same-tag rebuilds
- 'none' - nothing to apply
The frontend now branches on update_kind and renders 'Rebuild available'
next to the current tag for the digest case, leaving the version-arrow
diff for genuine tag bumps.
Three new buildSummary cases lock in the kind classification.
* feat(backend): add stack update-preview endpoint for readiness board
Adds GET /api/stacks/:stackName/update-preview that returns per-image
semver diff, bump classification, and a stack-level summary powering
the Auto-Update readiness board.
- New UpdatePreviewService parses compose images, inspects local
digests, fetches remote digests and tag lists, and finds the
highest compatible semver tag.
- Major bumps are flagged blocked until human review; unknown bumps
rank below real semver so they cannot mask a major.
- Rollback target is reconstructed through parseImageRef to preserve
registry ports and drop the Docker Hub library/ prefix.
- Registry helpers (httpGet, auth token, digest, tag list, ref parse)
are extracted into registry-api.ts and shared with ImageUpdateService.
- 28 Vitest cases cover parse, selection, bump math, digest rebuilds,
blocked policy, and rollback target construction.
* feat(schedules): next-24h timeline, merge auto-update crud, add readiness board
Replace the flat task table with a Timeline view as the default, showing the
next 24 hours of scheduled work across four lanes (Restart, Update, Scan,
Prune) with a live now rail and per-firing pills. The All tasks tab preserves
the existing CRUD surface.
Merge Auto-update Stack into Schedules as a first-class action and replace the
standalone Auto-Update Policies view with a per-stack Readiness board that
surfaces version diffs, risk tags, changelog previews, and rollback targets
sourced from the stack update-preview endpoint.