Note: This is a beta version and NOT ready for use in production.
Security
- Serve internal service messaging (WAMP) on a separate internal port and require a shared secret to connect
- Require a valid password along with the 2FA code when logging in
- Only allow password reset with tokens from the password reset flow
- Rotate refresh tokens on every use, and revoke the tokens of deleted accounts
- Require logging in again before resolving the keys of a password change that failed midway
- Block the CORS proxy from fetching internal addresses, and isolate it on its own network
- Validate the whole S3 object name
- Don't recreate revoked Inbox API keys
- Hide detailed sync errors in production
Sync
- Fix IDs being lost when moving them from unsynced to pending
- Record changes made during a full sync so they aren't missed afterwards
- Record pushed IDs in the same transaction as the pushed items
- Always commit changes in a transaction, and run transaction commands sequentially
- Don't fail a push that was already committed if updating the device's access time fails
- Fix monographs without an item ID only syncing during a full sync
- Register devices idempotently, and reject sync requests without a device ID
- Reject unknown push types
- Only remove sent IDs from pending instead of rewriting them, and record pushed IDs for all devices in one write
Accounts & storage
- Create the free subscription during signup, fixing "Failed to fetch user after signup"
- Reject concurrent duplicate signups
- Reserve storage quota atomically before uploading
- Delete all of a user's attachments when deleting or resetting an account (previously capped at 1,000)
- Clear revoked tokens from every replica's cache
Other
- Return errors through a shared exception handler: user-facing errors keep their messages, everything else is a 500 or 503 without internal details
- Create MongoDB indexes at startup
- Fix account endpoint bugs
- Send SSE events to clients concurrently
- Don't let publishing to internal services hang forever
- Reuse S3 and HTTP clients across requests
- Upgrade the MongoDB driver to 2.30
- Replace MinIO with Silo, an API-compatible fork, in the self-hosted setup
Upgrading
- Update all services together. Internal messaging moved to a separate port (each service's port + 1) and now requires a token derived from
NOTESNOOK_API_SECRET, so older and newer services can't talk to each other. - Indexes are created on first start. On a large database this may take a while in the background. If your data already has duplicate sync items, devices or user settings, the matching unique index can't be created; the API logs
Failed to create index ...and keeps running. - The S3 server is now Silo (
pgsty/silo). It reads the same data and keeps theMINIO_*variable names, so no changes to.envare needed. - The CORS proxy now runs on its own network. To also keep it away from your host and LAN, block private address ranges for its subnet in your host firewall (iptables
DOCKER-USERchain).
Test drive
wget https://raw.githubusercontent.com/streetwriters/notesnook-sync-server/v1.0-beta.40/docker-compose.yml
wget https://raw.githubusercontent.com/streetwriters/notesnook-sync-server/v1.0-beta.40/.env
docker compose upMake sure everything is up and running:
docker psAll the above services must show (healthy) in the output.
Full Changelog: v1.0-beta.39...v1.0-beta.40