Commit Graph

8 Commits

Author SHA1 Message Date
Anso d586ce393a feat(audit-log): add configurable retention, export, Auditor role, and enhanced filtering (#258)
- Configurable retention: audit_retention_days setting (1-365 days, default 90)
  replaces hardcoded 90-day retention, exposed in Settings > Data Retention
- Export: one-click CSV/JSON export of filtered audit data via new
  GET /api/audit-log/export endpoint (capped at 10,000 entries)
- Auditor role: read-only role with system:audit permission for viewing
  and exporting audit logs without admin privileges (Admiral tier)
- Enhanced filtering: full-text search across summaries/paths/usernames,
  date range picker, and expandable row details showing request path,
  IP address, node ID, and entry ID
2026-03-29 20:18:51 -04:00
Anso c328b7f49a refactor: rename Personal Pro to Skipper and Team Pro to Admiral (#256)
Align paid tier names with Sencho's nautical identity. Internal variant
values ('personal'/'team') remain unchanged in code, database, and
Lemon Squeezy integration — only user-facing display names updated.

- Backend: requireTeamPro → requireAdmiral, TEAM_PRO_REQUIRED → ADMIRAL_REQUIRED
- Frontend: TeamProGate.tsx → AdmiralGate.tsx, TierBadge labels updated
- Website: PricingSection tier names and nautical descriptions
- Docs: all 11 affected pages renamed, nautical footnote added to licensing
2026-03-29 18:00:29 -04:00
Anso 8380fbad4b feat(rbac): add Deployer & Node Admin roles with scoped permissions (Team Pro) (#253)
* feat(rbac): add Deployer & Node Admin roles with scoped permissions (Team Pro)

Add intermediate RBAC roles gated to Team Pro tier:
- Deployer: can deploy/restart/stop/start stacks but cannot edit compose files, delete stacks, or access system settings
- Node Admin: full stack and node management within scope, no system settings access
- Scoped permissions: assign roles per-stack or per-node for fine-grained access control
- Permission engine with checkPermission/requirePermission guards replacing requireAdmin on stack/node routes
- Frontend can() function with /api/permissions/me endpoint for client-side permission checks
- User management UI updated with 4-role selector and scoped permission editor
- Documentation updated with permission matrix, scoped permission docs, and screenshots

* fix(rbac): remove unused RoleAssignment import to fix lint error
2026-03-29 17:02:56 -04:00
Anso bd4008f509 feat: SSO & LDAP authentication for Team Pro (#209)
* feat: SSO & LDAP authentication for Team Pro

Add SSO integration allowing Team Pro users to authenticate via LDAP/Active Directory, Google, GitHub, and Okta identity providers. SSO works alongside password authentication with auto-provisioning and role mapping.

- LDAP bind+search authentication with group-based role mapping
- OIDC/OAuth2 flows with PKCE and CSRF protection for Google, GitHub, Okta
- Auto-provisioning: first SSO login creates a Sencho account automatically
- Role mapping via LDAP group membership or OIDC JWT claims
- SSO settings UI in Settings → SSO with per-provider config and test connection
- SSO login buttons on login page with LDAP toggle
- Environment variable seeding for infrastructure-as-code workflows
- Secrets encrypted at rest via CryptoService (AES-256-GCM)
- Seat limit enforcement during auto-provisioning
- Full documentation: feature docs, quickstart guides, env var reference

* fix: resolve ESLint errors in SSO feature

- Remove unnecessary escape characters in regex character classes
- Remove unused `issuer` variable from OIDC callback handler
- Fix setState-in-effect lint error in Login.tsx by using useState initializer
- Suppress set-state-in-effect for SSOSection fetch pattern (matches existing codebase convention)
2026-03-28 03:30:01 -04:00
Anso db73d7671a feat: RBAC, atomic deployments, and fleet-wide backups (Pro) (#181)
* feat: add RBAC viewer accounts, atomic deployments, and fleet-wide backups (Pro)

Introduces three Pro-tier features:

- RBAC: Multi-user system with admin/viewer roles, user management UI,
  automatic migration from single-admin credentials, viewer restrictions
  across the entire UI (read-only editor, hidden action buttons)

- Atomic Deployments: Pre-deploy file backup to .sencho-backup/, automatic
  rollback on health probe failure, manual rollback button, health probes
  added to stack updates, webhook-triggered deploys use atomic rollback

- Fleet-Wide Backups: Point-in-time snapshots of compose files across all
  nodes (local + remote), stored centrally in SQLite, per-stack restore
  with optional redeploy, graceful handling of offline nodes

* fix(settings): use correct ProGate prop name in UsersSection

* fix(settings): remove unused isPro prop from UsersSection

* fix(auth): fetch user info after login and setup so isAdmin is set correctly
2026-03-26 12:51:30 -04:00
SaelixCode c8a54a988b fix(lint): resolve all ESLint errors to pass CI lint step
- Replace catch (error: any) with catch (error) + (error as Error).message cast
  in EditorLayout, NodeManager, HomeDashboard, AppStoreView
- Define TemplateVolume interface in AppStoreView; replace volumes any[] with typed array
- Define MetricPoint interface in HomeDashboard; replace metrics any[] with MetricPoint[]
- Define TerminalContainer type in BashExecModal; replace as any DOM property casts
- Define NodeTestInfo interface in NodeManager; replace info: any with typed shape
- Fix DockerNetworkStats cast in EditorLayout container stats WebSocket handler
- Remove unused catch variable (e) in api.ts and other components
- Cast streamFilter onValueChange val to union type in GlobalObservabilityView
- Add eslint-disable-next-line react-refresh/only-export-components to badge.tsx,
  button.tsx, AuthContext, NodeContext, use-data-state, use-is-in-view
- Add eslint-disable-next-line react-hooks/set-state-in-effect in LogViewer
- Add /* eslint-disable */ to animate-ui third-party primitive files
2026-03-22 00:27:43 -04:00
SaelixCode 67c7078128 fix: stop infinite page reload caused by premature NodeProvider mount and 401 hard-redirect
- Move NodeProvider inside the authenticated branch in App.tsx so it only
  mounts after auth is confirmed; previously it mounted on boot causing
  refreshNodes to fire before any session existed
- Replace window.location.href='/' on 401 in apiFetch with a
  sencho-unauthorized custom event; AuthContext listens and transitions
  appStatus to notAuthenticated without a full browser reload
2026-03-19 13:57:48 -04:00
unknown 293f9cef26 Initial commit: Sencho V1 complete with Auth and Dockerization 2026-02-20 18:39:32 -05:00