Commit Graph

204 Commits

Author SHA1 Message Date
Anso 7d78c9fe22 feat(auth): add TOTP two-factor authentication with backup codes (#615)
* feat(auth): add TOTP two-factor authentication with backup codes

Adds RFC 6238 time-based one-time password support to every tier,
integrated with the existing password and SSO login paths.

Backend:
- New MfaService wrapping otplib with a plus or minus 1 step tolerance,
  base32 secret generation, and hashed single-use backup codes (bcrypt).
- user_mfa and mfa_used_tokens tables in DatabaseService. The second
  table is a DB-backed replay blacklist, purged on a 60s interval.
- authMiddleware now recognizes an mfa_pending scope. A token carrying
  that scope is rejected on every route except the MFA challenge and
  logout, so no API surface is reachable before the second factor
  clears.
- /api/auth/login issues only a short-lived mfa_pending cookie when the
  user has MFA enrolled. /api/auth/login/mfa consumes that cookie,
  verifies the code (or backup code), and swaps in a real session.
- /api/auth/mfa/* routes for status, enrol/start, enrol/confirm,
  disable, backup-code regenerate, and SSO-bypass opt-in.
- Admin recovery path: POST /api/users/:id/mfa/reset clears the target's
  MFA state, bumps token_version, and writes an audit log entry.
- CLI emergency fallback: backend/src/cli/resetMfa.ts is wired via
  `npm run reset-mfa <username>` and also exported for tests.
- SSO flows (LDAP and OIDC) gate on user_mfa.sso_enforce_mfa before
  issuing a session; default behaviour keeps the SSO path frictionless.
- Per-user lockout after 5 consecutive failed codes (15 min).

Frontend:
- AppStatus gains an mfa-challenge branch driven by /api/auth/status.
- New MfaChallenge screen, MfaEnrollDialog (QR plus manual secret plus
  backup codes), MfaDisableDialog, MfaBackupCodesDialog.
- Account section shows a Two-factor authentication card with enrol,
  regenerate, disable, and the SSO-enforce toggle (shown only when SSO
  providers are configured).
- Users section gains a Reset 2FA action for admins.

Docs:
- New user guide at features/two-factor-authentication.mdx.
- New admin guide at operations/two-factor-admin.mdx.
- SSO page cross-links to the 2FA doc.

* fix(mfa): drop unused TEST_PASSWORD import and stale eslint disable

* fix(mfa): simplify e2e openAccountSettings helper to match working pattern

* fix(mfa): make e2e suite self-contained and always clean up

Test #2 called loginAs() before the MFA challenge step, which waited for
the dashboard indicator that never appears once the previous test enrolled
the user. That timeout skipped the rest of the serial block, including
the disable step, leaving MFA enabled and breaking every later spec.

Two fixes:

- Tests #2 and #3 now navigate directly to the login page instead of
  piggybacking on loginAs, which only handles the password-only path.
- A new afterAll hook unconditionally disables MFA via the API using two
  unused backup codes, so the DB is reset even if a test fails midway.

* fix(e2e): use backup code for mfa recovery to avoid totp replay race

The final recovery step in the backup-code replay test previously
generated a fresh TOTP to sign back in. When the timing landed inside
the same 30-second window that test #2 consumed, the server's replay
blacklist correctly rejected it, producing a ~50% flake rate. Backup
codes are single-use and sidestep the replay window, so the recovery
becomes deterministic.

* fix(e2e): drive mfa disable test through the challenge screen

Test #4 called loginAs after test #3 left MFA enabled, but loginAs
waits for the dashboard indicator and does not handle the challenge
screen, so it timed out. Drive the login manually, satisfy the
challenge with a backup code, and use a backup code for the disable
step too to avoid any TOTP replay-window race against earlier tests
in the serial block.
2026-04-15 18:45:51 -04:00
sencho-token-app[bot] 87263ff357 docs: refresh screenshots (#611)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-15 15:36:48 +00:00
sencho-token-app[bot] d9f50b3229 docs: refresh screenshots (#608)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-15 12:07:58 +00:00
Anso 3955267bbe feat(git-sources): create a stack from a Git repository (#606)
* refactor(git-sources): extract GitSourceFields from GitSourcePanel

Pure extraction of the repo/branch/path/auth/apply-mode form fields into a
reusable controlled component so the upcoming Create Stack from Git flow can
render the same form in the Create Stack dialog. No behavior change.

* feat(git-sources): create a stack from a Git repository

Add a From Git tab to the Create Stack dialog so users can name a new
stack, point it at a repo + branch + compose path, and have the compose
fetched, validated, written to disk, and linked in one shot. Optional
deploy-after-create runs the initial bring-up when requested.

Backend: new POST /api/stacks/from-git route gated by stack:create.
GitSourceService.createStackFromGit() fetches and validates before
touching disk, then creates the stack, writes the compose (and .env if
sync is enabled), and seeds the git source row with the fetched commit
so future pulls produce a clean diff. Runs under the per-stack lock so
a concurrent webhook cannot race the create. Deploy failure is
non-fatal and surfaced to the caller.

Frontend: the existing Create Stack dialog is now tabbed, with Empty
keeping the original single-field flow unchanged.

* test(git-sources): cover create-from-git endpoint and e2e flow

Service tests verify createStackFromGit seeds the last_applied columns
on success, writes the env file when sync is enabled, refuses an
invalid apply-matrix without fetching, rejects invalid compose
without leaving orphan state, and rolls back the on-disk stack dir
when a post-create step fails.

Route tests cover auth, missing stack_name, invalid stack name,
http:// rejection, oversized repo_url, and the 409 collision guard.

E2E adds a Create-stack-from-Git block covering tab visibility,
client-side HTTPS check, backend .git/config rejection, and a
happy-path fetch against a public demo repo (skipped on network
failure).

* docs(git-sources): document create-stack-from-git tab

Add a new section near the top describing the From Git tab in the
Create Stack dialog: what it does, the Deploy after create checkbox,
and the four failure modes (name collision, unreachable repo,
invalid compose, deploy-after-create failure).
2026-04-15 08:05:10 -04:00
sencho-token-app[bot] a4ec11173b docs: refresh screenshots (#605)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-15 02:35:08 +00:00
Anso 00901cf5bf fix(git-sources): harden validation, RBAC, concurrency, and deploy recovery (#603)
* fix(git-sources): harden validation, RBAC, concurrency, and deploy recovery

Tightens the surface area around the Git source feature:

- Enforce HTTPS-only repo URLs server-side (regex was permissive).
- Add stack:read permission check on git-source reads and filter the
  list endpoint by callable permission.
- Validate stack names before permission checks on mutation routes so
  scoped lookups never see unvalidated input.
- Cap repo_url / branch / compose_path / env_path / token lengths and
  require the stack directory to exist before upsert.
- Wrap pull() in the per-stack mutex to eliminate the pull/delete race
  that could orphan pending data.
- Block .git/ path components in compose_path / env_path so a
  misconfigured clone cannot leak repo metadata.
- Return {applied, deployed, deployError?} on deploy failure instead of
  throwing, and surface deployError as a warning toast so the user can
  retry deploy without re-pulling.
- Always clean the stack_git_sources row on stack delete even when the
  file deletion step fails.
- Add shadow-card-bevel to the pending alert and metadata card per the
  design system.
- Handle the new 403 response on the panel fetch gracefully.
- Add diagnostic logging gated on developer_mode (isDebugEnabled) across
  fetch / pull / apply / webhook paths with credential scrubbing.

* test(git-sources): expand coverage for hardening and route validation

- New route-level suite covers HTTPS enforcement, required fields,
  max-length caps on repo_url / branch / compose_path / env_path /
  token, the stack-existence 404 guard, and GET authz.
- Service tests cover the .git metadata guard on compose and env
  paths (including nested and substring-containing "git"), pull and
  apply rejections when no source is configured or pending is
  cleared, the sha-mismatch branch, and the deploy-failure return
  shape that now carries deployError.
- E2E adds three server-side contract assertions: PUT against a
  missing stack returns 404, http:// is rejected with 400, and
  .git/config is rejected as compose_path.

* docs(git-sources): document deploy-failure recovery path

Adds a Troubleshooting entry explaining that when apply succeeds but
the subsequent deploy fails, the compose content is already on disk
and the user can retry deploy from the stack editor without
re-pulling.

* docs(git-sources): add configuration, diff, pending, and webhook screenshots
2026-04-14 22:32:42 -04:00
sencho-token-app[bot] 789437cc46 docs: refresh screenshots (#602)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-15 01:15:38 +00:00
sencho-token-app[bot] d7ff706e50 docs: refresh screenshots (#599)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 22:23:02 +00:00
sencho-token-app[bot] aeb8adc5f5 docs: refresh screenshots (#596)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 20:44:55 +00:00
sencho-token-app[bot] f8a7abc07b docs: refresh screenshots (#593)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 18:39:47 +00:00
sencho-token-app[bot] 3530816353 docs: refresh screenshots (#590)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 17:54:52 +00:00
sencho-token-app[bot] 376dffbb53 docs: refresh screenshots (#585)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 15:06:53 +00:00
Anso 23fc702296 fix(network-topology): harden with edge-case fixes, logging, and test coverage (#583)
* fix(network-topology): harden with edge-case fixes, logging, and test coverage

Fixes stale data on node switch (topology now refreshes when active node changes),
adds manual refresh button to toolbar, and guards against containers with empty
Names arrays by falling back to a 12-char short ID. Adds operational and diagnostic
logging around topology fetches, and introduces 25 unit tests covering happy paths,
system network filtering, stack resolution, container deduplication, edge cases,
and error handling.

* docs: refresh screenshots
2026-04-14 10:59:11 -04:00
sencho-token-app[bot] 5bc709fc25 docs: refresh screenshots (#582)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 14:14:13 +00:00
Anso 718c1eb1ea fix(host-console): harden with security fixes, validation, and test coverage (#580)
Security:
- Enforce RBAC (system:console permission) on WebSocket upgrade
- Validate token_version for user sessions on WS connections
- Expand env var sanitization to cover additional secret patterns
  (PRIVATE, AUTH, PASSPHRASE, ENCRYPT, SIGNING) and connection
  strings (REDIS_URL, MONGO_URI, AMQP_URL, DSN)

Reliability:
- Add session tracking with max 5 concurrent console sessions
- Add WebSocket heartbeat (30s ping, 60s pong timeout) to detect
  and clean up dead connections and orphaned PTY processes
- Differentiate PTY spawn error messages (shell not found,
  permission denied, generic failure)
- Guard against duplicate cleanup when both WS close and PTY exit
  fire

Observability:
- Add structured logging with [HostConsole] prefix for session
  lifecycle (open, close, duration, user, pid)
- Add diagnostic logging behind developer_mode for terminal resize
  events and message parse errors

Frontend:
- Replace hardcoded hex colors with oklch CSS custom properties
  (--terminal-bg, --terminal-fg, --terminal-cursor, etc.)
- Apply design system material tokens (shadow-card-bevel, recessed
  well shadow, card border hierarchy, strokeWidth 1.5)

Tests:
- Add 20 tests covering env sanitization patterns (10 keyword
  categories + safe vars + case insensitivity), session tracking,
  and console-token RBAC (admin, viewer, deployer, API tokens)

Docs:
- Document admin role requirement and session limits
- Add troubleshooting section (session limits, shell not found,
  proxy timeouts, missing console tab)
- Update security section with expanded env var coverage
2026-04-14 10:06:59 -04:00
sencho-token-app[bot] f207e6000f docs: refresh screenshots (#579)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 12:34:05 +00:00
Anso c4ff58347e fix(container-exec): harden with security fixes, validation, and test coverage (#577)
* fix(container-exec): harden with security fixes, validation, and test coverage

- Enforce admin role at WebSocket upgrade for container exec sessions
- Validate container is running before creating exec
- Fix bash-to-sh fallback (move .start() inside try/catch)
- Register container-exec as a capability for fleet visibility
- Add standard and diagnostic logging for exec lifecycle
- Fix false Admiral license claim in API docs
- Fix design system violations in BashExecModal (hardcoded colors)
- Remove duplicate legacy xterm dependencies
- Add 18-test suite covering auth, validation, fallback, and cleanup

* fix(container-exec): use correct Duplex type for exec stream

The stream variable was typed as NodeJS.ReadWriteStream, which lacks
.destroy(). Dockerode's Exec.start() returns stream.Duplex per its
type definitions. This caused tsc to fail while Vitest (which skips
full type checking) passed.
2026-04-14 08:23:05 -04:00
sencho-token-app[bot] 5908898395 docs: refresh screenshots (#575)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 02:19:39 +00:00
sencho-token-app[bot] 96a653e54f docs: refresh screenshots (#572)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-14 01:43:39 +00:00
sencho-token-app[bot] 4cf6949e9f docs: refresh screenshots (#569)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 22:57:59 +00:00
Anso e0d1ca9dc0 fix(api-tokens): harden with security fixes, design compliance, and test coverage (#567)
Security: add JWT-level expiry ceiling (400d), per-user token count limit (25),
and token name uniqueness enforcement. Fix async clipboard copy.

Design: migrate Select to Combobox, apply card bevel styling, fix icon
strokeWidth, add tabular-nums to timestamps, fix destructive button pattern.

Tests: expand from ~20 to 47 test cases covering creation validation, token
limits, name uniqueness, last_used_at tracking, ownership constraints, delete
edge cases, and registry blocked endpoints.

Docs: update API Tokens docs with token limits, name uniqueness, registry
restrictions, and JWT expiry ceiling. Update OpenAPI spec with 409 response.
2026-04-13 18:32:07 -04:00
sencho-token-app[bot] 02c2d24004 docs: refresh screenshots (#566)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 21:50:40 +00:00
Anso 1d89e8ce59 fix(sso): harden SSO with role sync, security fixes, design compliance, and test coverage (#564)
Rate-limit OIDC callback route and clear state cookie on all paths.
Validate GitHub API responses and add server-side config validation.
Sync SSO user roles on every login respecting seat limits.
Add LDAP connection timeout, bind DN warning, and multiple entry logging.
Replace Select with Combobox and apply card design tokens in SSOSection.
Expose OIDC scopes field in settings UI.
Fix hardcoded colors to use design system tokens.
Add standard and diagnostic logging throughout SSO flow.
Add tests for role sync, seat limits, LDAP escaping, and config validation.
Remove unused login-form.tsx template.
Update docs and screenshots for SSO feature.
2026-04-13 17:46:38 -04:00
sencho-token-app[bot] d184b7134b docs: refresh screenshots (#563)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 19:52:35 +00:00
Anso 6daa7a135d fix(audit): harden audit log with summary fixes, design compliance, and test coverage (#561)
* fix(audit): harden audit log with summary fixes, design compliance, and test coverage

Replace stale /compose/* route summaries with current /stacks/* patterns,
add ~30 missing route summaries for container ops, labels, fleet updates,
SSO, templates, and auto-update. Fix X-Forwarded-For extracting full
proxy chain instead of first client IP. Pre-sort pattern table at module
load for O(1) lookup instead of sorting per request.

Add Calendar and DatePicker UI components (react-day-picker v9 + date-fns)
replacing browser-native date inputs. Align AuditLogView with design system:
Combobox instead of Select, design token colors, strokeWidth 1.5, card bevel,
tabular-nums on all numeric cells.

Add diagnostic logging gated behind developer mode for audit middleware,
query, and export endpoints. Extract getAuditSummary to testable utility.
Add 32 tests covering summary resolution, DB round-trips, API permissions,
export formats, and middleware integration.

* fix(audit): use correct Chevron prop types for react-day-picker compatibility
2026-04-13 15:38:33 -04:00
sencho-token-app[bot] 397b684eab docs: refresh screenshots (#560)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 18:36:22 +00:00
Anso c261fbc327 fix(rbac): harden user management with token versioning, session invalidation, and test coverage (#558)
Security fixes:
- Map deploy-only API tokens to deployer role (not admin)
- Add token versioning to invalidate sessions on password/role changes
- Reject deleted users immediately in auth middleware (no 24h JWT grace)
- Use DB role instead of JWT role so changes take effect instantly
- Block password setting on SSO-provisioned users
- Check proxy variant in scoped permission resolver

Cleanup and logging:
- Remove orphaned role assignments when stacks/nodes are deleted
- Add standard logging for login, user CRUD, role assignments, password changes
- Add diagnostic logging gated behind developer_mode setting
- Extract issueSessionCookie helper (DRY across 5 JWT signing sites)

Frontend:
- Replace Select with Combobox in UsersSection (design system compliance)
- Add strokeWidth={1.5} to Lucide icons
- Hide password fields for SSO-provisioned users

Testing:
- Add 42-test RBAC suite covering user CRUD, token versioning, scoped
  assignments, permissions endpoint, password management, seat limits,
  last-admin protection, and orphan cleanup
2026-04-13 14:31:34 -04:00
sencho-token-app[bot] ed67a2d928 docs: refresh screenshots (#557)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 17:29:52 +00:00
Anso 809bf76c20 fix(fleet): harden fleet snapshots with DRY capture, audit fixes, and design compliance (#555)
Extract duplicated snapshot capture functions from index.ts and
SchedulerService.ts into a shared module (snapshot-capture.ts). Fix
audit log route patterns that used singular 'snapshot' instead of
plural 'snapshots'. Apply design system to FleetSnapshots component
(card styling, strokeWidth, font-mono, tabular-nums, ScrollArea).
Add safePage pagination, loading toast for creation, and fix the
restore dialog race condition with a controlled AlertDialog. Add
diagnostic logging gated behind Developer Mode. Add tests for
restore endpoint, admin role enforcement, and edge cases. Update
docs with troubleshooting section and refresh screenshots.
2026-04-13 13:26:55 -04:00
sencho-token-app[bot] 620e537eda docs: refresh screenshots (#554)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 16:51:59 +00:00
sencho-token-app[bot] faabbea350 docs: refresh screenshots (#551)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 15:40:47 +00:00
sencho-token-app[bot] 313dc73b42 docs: refresh screenshots (#547)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 14:06:21 +00:00
Anso a17b16b258 fix(scheduler): harden auto-update policies with cascade deletes, error reporting, and UI fixes (#545)
* fix(scheduler): harden auto-update policies with cascade deletes, error reporting, and UI fixes

- Fix orphaned task runs on policy/node deletion with transaction-wrapped cascade deletes
- Make manual trigger non-blocking (202 Accepted) to prevent proxy timeouts
- Distinguish registry check failures from clean "no update" results via structured ImageCheckResult
- Trim whitespace-only policy names in both frontend and backend validation
- Add strokeWidth={1.5} to action icons per design system
- Add sr-only DialogDescription for Radix accessibility
- Replace Select with Combobox for frequency picker
- Wrap run history sheet content in ScrollArea
- Support concurrent Run Now indicators via Set-based state
- Abort stale stack fetches on node switch with AbortController
- Add standard and diagnostic logging to SchedulerService and ImageUpdateService
- Add tests for cascade deletes, image checking, and scheduler edge cases
- Add troubleshooting section to auto-update docs

* fix(tests): resolve lint errors in image-update-service tests

Remove unused mock variables (mockGetImage, mockGetDocker) and unused
ImageCheckResult type import. Replace CommonJS require('yaml') with
ESM import to satisfy no-require-imports rule.

* chore(deps): bump Docker CLI to 29.4.0 and Compose to v5.1.2

Resolves Trivy CVE-2026-32282 (Go stdlib symlink follow in Root.Chmod)
by upgrading to releases that ship Go 1.25.9. Compose v5.1.2 also bumps
grpc to 1.80.0, resolving CVE-2026-33186.

* chore(security): accept CVE-2026-32282 in .trivyignore, update stale refs

Go stdlib symlink-following in Root.Chmod (CVE-2026-32282) affects both
Docker CLI 29.4.0 (Go 1.26.1) and Compose v5.1.2 (Go 1.25.8). Fix
requires Go 1.25.9 or 1.26.2; no upstream static binary ships a patched
runtime yet. The vulnerable code path requires a chroot context with
attacker-controlled filesystem, which does not apply to our usage.

Also updates version references from v5.1.1/v29.3.1 to v5.1.2/v29.4.0
for existing CVE entries, and notes that Compose v5.1.2 resolved
CVE-2026-33186 (grpc bumped to 1.80.0) for the compose binary.
2026-04-13 09:49:11 -04:00
sencho-token-app[bot] c6e8efc2e7 docs: refresh screenshots (#544)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 02:09:58 +00:00
sencho-token-app[bot] a0fe84e84b docs: refresh screenshots (#541)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 01:27:35 +00:00
Anso a74a516850 fix(logs): harden global logs with shared parsing, SSE fixes, and level filter (#539)
- Extract log parsing utilities (normalizeContainerName, parseLogTimestamp,
  detectLogLevel, stripControlChars, demuxDockerLog) to shared module,
  eliminating duplication between polling and SSE endpoints
- Fix timestamp regex to accept timezone offsets (+HH:MM/-HH:MM), not just Z
- Replace any[] with typed GlobalLogEntry interface
- Add SSE heartbeat (30s) to prevent reverse proxy timeouts
- Add X-Accel-Buffering: no header for nginx SSE compatibility
- Replace swallowed catch blocks with console.warn diagnostics
- Fix SSE not reconnecting on node switch (missing dep in effect array)
- Add settings change event so devMode/pollRate updates apply without remount
- Add log level filter (ALL/ERROR/WARN/INFO) to toolbar
- Replace overflow-auto div with ScrollArea for design system compliance
- Add strokeWidth={1.5} to all toolbar icons
- Include stack name in download format
- Surface fetch errors with inline banner
- Add 39 unit tests for all log parsing utilities
- Update docs with level filter documentation and refreshed screenshot
2026-04-12 21:19:08 -04:00
sencho-token-app[bot] c1fb0caba6 docs: refresh screenshots (#538)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 00:32:52 +00:00
Anso 1702dabb7a fix(fleet): add auth middleware, input validation, and design system compliance (#536)
Add authMiddleware to all 13 fleet endpoints that were previously
accessible without authentication. Add NaN validation for parseInt
params, stackName validation on snapshot restore, and description
length cap on snapshot creation. Clean up updateTracker entries on
node deletion to prevent memory leaks.

Replace hardcoded colors with design system tokens, swap Select for
Combobox, replace overflow-y-auto with ScrollArea, fix card styling
(shadow-card-bevel, border tokens). Fix stale container data by
always refetching on stack expand with a loading guard against
concurrent requests.

Add operational logging for state-changing fleet operations and
diagnostic logging gated behind Developer Mode. Add 20 fleet tests
covering auth enforcement, input validation, tier gating, and
snapshot CRUD lifecycle.
2026-04-12 20:28:18 -04:00
sencho-token-app[bot] bbaee7f7f0 docs: refresh screenshots (#535)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-13 00:00:27 +00:00
Anso cd3d7b23be feat(app-store): add port conflict indicator to deploy sheet (#533)
Show a pulsating warning dot next to host ports that are already in
use by a running container. Hovering over the dot reveals which
Sencho-managed stack or external app occupies the port.

Adds GET /api/ports/in-use endpoint that returns a map of bound host
ports with ownership info, and a getPortsInUse method on
DockerController that reuses the existing container-to-stack
resolution logic.
2026-04-12 19:57:38 -04:00
sencho-token-app[bot] 7a2099b56e docs: refresh screenshots (#532)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 23:32:37 +00:00
sencho-token-app[bot] 36f2e8a7bc docs: refresh screenshots (#529)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 19:37:01 +00:00
Anso 4909c35e50 fix(resources): harden Resource Explorer with auth, validation, design, and UX fixes (#527)
- Sanitize error messages in all delete/prune/create/inspect endpoints
  to prevent Docker internals from leaking to the frontend
- Add CIDR, IPv4, and Docker resource ID input validation
- Add requirePaid gate to network topology endpoint
- Add invalidateNodeCaches after image/volume/network mutations
- Fix design system violations: card borders, destructive button variant,
  visible DialogDescription, overflow-auto replaced with ScrollArea,
  hardcoded Tailwind colors replaced with tokens
- Gate purge button behind isAdmin to prevent silent 403s
- Fix shared inspect loading state to be per-network-row
- Parse error response bodies for meaningful toast messages
- Add clipboard API fallback for non-HTTPS contexts
- Render Options section in network inspect sheet
- Add operational and diagnostic logging for resource operations
- Extend validation and DockerController test suites
- Update docs with Options field in network inspect
2026-04-12 15:31:35 -04:00
sencho-token-app[bot] a5cb316ca9 docs: refresh screenshots (#525)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 18:33:50 +00:00
sencho-token-app[bot] 8e91f91622 docs: refresh screenshots (#522)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 09:48:00 +00:00
sencho-token-app[bot] 3ad1ab5c84 docs: refresh screenshots (#519)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 08:28:47 +00:00
Anso 9db97107aa fix(dashboard): harden real-time dashboard with bug fixes and design compliance (#517)
* fix(dashboard): harden real-time dashboard with bug fixes and design compliance

- Fix host alert spam: add 5-minute cooldown for CPU/RAM/disk threshold
  alerts, preventing duplicate notifications every 30s during sustained
  breaches. Extract shared dispatchWithCooldown helper (also used by
  Docker janitor alerts).
- Fix memory metric inflation: subtract filesystem cache from stored
  memory_mb values, matching the existing calculateMemoryPercent logic.
- Fix crash detection reliability: replace fragile 'seconds ago' string
  matching with a tracked Set of alerted container IDs. Containers are
  only alerted once per crash event, with automatic cleanup when they
  start running again or after a 1-hour TTL.
- Fix health status bar: exited containers now trigger 'degraded' state
  independently of unread error notifications.
- Fix CPU chart Y-axis: auto-scale when aggregate container CPU exceeds
  100% instead of silently clipping at the hardcoded domain ceiling.
- Fix grammar: 'actives' to 'active' in container count label.
- Add shadow-card-bevel to all dashboard cards per design system.
- Update dashboard docs to reflect revised health status thresholds.

* test(dashboard): update monitor service tests for new alert signatures

- Add container Id fields to crash detection test fixtures
- Update host alert assertions to match dispatchWithCooldown 3-arg call
- Fix unhealthy container test to use State: 'unhealthy' instead of
  State: 'running' (running containers are now skipped in crash detect)
2026-04-12 04:25:41 -04:00
sencho-token-app[bot] c7f041957c docs: refresh screenshots (#516)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 07:22:13 +00:00
Anso 4950cd0bd0 fix(updates): scan all filesystem stacks for image updates (#514)
ImageUpdateService previously discovered stacks by iterating Docker
containers, which meant stacks without containers (e.g. after
docker compose down) were silently excluded from update checks.

Switch to a hybrid discovery approach: enumerate stacks from the
filesystem via FileSystemService.getStacks(), parse compose files
for image refs with .env variable resolution, then augment with
container-based image discovery for running stacks.

Also cleans up stale stack_update_status entries when stacks are
deleted or no longer exist on disk, and replaces the plain
update-available tooltip with an animated cursor follow pattern.
2026-04-12 03:17:37 -04:00
sencho-token-app[bot] f26ac16bc0 docs: refresh screenshots (#513)
Co-authored-by: AnsoCode <18150933+AnsoCode@users.noreply.github.com>
2026-04-12 06:29:22 +00:00