* feat(sync): add Helm chart for SuperSync Kubernetes deployment
Includes Deployment, StatefulSet (PostgreSQL), Service, Ingress,
ConfigMap, Secret, HPA, PDB, NetworkPolicy, and test templates.
Supports both bundled PostgreSQL and external database configurations.
* feat(sync): add WebSocket push notifications for near-realtime sync
Server: Fastify WebSocket plugin with connection manager, app-level
heartbeat (30s), debounced notifications, and per-user routing.
Client: WebSocket service with exponential backoff reconnection,
WS-triggered download service, and reduced polling when connected.
* fix(sync): improve WebSocket error handling and reactivity
Make syncInterval$ reactive to WS connection state, fix Set/Map
mutation during heartbeat iteration, add error handling to WS route
handler, separate JSON parsing from message handling, detect auth
failures in WS-triggered downloads, and add logging to all empty
catch blocks.
* fix(sync): address PR review findings for WebSocket and Helm
Fix race condition in WS-triggered download pipeline by moving
isSyncInProgress filter after debounce and adding guard in
_downloadOps. Add logging to remaining empty catch blocks, fix
missing $NODE_IP in Helm NOTES.txt, and correct inaccurate
comments in values.yaml and ws-triggered-download.service.ts.
* fix(sync): add rate limiting to WebSocket upgrade endpoint
Limit WS connection attempts to 10 per minute per IP to prevent
connection flooding, matching the rate-limit pattern used by other
sync endpoints.
* fix(sync): extract shared constants, fix debounce correctness, replace deprecated toPromise
Extract CLIENT_ID_REGEX and MAX_CLIENT_ID_LENGTH into sync.const.ts
to prevent drift between sync.routes.ts and websocket.routes.ts.
Fix debounce in notifyNewOps to accumulate excluded client IDs across
rapid calls from different clients, preventing self-notifications.
Replace deprecated toPromise() with firstValueFrom in connectWebSocket
and _sync methods. Add .catch() to reconnect path and logging to
silent early returns in _downloadOps.
* fix(build): restore correct package-lock.json and fix upstream lint errors
* revert: restore upstream HTML formatting to match CI prettier config
* fix(sync): use DownloadOutcome discriminated union in WsTriggeredDownloadService
* fix(sync): narrow TokenVerificationResult before accessing userId
* fix(sync): await async getProviderById in connectWebSocket
Missing await caused the Promise object to be cast to
SuperSyncProvider, making getWebSocketParams undefined.
* feat(sync): add SEED_USERS env var to create verified users on startup
For self-hosted single-user setups: set SEED_USERS=email1,email2 to
create verified users on boot and log their access tokens. Skips
existing users. Removes need for SMTP/magic link registration.
Also fix Dockerfile to use npm install instead of npm ci for lockfile
compatibility.
* fix(sync): address PR review feedback for Helm chart and server
Security:
- Remove seed-users.ts (logged full JWT tokens to stdout)
- Add fail assertions for missing jwtSecret and postgresql.password
- Add smtp.user/smtp.password values fields
- Add from: selector to NetworkPolicy ingress
- Add egress rule for external database when postgresql.enabled=false
Correctness:
- Fix PostgreSQL StatefulSet indentation for non-persistent mode
- Fix NOTES.txt panic on empty tls list (use len instead of index)
- Restore npm ci in Dockerfile by using node:24-alpine (ships npm 11)
- Add Recreate deployment strategy when using RWO PVC
Operational:
- Add fail guard preventing HPA maxReplicas > 1 (in-memory WS state)
- Fix PDB to use maxUnavailable instead of minAvailable
- Add WebSocket ingress timeout annotation examples
- Add Prisma db push init container for schema migrations
- Default serviceAccount.automount to false
- Add Chart.yaml maintainers, home, sources metadata
* feat(sync): add ALLOWED_EMAILS env var to restrict registration
Supports fully qualified emails (user@example.com) and domain
wildcards (*@example.com). When unset, all emails are allowed.
Applied to all three registration endpoints (passkey options,
passkey verify, magic link).
* fix(sync): exempt health endpoint from rate limiting
Kubernetes liveness/readiness probes hit /health every 5-15s,
exhausting the global rate limit (100 req/15min) and causing
429 responses that trigger container restarts.
* fix(sync): harden WebSocket, Helm chart, and sync services from multi-agent review
- Pin prisma@5.22.0 in init container and use migrate deploy instead of db push
- Add per-user WebSocket connection limit (max 10) to prevent resource exhaustion
- Add replicaCount > 1 fail guard in deployment template (in-memory WS state)
- Set maxPayload: 1024 on WebSocket plugin (only pong messages expected)
- Remove premature IN_SYNC status from download-only WS-triggered sync
- Fix double removeConnection on error+close events (let close handle cleanup)
- DRY debounce logic in notifyNewOps and store latestSeq on pending entry
- Remove dead fromClientId from NewOpsNotification and WsMessage interfaces
- Add takeUntilDestroyed to _wsProviderCleanup subscription
- Simplify email-allowlist.ts to eager init (eliminate mutable state)
- Guard connectWebSocket at call site for non-SuperSync providers
- Add distinctUntilChanged to syncInterval$ to prevent unnecessary resets
- Add container-level securityContext to PostgreSQL StatefulSet
- Fix HPA maxReplicas default to 1 (matches single-replica constraint)
* fix(sync): restore migration in Dockerfile CMD for non-Helm Docker users
Helm users get migration via init container (runs first, CMD becomes no-op).
Docker-compose/plain Docker users get automatic migration back on startup.
* fix(boards): add missing drag delay for touch and extract shared signal
Add cdkDragStartDelay to board-panel drag items, which was missing
entirely. Extract the repeated `isTouchActive() ? DRAG_DELAY_FOR_TOUCH : 0`
expression into a shared `dragDelayForTouch` computed signal and refactor
all 8 components to use it.
* test(sync): add comprehensive WebSocket test coverage
Add unit tests for the new WebSocket real-time sync notification pipeline:
- WebSocketConnectionService (server): connection lifecycle, max-per-user
limits, notification debouncing, heartbeat, graceful shutdown (13 tests)
- WebSocket routes validation: token/clientId validation, close codes,
error handling, validation ordering (18 tests)
- SuperSyncWebSocketService (frontend): reconnection with exponential
backoff, heartbeat, disconnect cleanup, URL conversion (6 tests)
- WsTriggeredDownloadService: auth error handling, pipeline resilience,
start() idempotency (3 tests)
- SyncWrapperService: connectWebSocket guards for non-SuperSync, null
params, and already-connected cases (3 tests)
- E2E realtime push: verifies WS-triggered download between two clients
Quality fixes:
- Replace waitForTimeout with syncAndWait in E2E
- Add explanatory comment for microtask flushing in sync-wrapper spec
- Use getter for isSyncInProgress mock in ws-triggered-download spec
---------
Co-authored-by: Johannes Millan <johannes.millan@gmail.com>
The monitor:all, analyze-storage, and related npm scripts used tsx
which isn't available in the production Docker image. Switch to
node dist/scripts/*.js and add :dev variants for local development.
Add pretest script to run prisma generate before tests, ensuring the
Prisma client is always generated in any environment. Fix verifyToken
mocks across all test files to include valid:true matching the
TokenVerificationResult discriminated union. Expand jsonwebtoken mock
to include JsonWebTokenError/TokenExpiredError stubs needed by auth.ts.
Add $queryRaw to transaction mock in sync-fixes tests.
Add reusable investigation scripts for analyzing SuperSync storage patterns,
user behavior, and operation anomalies.
New scripts:
- analyze-storage.ts: 9 specialized analysis commands (operation sizes,
timeline, types, large ops, rapid-fire detection, snapshots, user deep-dive,
export, compare users)
- run-all-monitoring.ts: Complete monitoring suite runner with quick mode
and save-to-file options
- MONITORING-README.md: Complete documentation with investigation workflows
New npm scripts:
- npm run analyze-storage -- <command>: Run specific analysis
- npm run monitor:all: Run complete monitoring suite
- npm run monitor:all:quick: Quick health check (skip deep analysis)
- npm run monitor:all:save: Save timestamped report to file
These tools provide structured workflows for investigating storage issues
like rapid-fire operations, unusually large operations, and sync loops.
- Update @simplewebauthn/server from v11 to v13.2.2 for compatibility
- Add debug logging for WebAuthn config and authentication options
- Browser library also needs to be updated to v13.2.2 (manual step)
The version mismatch between server and browser libraries may have been
causing passkey registration/login issues.
Authentication changes:
- Add passkey (WebAuthn) as primary login method
- Add email magic link as fallback for devices without passkey support
- Remove password-based authentication entirely
New features:
- Passkey registration and login via @simplewebauthn/server
- Magic link login with 15-minute expiry tokens
- Passkey recovery via email link
- Self-hosted simplewebauthn-browser.min.js for reliability
Database changes:
- Add Passkey model for WebAuthn credentials
- Add PasskeyChallenge model for registration/auth challenges
- Add loginToken and loginTokenExpiresAt fields for magic links
- Add passkeyRecoveryToken fields for passkey recovery
UI changes:
- Login form: email + "Login with Passkey" + "Send Login Link"
- Register form: email + terms checkbox + "Register with Passkey"
- Consistent token display UI for both passkey and magic link login
- Remove password fields and forgot password flow
Security:
- CSP-compliant magic link redirect using external script
- Rate limiting on all auth endpoints
- Single-use magic link tokens
ts-node is a devDependency and not available in production containers.
Updated tsconfig to compile scripts/ alongside src/, and changed npm
scripts to use compiled JS. Added monitor:dev for local development.
Switch from server-side builds to pre-built images:
- Add build-and-push.sh for local builds to GHCR
- Update deploy.sh to pull from registry (30s vs 20min)
- Add docker-compose.build.yml for local build fallback
- Update docker-compose.yml to use registry image
- Add GHCR_USER/GHCR_TOKEN to env.example
- Add npm scripts: docker:build, docker:deploy, docker:backup
- Update start script to use docker compose
- Add logs script for viewing container logs
- Expand privacy policy and terms of service content
- Format app.js and registration-api.spec.ts
This commit introduces a lightweight monitoring CLI tool for the super-sync-server.
Changes include:
- Enhanced logging: now supports writing logs to a file () when is set, enabling persistent log storage.
- New monitoring script: provides commands for:
- : Displays system vitals (CPU, RAM) and database connectivity/size.
- : Shows top 20 users by data storage usage within the database.
- : Allows tailing, searching, and filtering server logs from the file.
- update: Added a script to easily run the tool.
Refactored 'delete-user.ts' and 'clear-data.ts' to use Prisma Client, aligning them with the current PostgreSQL architecture.
Updated 'packages/super-sync-server/README.md' to reflect the Docker-based, PostgreSQL setup and added documentation for the administrative scripts.
Removed '@types/better-sqlite3' from 'package.json' as it's no longer needed.
Create @sp/shared-schema package with pure TypeScript migration functions
that work in both Angular frontend and Node.js backend environments.
Package contents:
- schema-version.ts: Version constants (CURRENT=1, MAX_SKIP=3)
- migration.types.ts: OperationLike, SchemaMigration interfaces
- migrate.ts: Pure functions (migrateState, migrateOperation, etc.)
- migrations/index.ts: Empty migrations array (ready for first migration)
- 22 unit tests covering all migration scenarios
Backend changes:
- Add snapshot_schema_version column to user_sync_state table
- Migrate snapshots during generateSnapshot if outdated
- Migrate operations during replayOpsToState if outdated
- Drop operations that return null from migration (removed features)
Frontend changes:
- Refactor SchemaMigrationService to use @sp/shared-schema
- Re-export constants for backwards compatibility
- All 20 existing tests pass
This enables coordinated schema migrations across client and server,
ensuring old snapshots and operations can be upgraded when the state
structure changes.
Rollout strategy: Deploy backend first, then frontend.
- Rewrote README to clarify custom operation-log architecture (not WebDAV).
- Added Vitest and implemented comprehensive unit tests for SyncService.
- Implemented Incremental Snapshots to improve performance.
- Reduced stale device cleanup threshold to 30 days to reduce DB bloat.
- Increased max payload size to 20MB to support large initial imports.
- Added in-memory DB support for faster testing.
Replace custom UUID v7 implementations with the standard uuidv7 library.
The custom implementation had a bug with JavaScript bitwise operators
not handling 48-bit timestamps correctly.
- Remove webdav-server dependency from super-sync-server
- Create SuperSyncPrivateCfg model for SuperSync configuration
- Refactor SuperSyncProvider to use REST API instead of WebDAV
- Add early return in sync.service for operation-only providers
- Add nodemon for dev server auto-restart
- Remove file-based sync support from SuperSync provider