Commit Graph
514 Commits
Author SHA1 Message Date
SnapOtter 110700520c feat: add GET /api/v1/tools/popular endpoint 2026-06-14 18:36:32 +08:00
SnapOtter f9ed5d125a Merge branch 'feat/enterprise-on-prem' 2026-06-14 16:10:15 +08:00
SnapOtter e7bef34918 style: apply Biome formatting to enterprise files 2026-06-14 14:53:44 +08:00
SnapOtter 954cfb01a6 fix: test server registration gaps, Redis subscriber cleanup, atomic settings upsert 2026-06-14 14:30:35 +08:00
SnapOtter 29dd675f42 fix(enterprise): SCIM token generation, GDPR job cancellation, MFA replay, config redaction, encryption validation, SCIM rate limit
- Add POST/DELETE /api/v1/enterprise/scim/token for SCIM bearer token management
- Cancel active BullMQ jobs via requestCancel() before GDPR purge deletes DB rows
- Reject duplicate MFA enrollment when a pending (unverified) secret exists
- Add webhook_destinations to config export REDACTED_KEYS (contains auth headers)
- Validate DATA_ENCRYPTION_KEY and DATA_ENCRYPTION_KEY_PREVIOUS are 64-char hex at startup
- Add 1000 req/min Redis counter rate limit to SCIM auth middleware
- Document SIEM/webhook system coexistence in siem-forward.ts
2026-06-14 14:03:47 +08:00
SnapOtter d86e4585e4 feat(enterprise): add unified webhook system with admin alerts 2026-06-14 12:21:46 +08:00
SnapOtter 0f883fe853 feat(enterprise): add configuration export/import with dry-run and dependency validation 2026-06-14 12:17:40 +08:00
SnapOtter 03e12e6f0b feat(enterprise): add upgrade management endpoints (version, migrations, readiness) 2026-06-14 12:14:52 +08:00
SnapOtter 2aea351f70 feat: add backup status tracking endpoints 2026-06-14 12:11:23 +08:00
SnapOtter 239f85f098 feat: add per-user rate limiting and concurrent job limits
Redis sliding window (sorted set) enforces per-user request rate limits
via the rateLimitPerUser DB setting. Concurrent job limits checked at
the HTTP layer before enqueue via maxConcurrentJobsPerUser setting.
Both default to 0 (unlimited).
2026-06-14 12:09:25 +08:00
SnapOtter fb14f41512 feat: expand Prometheus metrics with request duration, storage, and auth counters 2026-06-14 12:06:06 +08:00
SnapOtter 6237684ec8 feat: extend health endpoints with disk space, S3, storage, and backup checks 2026-06-14 12:01:29 +08:00
SnapOtter 7f62b1bf12 fix: resolve 6 bugs from enterprise audit (SIEM cursor, legal hold join, SCIM role, GDPR self-purge, export OOM, quota check) 2026-06-14 11:04:44 +08:00
SnapOtter b9dac59736 fix: correct SAML idpCert property name for @node-saml/node-saml v5 2026-06-13 23:02:20 +08:00
SnapOtter db6f7bf38a feat(enterprise): add IP allowlisting with CIDR matching and Redis cache
Enterprise-gated onRequest hook that restricts API access to
configured CIDR ranges using Node 22's native BlockList.

- Plugin (ip-allowlist.ts): builds a BlockList from the ipAllowlist
  setting, caches in-process, syncs across instances via Redis pub/sub.
  Exempt paths for health probes, SCIM, SAML/OIDC callbacks.
  Handles IPv4-mapped IPv6 (::ffff:x.x.x.x) transparently.
- Admin API (enterprise/ip-allowlist.ts): GET/PUT endpoints gated by
  security:manage permission and ip_allowlist feature flag.  Validates
  CIDRs, prevents self-lockout, emits IP_ALLOWLIST_UPDATED audit event.
- 32 unit tests covering CIDR matching, validation, exempt paths, IPv6,
  and edge cases (/0, /32, mapped addresses).
2026-06-13 22:54:06 +08:00
SnapOtter 1787be35fe feat(enterprise): add TOTP MFA with enrollment, verification, and recovery codes 2026-06-13 22:49:00 +08:00
SnapOtter a1b5c6d2c3 feat(enterprise): add SCIM 2.0 provisioning (Users + Groups) 2026-06-13 22:42:55 +08:00
SnapOtter 0c4468a004 feat(enterprise): add SSO enforcement mode with break-glass admin 2026-06-13 22:32:16 +08:00
SnapOtter 54132d1833 feat(enterprise): add SAML 2.0 SSO with SP-initiated login
Implements SAML SSO using @node-saml/node-saml, gated behind
SAML_ENABLED env var and the saml_sso enterprise license feature.

- SAML env vars (entity ID, callback URL, IdP SSO URL, IdP cert,
  auto-create/auto-link users, default role, provider name,
  username/email attribute mapping) with validation in superRefine
- SAML plugin with three routes: metadata (GET), login (GET),
  and ACS callback (POST with form-urlencoded content type parser)
- Callback uses the shared external-auth resolver for user
  resolution (same pattern as OIDC: match/link/create/deny)
- Auth config endpoint exposes samlEnabled and samlProviderName
- Session loginMethod detection updated for SAML auth provider
- Frontend login page shows SAML SSO button when enabled
- i18n strings for SAML error messages across all 21 locales
2026-06-13 22:27:56 +08:00
SnapOtter 6920035f5a refactor: extract external auth resolver from OIDC for SAML reuse
Move user resolution logic (match by externalId, auto-link by email,
auto-create with user limit check) into a shared module that both
OIDC and SAML callbacks can use. Includes sanitizeUsername and
findUniqueUsername helpers. Preserves all existing OIDC behavior
and audit events.
2026-06-13 22:20:22 +08:00
SnapOtter 8b349b0341 feat: make password policy configurable via admin settings 2026-06-13 22:12:38 +08:00
SnapOtter 9fa23f4543 feat: add per-tool permission model with category and per-tool modes 2026-06-13 22:11:03 +08:00
SnapOtter 3cc4ef6895 feat: add session idle timeout and concurrent session limit
Idle timeout: reads `sessionIdleTimeoutMinutes` from settings, tracks
last activity in Redis (with Postgres fallback on cache miss), and
invalidates sessions that exceed the configured idle window.

Concurrent session limit: reads `maxSessionsPerUser` from settings
and evicts oldest sessions (FIFO) when a new login exceeds the cap.

Both features are opt-in (disabled when value is 0 or absent).
2026-06-13 22:07:31 +08:00
SnapOtter 7ed043ec53 feat(db): add identity columns (lastActivity, toolPermissions, TOTP) 2026-06-13 22:04:14 +08:00
SnapOtter 8eefa46981 chore: install @node-saml/node-saml and otpauth for Phase 3 identity 2026-06-13 22:04:03 +08:00
SnapOtter dd2a50799a feat(enterprise): add GDPR user/team data purge with audit redaction 2026-06-13 21:13:22 +08:00
SnapOtter b6a8226837 feat(enterprise): add GDPR user data export (async) 2026-06-13 21:07:28 +08:00
SnapOtter fa7da7ce0c feat(enterprise): add legal hold with cleanup bypass 2026-06-13 21:01:04 +08:00
SnapOtter b60f550b3f feat(enterprise): add per-team retention overrides with deleteAfter
Compute a deleteAfter timestamp on job creation when the enterprise
team_retention_overrides feature is enabled. The cleanup sweep now
deletes storage for jobs past their deleteAfter deadline, running
independently of the global TTL setting.
2026-06-13 20:55:17 +08:00
SnapOtter d064286559 feat: add team-level storage quotas with enforcement on upload and save 2026-06-13 20:49:28 +08:00
SnapOtter b1e94bd988 fix: build script venv handling and lint fixes
- Use /opt/venv directly when --entrypoint bash bypasses entrypoint.sh
- Use sys.executable for all pip calls (not bare pip)
- Override entrypoint in CI workflow to avoid startup banner
- Fix Biome formatting (template literals, try/catch blocks)
2026-06-13 20:48:27 +08:00
SnapOtter aaa8a37c9b feat: add storage usage tracking with DB counters and reconciliation
Increment users.storageUsed on file upload/save, decrement on delete
(per-user via GREATEST to prevent negatives). Add per-team storage
breakdown to GET /api/v1/admin/usage. Weekly reconciliation job
(3 AM Sunday) recomputes counters from actual userFiles sums.
2026-06-13 20:43:52 +08:00
SnapOtter 7e5843cd40 feat(db): add data lifecycle columns (deleteAfter, legalHold, quotas, retention) 2026-06-13 20:39:38 +08:00
SnapOtter 1cf1f47d6f feat: add request correlation IDs to audit logs and response headers 2026-06-13 17:04:27 +08:00
SnapOtter c1dc27f248 feat(enterprise): add audit log archival with crash-safe state machine 2026-06-13 16:57:20 +08:00
SnapOtter d3f30a2f5d feat(enterprise): add SIEM webhook forwarding with circuit breaker 2026-06-13 16:53:32 +08:00
SnapOtter ab88b9ad0d feat: add webhook delivery module with retry and backoff 2026-06-13 16:49:47 +08:00
SnapOtter 895e29e93f feat(enterprise): add tamper-resistant audit mode with HMAC integrity 2026-06-13 16:48:09 +08:00
SnapOtter 913dd6bbe1 feat(enterprise): add audit log export endpoint (CSV/JSON) 2026-06-13 16:45:11 +08:00
SnapOtter c6f9a29687 feat(web): complete audit log viewer with IP column and all event types 2026-06-13 16:42:10 +08:00
SnapOtter 2520cdd556 feat: add AES-256-GCM encryption at rest for sensitive settings 2026-06-13 16:35:28 +08:00
SnapOtter 5d5240e481 feat: extend importBundleArchive for site-packages and fixups 2026-06-13 16:32:45 +08:00
SnapOtter 36f083ba64 feat(audit): add TOOL_EXECUTED logging with opt-in setting
Add isToolAuditEnabled() helper that checks the auditToolOperations
DB setting (off by default) or falls back to the enterprise
audit_export feature flag. The createToolRoute factory now emits a
TOOL_EXECUTED audit entry on successful tool execution when enabled,
using a fire-and-forget pattern so a failed audit write never blocks
the tool response.
2026-06-13 16:31:49 +08:00
SnapOtter d1e9536cff feat: extend crash recovery for pre-built bundle artifacts 2026-06-13 16:29:50 +08:00
SnapOtter 37b2b9c2ee feat(audit): extensible event type system with shared constants 2026-06-13 16:27:53 +08:00
SnapOtter 5d2f520d78 feat(audit): capture IP address, make TRUST_PROXY configurable 2026-06-13 16:25:58 +08:00
SnapOtter 86d6f50ea6 feat: add enterprise Phase 1-4 feature flags and new permissions 2026-06-13 16:20:24 +08:00
SnapOtter cafd2d8b65 feat(db): add audit integrity/requestId columns, user_preferences table, audit indexes 2026-06-13 16:17:17 +08:00
SnapOtter 82991b6a41 fix(api): fix batch user-files delete recursive CTE query
The refactored CTE used = ANY(${validIds}::uuid[]) which Drizzle
serializes as a scalar text parameter with a ::uuid[] cast. Since
the user_files.id column is text (not uuid), PostgreSQL rejects
the text = uuid comparison. Replace with IN (...) via sql.join()
to pass each ID as a plain text parameter matching the column type.
2026-06-13 10:55:14 +08:00
SnapOtter e2c57144dd fix(api): batch user-files delete to eliminate N+1 queries 2026-06-13 10:37:32 +08:00