Commit graph

33 commits

Author SHA1 Message Date
Thorsten Klein
7fa8f12132
feat(sync): add Helm chart and WebSocket push for SuperSync (#6971)
* 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>
2026-03-30 21:34:30 +02:00
Johannes Millan
e2145fa2ef fix(sync-server): use compiled JS for monitoring npm scripts in Docker
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.
2026-03-27 18:05:30 +01:00
dependabot[bot]
3423193d82
chore(deps): bump nodemailer (#6974)
Bumps the npm_and_yarn group with 1 update in the / directory: [nodemailer](https://github.com/nodemailer/nodemailer).


Updates `nodemailer` from 7.0.13 to 8.0.4
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v7.0.13...v8.0.4)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-version: 8.0.4
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 12:26:07 +01:00
Johannes Millan
43e04bc407 fix(sync): fix supersync server unit test failures
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.
2026-03-22 10:10:19 +01:00
dependabot[bot]
620cd3dd52
chore(deps): bump fastify in the npm_and_yarn group across 1 directory (#6753)
Bumps the npm_and_yarn group with 1 update in the / directory: [fastify](https://github.com/fastify/fastify).


Updates `fastify` from 5.7.3 to 5.8.1
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/compare/v5.7.3...v5.8.1)

---
updated-dependencies:
- dependency-name: fastify
  dependency-version: 5.8.1
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-07 11:02:30 +01:00
dependabot[bot]
518d40f6c1
chore(deps): bump fastify in the npm_and_yarn group across 1 directory (#6334)
Bumps the npm_and_yarn group with 1 update in the / directory: [fastify](https://github.com/fastify/fastify).


Updates `fastify` from 5.6.2 to 5.7.3
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/compare/v5.6.2...v5.7.3)

---
updated-dependencies:
- dependency-name: fastify
  dependency-version: 5.7.3
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-03 12:19:34 +01:00
Johannes Millan
554cc09608 feat(supersync): add production Docker monitoring wrapper and tooling
Add docker-monitor.sh wrapper script for running monitoring tools in
production Docker containers, with automatic tsx installation.

Changes:
- docker-monitor.sh: Wrapper script for all monitoring commands
  - Supports basic monitoring (stats, usage, ops, logs)
  - Supports analysis commands (user-deep-dive, large-ops, etc)
  - Auto-installs tsx in container when needed
  - Handles report extraction from container
- Dockerfile: Include TypeScript source files for tsx execution
- package.json: Add docker:monitor npm scripts
- DOCKER-MONITORING.md: Production Docker monitoring guide

New npm scripts:
- npm run docker:monitor -- <command>: Run any monitoring command
- npm run docker:monitor:usage: Quick storage check
- npm run docker:monitor:all: Full monitoring suite
- npm run docker🐚 Interactive shell

Usage:
  ./scripts/docker-monitor.sh usage
  ./scripts/docker-monitor.sh analyze user-deep-dive --user 29
  ./scripts/docker-monitor.sh monitor-all --save
  ./scripts/docker-monitor.sh get-reports ./reports
2026-01-23 14:31:24 +01:00
Johannes Millan
5027b31431 feat(supersync): add comprehensive storage monitoring and analysis toolkit
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.
2026-01-23 14:31:24 +01:00
Johannes Millan
2c429d77b9
Merge pull request #6087 from super-productivity/dependabot/npm_and_yarn/multi-982254d4fd
chore(deps): bump nodemailer and @types/nodemailer
2026-01-21 15:26:53 +01:00
dependabot[bot]
8c64f6099f
chore(deps): bump nodemailer and @types/nodemailer
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) and [@types/nodemailer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/nodemailer). These dependencies needed to be updated together.

Updates `nodemailer` from 7.0.11 to 7.0.12
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v7.0.11...v7.0.12)

Updates `@types/nodemailer` from 7.0.4 to 7.0.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/nodemailer)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-version: 7.0.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: "@types/nodemailer"
  dependency-version: 7.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-21 13:43:30 +00:00
dependabot[bot]
45265f915a
chore(deps): bump zod from 4.1.13 to 4.3.5
Bumps [zod](https://github.com/colinhacks/zod) from 4.1.13 to 4.3.5.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v4.1.13...v4.3.5)

---
updated-dependencies:
- dependency-name: zod
  dependency-version: 4.3.5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-21 13:41:42 +00:00
Johannes Millan
4cee57db14 fix(sync-server): fix SimpleWebAuthn v13 type imports
Import types from @simplewebauthn/server instead of deprecated
@simplewebauthn/types package which is no longer supported in v13.
2026-01-02 22:00:10 +01:00
Johannes Millan
f143210cd9 fix(sync-server): update SimpleWebAuthn to v13 and add debug logging
- 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.
2026-01-02 21:58:49 +01:00
Johannes Millan
9c0a728ef4 feat(sync-server): replace password auth with passkey + magic link
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
2026-01-02 16:52:48 +01:00
Johannes Millan
8a449fb944 fix(sync-server): compile scripts for production Docker image
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.
2025-12-19 15:58:21 +01:00
Johannes Millan
f056e1224c feat(sync-server): add GHCR-based deployment workflow
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
2025-12-19 15:24:20 +01:00
Johannes Millan
d46dab3d2e chore(sync-server): update npm scripts and expand legal docs
- 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
2025-12-15 13:47:42 +01:00
Johannes Millan
7479a37a33 build(superSync): add deploy script 2025-12-12 20:48:40 +01:00
Johannes Millan
2c42cf65cb feat(super-sync-server): Add basic monitoring tool
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.
2025-12-12 20:48:40 +01:00
Johannes Millan
2a4dbd7ad0 fix(superSync): Update admin scripts and README for Postgres compatibility
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.
2025-12-12 20:48:40 +01:00
Johannes Millan
b6fc65831c feat(superSync): implement prisma and postgres 2025-12-12 20:48:38 +01:00
Johannes Millan
8dc8207da2 feat(sync): add shared schema versioning package for frontend/backend
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.
2025-12-12 20:47:44 +01:00
Johannes Millan
9a2f972e4e feat(syncServer): add script to clear sync data for users 2025-12-12 20:46:25 +01:00
Johannes Millan
75c66a243f feat(super-sync-server): fix docs, add tests, and optimize snapshots
- 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.
2025-12-12 20:46:23 +01:00
Johannes Millan
c87e7ec218 refactor(sync): use uuidv7 library for UUID generation
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.
2025-12-12 20:46:19 +01:00
Johannes Millan
87e8f4b1a1 refactor(sync-server): remove WebDAV, use REST API for operation sync only
- 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
2025-12-12 20:46:15 +01:00
Johannes Millan
da1e4dcada feat(syncServer): enhance user authentication with async bcrypt operations, add security headers, and implement health check endpoint 2025-12-12 20:46:05 +01:00
Johannes Millan
87f459f5e6 feat(syncServer): add rate limiting, enhance user registration with stronger password validation and add verification token expiration 2025-12-12 20:46:05 +01:00
Johannes Millan
ec2de9c533 feat(syncServer): add Zod validation schemas for user registration, login, and email verification 2025-12-12 20:46:04 +01:00
Johannes Millan
4570ed965f feat(syncServer): add email verification route and user deletion script 2025-12-12 20:46:04 +01:00
Johannes Millan
6308e33a56 feat(syncServer): add SMTP email verification for user registration 2025-12-12 20:46:04 +01:00
Johannes Millan
93c76d5cdb feat(syncServer): implement JWT authentication and user registration/login functionality 2025-12-12 20:46:04 +01:00
Johannes Millan
180c5d70cc feat(syncServer): first draft 2025-12-12 20:46:04 +01:00