cursedbelt-server 4.11.1 → 4.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/_bunOnly.d.ts +1 -0
- package/dist/server/_bunOnly.js +12 -0
- package/dist/server/activity/index.d.ts +4 -4
- package/dist/server/activity/index.js +3 -3
- package/dist/server/activity/migrations.d.ts +1 -1
- package/dist/server/activity/shareSource.d.ts +1 -1
- package/dist/server/activity/shareSource.js +1 -1
- package/dist/server/activity/store.js +2 -2
- package/dist/server/analytics/index.d.ts +2 -2
- package/dist/server/analytics/index.js +2 -2
- package/dist/server/app.d.ts +4 -4
- package/dist/server/app.js +6 -6
- package/dist/server/audit/index.d.ts +2 -2
- package/dist/server/audit/index.js +2 -2
- package/dist/server/audit/migrations.d.ts +1 -1
- package/dist/server/audit/sqliteSink.js +2 -2
- package/dist/server/audit/sqliteSink.test.js +1 -1
- package/dist/server/auth/csrf.js +1 -1
- package/dist/server/auth/fileTokenSigner.d.ts +1 -1
- package/dist/server/auth/getOnly.d.ts +1 -1
- package/dist/server/auth/getOnly.js +1 -1
- package/dist/server/auth/index.d.ts +12 -12
- package/dist/server/auth/index.js +11 -11
- package/dist/server/auth/jwt.d.ts +1 -1
- package/dist/server/auth/middleware.d.ts +1 -1
- package/dist/server/auth/middleware.js +3 -3
- package/dist/server/auth/sessionStore.d.ts +2 -2
- package/dist/server/auth/types.d.ts +1 -1
- package/dist/server/bench/assert.d.ts +1 -1
- package/dist/server/bench/assert.js +1 -1
- package/dist/server/bench/cpuBudget.d.ts +4 -4
- package/dist/server/bench/cpuBudget.js +3 -3
- package/dist/server/bench/index.d.ts +6 -6
- package/dist/server/bench/index.js +6 -6
- package/dist/server/bench/recorder.d.ts +2 -2
- package/dist/server/bench/recorder.js +1 -1
- package/dist/server/bench/runBench.d.ts +2 -2
- package/dist/server/ctgr.d.ts +1 -1
- package/dist/server/ctgr.js +1 -1
- package/dist/server/d1/fakeD1.d.ts +1 -1
- package/dist/server/d1/fakeD1.js +1 -1
- package/dist/server/d1/index.d.ts +8 -8
- package/dist/server/d1/index.js +8 -8
- package/dist/server/d1/invocation.d.ts +1 -1
- package/dist/server/d1/invocation.js +2 -2
- package/dist/server/d1/kysely.d.ts +2 -2
- package/dist/server/d1/kysely.js +2 -2
- package/dist/server/d1/limits.d.ts +1 -1
- package/dist/server/d1/limits.js +1 -1
- package/dist/server/d1/local.d.ts +1 -1
- package/dist/server/d1/local.js +3 -3
- package/dist/server/d1/localBackup.d.ts +1 -1
- package/dist/server/d1/localBackup.js +2 -2
- package/dist/server/d1/remote.d.ts +1 -1
- package/dist/server/d1/remote.js +3 -3
- package/dist/server/d1/scheduling.d.ts +1 -1
- package/dist/server/d1/values.d.ts +1 -1
- package/dist/server/d1/values.js +1 -1
- package/dist/server/db/kysely.d.ts +1 -1
- package/dist/server/dropzone/index.d.ts +2 -2
- package/dist/server/dropzone/index.js +2 -2
- package/dist/server/guard/argon2Binding.js +1 -1
- package/dist/server/guard/index.d.ts +5 -5
- package/dist/server/guard/index.js +5 -5
- package/dist/server/guard/kdfWorker.d.ts +1 -1
- package/dist/server/guard/kdfWorker.js +3 -3
- package/dist/server/guard/kdfWorkerEntry.js +1 -1
- package/dist/server/guard/passwordVerifier.js +1 -1
- package/dist/server/guard/sessionSigner.d.ts +2 -2
- package/dist/server/guard/sessionSigner.js +1 -1
- package/dist/server/incidents/checks.d.ts +2 -2
- package/dist/server/incidents/index.d.ts +8 -8
- package/dist/server/incidents/index.js +8 -8
- package/dist/server/incidents/migrations.d.ts +1 -1
- package/dist/server/incidents/notifier.d.ts +3 -3
- package/dist/server/incidents/reporter.d.ts +1 -1
- package/dist/server/incidents/routes.d.ts +4 -4
- package/dist/server/incidents/routes.js +1 -1
- package/dist/server/incidents/store.d.ts +1 -1
- package/dist/server/incidents/store.js +3 -3
- package/dist/server/index.d.ts +26 -26
- package/dist/server/index.js +23 -23
- package/dist/server/jobs/fireQueue.d.ts +1 -1
- package/dist/server/jobs/fireQueue.js +3 -3
- package/dist/server/jobs/index.d.ts +7 -7
- package/dist/server/jobs/index.js +7 -7
- package/dist/server/jobs/logger.d.ts +1 -1
- package/dist/server/jobs/polling.d.ts +1 -1
- package/dist/server/jobs/polling.js +1 -1
- package/dist/server/jobs/runner.d.ts +1 -1
- package/dist/server/jobs/runner.js +5 -5
- package/dist/server/master-lock/accountsPage.d.ts +1 -1
- package/dist/server/master-lock/accountsPage.js +1 -1
- package/dist/server/master-lock/guard.d.ts +2 -2
- package/dist/server/master-lock/guard.js +2 -2
- package/dist/server/master-lock/index.d.ts +7 -7
- package/dist/server/master-lock/index.js +7 -7
- package/dist/server/master-lock/masterLock.d.ts +26 -49
- package/dist/server/master-lock/masterLock.js +48 -15
- package/dist/server/master-lock/principals.d.ts +1 -1
- package/dist/server/master-lock/principals.js +1 -1
- package/dist/server/master-lock/seed.d.ts +1 -1
- package/dist/server/master-lock/seed.js +1 -1
- package/dist/server/master-lock/store.d.ts +6 -1
- package/dist/server/master-lock/store.js +5 -0
- package/dist/server/media-bun/index.d.ts +3 -3
- package/dist/server/media-bun/index.js +3 -3
- package/dist/server/media-bun/video.d.ts +1 -1
- package/dist/server/media-bun/video.js +1 -1
- package/dist/server/metrics/telemetrySink.d.ts +1 -1
- package/dist/server/metrics/telemetrySink.js +1 -1
- package/dist/server/middleware/correlationId.d.ts +1 -1
- package/dist/server/middleware/errorEnvelope.d.ts +1 -1
- package/dist/server/middleware/errorEnvelope.js +1 -1
- package/dist/server/middleware/index.d.ts +10 -10
- package/dist/server/middleware/index.js +10 -10
- package/dist/server/middleware/rateLimit.js +1 -1
- package/dist/server/middleware/requestLogger.d.ts +3 -3
- package/dist/server/middleware/requestLogger.js +3 -3
- package/dist/server/middleware/zValidator.d.ts +1 -1
- package/dist/server/middleware/zValidator.js +1 -1
- package/dist/server/migration/runner.d.ts +1 -1
- package/dist/server/net/outboundGuard.js +1 -1
- package/dist/server/notifications/index.d.ts +7 -7
- package/dist/server/notifications/index.js +4 -4
- package/dist/server/notifications/migrations.d.ts +1 -1
- package/dist/server/notifications/routes.d.ts +1 -1
- package/dist/server/notifications/service.d.ts +1 -1
- package/dist/server/notifications/service.js +2 -2
- package/dist/server/resume/index.d.ts +2 -2
- package/dist/server/resume/index.js +2 -2
- package/dist/server/resume/routes.d.ts +1 -1
- package/dist/server/resume/routes.js +1 -1
- package/dist/server/retention/archive.js +1 -1
- package/dist/server/retention/fleet.d.ts +2 -2
- package/dist/server/retention/fleet.js +2 -2
- package/dist/server/retention/index.d.ts +6 -6
- package/dist/server/retention/index.js +6 -6
- package/dist/server/retention/store.d.ts +1 -1
- package/dist/server/retention/store.js +2 -2
- package/dist/server/retention/sweeper.d.ts +3 -3
- package/dist/server/retention/sweeper.js +2 -2
- package/dist/server/retention/target.d.ts +3 -3
- package/dist/server/retention/target.js +2 -2
- package/dist/server/search/index.d.ts +2 -2
- package/dist/server/search/index.js +2 -2
- package/dist/server/search/pgSearchProvider.js +2 -2
- package/dist/server/search/pgSearchProvider.pg.test.js +2 -2
- package/dist/server/sharing/index.d.ts +8 -8
- package/dist/server/sharing/index.js +5 -5
- package/dist/server/sharing/migrations.d.ts +1 -1
- package/dist/server/sharing/router.d.ts +1 -1
- package/dist/server/sharing/sql.js +1 -1
- package/dist/server/sharing/store.js +3 -3
- package/dist/server/sqlite/browse.js +1 -1
- package/dist/server/sqlite/export.js +1 -1
- package/dist/server/sqlite/import.js +1 -1
- package/dist/server/sqlite/index.d.ts +9 -9
- package/dist/server/sqlite/index.js +9 -9
- package/dist/server/sqlite/stats.js +1 -1
- package/dist/server/sqlite/viewer.js +2 -2
- package/dist/server/storage/binaryServerProcessing.d.ts +1 -1
- package/dist/server/storage/binaryServerProcessing.js +2 -2
- package/dist/server/storage/binaryServerStore.d.ts +2 -2
- package/dist/server/storage/binaryStore.d.ts +1 -1
- package/dist/server/storage/binaryStoreFake.d.ts +1 -1
- package/dist/server/storage/diskStore.d.ts +1 -1
- package/dist/server/storage/files/adapter.d.ts +4 -4
- package/dist/server/storage/files/adapter.js +1 -1
- package/dist/server/storage/files/catalogue.d.ts +3 -3
- package/dist/server/storage/files/catalogue.js +6 -6
- package/dist/server/storage/files/chunkedUpload.d.ts +3 -3
- package/dist/server/storage/files/chunkedUpload.js +1 -1
- package/dist/server/storage/files/fileRoutes.d.ts +4 -4
- package/dist/server/storage/files/fileRoutes.js +3 -3
- package/dist/server/storage/files/index.d.ts +9 -9
- package/dist/server/storage/files/index.js +8 -8
- package/dist/server/storage/files/migrations.d.ts +1 -1
- package/dist/server/storage/files/stack.d.ts +7 -7
- package/dist/server/storage/files/stack.js +10 -10
- package/dist/server/storage/files/storageOps.d.ts +1 -1
- package/dist/server/storage/files/types.d.ts +1 -1
- package/dist/server/storage/imageThumbnail.js +1 -1
- package/dist/server/storage/index.d.ts +15 -15
- package/dist/server/storage/index.js +14 -14
- package/dist/server/storage/mountMediaRoutes.d.ts +3 -3
- package/dist/server/storage/mountMediaRoutes.js +2 -2
- package/dist/server/storage/objectStoreMediaStore.d.ts +1 -1
- package/dist/server/storage/s3ObjectStore.js +1 -1
- package/dist/server/storage/sources.d.ts +2 -2
- package/dist/server/storage/sources.js +2 -2
- package/dist/server/storage/streamRange.d.ts +1 -1
- package/dist/server/storage/streamToken.js +1 -1
- package/dist/server/storage/videoProcessor.d.ts +1 -1
- package/dist/server/storage/videoProcessor.js +2 -2
- package/dist/server/sync/engine.d.ts +2 -2
- package/dist/server/sync/engine.js +1 -1
- package/dist/server/sync/http.d.ts +4 -4
- package/dist/server/sync/http.js +3 -3
- package/dist/server/sync/index.d.ts +11 -11
- package/dist/server/sync/index.js +11 -11
- package/dist/server/sync/opLog.d.ts +1 -1
- package/dist/server/sync/signal.d.ts +1 -1
- package/dist/server/sync/timer.d.ts +3 -3
- package/dist/server/sync/timer.js +1 -1
- package/dist/server/ws/eventBus.d.ts +1 -1
- package/dist/server/ws/hub.d.ts +1 -1
- package/dist/server/ws/hub.js +3 -3
- package/dist/server/ws/index.d.ts +5 -5
- package/dist/server/ws/index.js +4 -4
- package/dist/server/ws/presence.d.ts +1 -1
- package/dist/server/ws/room.d.ts +1 -1
- package/dist/server/ws/types.d.ts +1 -1
- package/package.json +9 -9
- package/src/publicSurface.spec.ts +1 -1
- package/src/server/_bunOnly.ts +15 -0
- package/src/server/activity/index.ts +4 -4
- package/src/server/activity/migrations.ts +1 -1
- package/src/server/activity/shareSource.ts +2 -2
- package/src/server/activity/store.spec.ts +3 -3
- package/src/server/activity/store.ts +2 -2
- package/src/server/analytics/index.ts +2 -2
- package/src/server/analytics/injectedScripts.spec.ts +3 -3
- package/src/server/analytics/webAnalytics.spec.ts +1 -1
- package/src/server/app.spec.ts +9 -9
- package/src/server/app.ts +7 -7
- package/src/server/audit/index.ts +2 -2
- package/src/server/audit/migrations.ts +1 -1
- package/src/server/audit/sqliteSink.test.ts +1 -1
- package/src/server/audit/sqliteSink.ts +2 -2
- package/src/server/auth/cookie.spec.ts +1 -1
- package/src/server/auth/csrf.spec.ts +1 -1
- package/src/server/auth/csrf.ts +1 -1
- package/src/server/auth/fileTokenSigner.ts +1 -1
- package/src/server/auth/getOnly.spec.ts +2 -2
- package/src/server/auth/getOnly.ts +2 -2
- package/src/server/auth/index.ts +12 -12
- package/src/server/auth/jwt.spec.ts +2 -2
- package/src/server/auth/jwt.ts +1 -1
- package/src/server/auth/loginThrottle.spec.ts +1 -1
- package/src/server/auth/middleware.spec.ts +7 -7
- package/src/server/auth/middleware.ts +4 -4
- package/src/server/auth/password.spec.ts +1 -1
- package/src/server/auth/sessionStore.spec.ts +3 -3
- package/src/server/auth/sessionStore.ts +3 -3
- package/src/server/auth/totp.spec.ts +1 -1
- package/src/server/auth/types.ts +1 -1
- package/src/server/auth/vault.spec.ts +1 -1
- package/src/server/bench/assert.ts +2 -2
- package/src/server/bench/budget.spec.ts +2 -2
- package/src/server/bench/cpuBudget.spec.ts +6 -6
- package/src/server/bench/cpuBudget.ts +5 -5
- package/src/server/bench/cpuClock.spec.ts +2 -2
- package/src/server/bench/index.ts +6 -6
- package/src/server/bench/recorder.ts +2 -2
- package/src/server/bench/runBench.ts +2 -2
- package/src/server/ctgr.spec.ts +2 -2
- package/src/server/ctgr.ts +2 -2
- package/src/server/d1/backup.spec.ts +2 -2
- package/src/server/d1/fakeD1.ts +2 -2
- package/src/server/d1/index.ts +8 -8
- package/src/server/d1/invocation.spec.ts +6 -6
- package/src/server/d1/invocation.ts +2 -2
- package/src/server/d1/kysely.spec.ts +5 -5
- package/src/server/d1/kysely.ts +3 -3
- package/src/server/d1/limits.spec.ts +3 -3
- package/src/server/d1/limits.ts +1 -1
- package/src/server/d1/local.ts +3 -3
- package/src/server/d1/localBackup.ts +3 -3
- package/src/server/d1/remote.ts +3 -3
- package/src/server/d1/sameShape.spec.ts +4 -4
- package/src/server/d1/scheduling.spec.ts +1 -1
- package/src/server/d1/scheduling.ts +1 -1
- package/src/server/d1/values.ts +1 -1
- package/src/server/db/kysely.spec.ts +1 -1
- package/src/server/db/kysely.ts +1 -1
- package/src/server/dropzone/index.ts +2 -2
- package/src/server/dropzone/scan.spec.ts +1 -1
- package/src/server/errors.spec.ts +1 -1
- package/src/server/guard/argon2Binding.spec.ts +1 -1
- package/src/server/guard/argon2Binding.ts +1 -1
- package/src/server/guard/argon2Kat.spec.ts +1 -1
- package/src/server/guard/guard.spec.ts +3 -3
- package/src/server/guard/index.ts +5 -5
- package/src/server/guard/kdfWorker.spec.ts +3 -3
- package/src/server/guard/kdfWorker.ts +3 -3
- package/src/server/guard/kdfWorkerEntry.ts +1 -1
- package/src/server/guard/passwordVerifier.spec.ts +1 -1
- package/src/server/guard/passwordVerifier.ts +1 -1
- package/src/server/guard/revocationStore.spec.ts +2 -2
- package/src/server/guard/sessionSigner.ts +3 -3
- package/src/server/incidents/checks.ts +2 -2
- package/src/server/incidents/incidents.spec.ts +7 -7
- package/src/server/incidents/index.ts +8 -8
- package/src/server/incidents/migrations.ts +1 -1
- package/src/server/incidents/notifier.ts +3 -3
- package/src/server/incidents/reporter.ts +1 -1
- package/src/server/incidents/routes.ts +5 -5
- package/src/server/incidents/store.ts +3 -3
- package/src/server/index.ts +26 -26
- package/src/server/jobs/fireQueue.spec.ts +1 -1
- package/src/server/jobs/fireQueue.ts +3 -3
- package/src/server/jobs/index.ts +7 -7
- package/src/server/jobs/logger.ts +1 -1
- package/src/server/jobs/plainjobAdapter.spec.ts +1 -1
- package/src/server/jobs/polling.spec.ts +1 -1
- package/src/server/jobs/polling.ts +2 -2
- package/src/server/jobs/runner.spec.ts +3 -3
- package/src/server/jobs/runner.ts +5 -5
- package/src/server/jobs/timeout.spec.ts +1 -1
- package/src/server/master-lock/accounts.spec.ts +2 -2
- package/src/server/master-lock/accountsPage.spec.ts +4 -4
- package/src/server/master-lock/accountsPage.ts +1 -1
- package/src/server/master-lock/beaconNeverReachesTheWall.spec.ts +4 -4
- package/src/server/master-lock/guard.spec.ts +3 -3
- package/src/server/master-lock/guard.ts +3 -3
- package/src/server/master-lock/index.ts +8 -7
- package/src/server/master-lock/lockPage.spec.ts +2 -2
- package/src/server/master-lock/masterLock.spec.ts +59 -2
- package/src/server/master-lock/masterLock.ts +76 -14
- package/src/server/master-lock/principals.spec.ts +4 -4
- package/src/server/master-lock/principals.ts +1 -1
- package/src/server/master-lock/seed.spec.ts +3 -3
- package/src/server/master-lock/seed.ts +1 -1
- package/src/server/master-lock/store.ts +7 -1
- package/src/server/media-bun/image.spec.ts +1 -1
- package/src/server/media-bun/index.ts +3 -3
- package/src/server/media-bun/streaming.spec.ts +1 -1
- package/src/server/media-bun/video.spec.ts +1 -1
- package/src/server/media-bun/video.ts +1 -1
- package/src/server/metrics/normalizeRoute.spec.ts +1 -1
- package/src/server/metrics/telemetrySink.spec.ts +3 -3
- package/src/server/metrics/telemetrySink.ts +1 -1
- package/src/server/middleware/bodyLimit.spec.ts +1 -1
- package/src/server/middleware/correlationId.ts +1 -1
- package/src/server/middleware/corsAllowlist.spec.ts +2 -2
- package/src/server/middleware/errorEnvelope.ts +2 -2
- package/src/server/middleware/index.ts +10 -10
- package/src/server/middleware/localOrigin.spec.ts +1 -1
- package/src/server/middleware/rateLimit.spec.ts +1 -1
- package/src/server/middleware/rateLimit.ts +1 -1
- package/src/server/middleware/requestLogger.ts +5 -5
- package/src/server/middleware/zValidator.spec.ts +4 -4
- package/src/server/middleware/zValidator.ts +2 -2
- package/src/server/migration/runner.spec.ts +2 -2
- package/src/server/migration/runner.ts +1 -1
- package/src/server/net/outboundGuard.spec.ts +1 -1
- package/src/server/net/outboundGuard.ts +1 -1
- package/src/server/notifications/index.ts +7 -7
- package/src/server/notifications/migrations.ts +1 -1
- package/src/server/notifications/routes.ts +1 -1
- package/src/server/notifications/service.spec.ts +3 -3
- package/src/server/notifications/service.ts +2 -2
- package/src/server/paths/appDataHome.spec.ts +1 -1
- package/src/server/resume/index.ts +2 -2
- package/src/server/resume/resume.spec.ts +2 -2
- package/src/server/resume/routes.ts +1 -1
- package/src/server/retention/archive.spec.ts +2 -2
- package/src/server/retention/archive.ts +1 -1
- package/src/server/retention/fleet.ts +4 -4
- package/src/server/retention/index.ts +6 -6
- package/src/server/retention/policy.spec.ts +1 -1
- package/src/server/retention/store.spec.ts +3 -3
- package/src/server/retention/store.ts +3 -3
- package/src/server/retention/sweeper.spec.ts +5 -5
- package/src/server/retention/sweeper.ts +5 -5
- package/src/server/retention/target.spec.ts +3 -3
- package/src/server/retention/target.ts +5 -5
- package/src/server/search/index.ts +2 -2
- package/src/server/search/pgSearchProvider.pg.test.ts +2 -2
- package/src/server/search/pgSearchProvider.ts +2 -2
- package/src/server/sharing/index.ts +8 -8
- package/src/server/sharing/migrations.ts +1 -1
- package/src/server/sharing/router.spec.ts +2 -2
- package/src/server/sharing/router.ts +1 -1
- package/src/server/sharing/sql.ts +1 -1
- package/src/server/sharing/store.spec.ts +2 -2
- package/src/server/sharing/store.ts +3 -3
- package/src/server/sqlite/backup.spec.ts +1 -1
- package/src/server/sqlite/browse.spec.ts +1 -1
- package/src/server/sqlite/browse.ts +1 -1
- package/src/server/sqlite/export.spec.ts +2 -2
- package/src/server/sqlite/export.ts +1 -1
- package/src/server/sqlite/fts5.spec.ts +1 -1
- package/src/server/sqlite/health.spec.ts +1 -1
- package/src/server/sqlite/import.spec.ts +3 -3
- package/src/server/sqlite/import.ts +1 -1
- package/src/server/sqlite/index.ts +9 -9
- package/src/server/sqlite/readonlySql.spec.ts +1 -1
- package/src/server/sqlite/stats.spec.ts +1 -1
- package/src/server/sqlite/stats.ts +1 -1
- package/src/server/sqlite/viewer.spec.ts +1 -1
- package/src/server/sqlite/viewer.ts +2 -2
- package/src/server/storage/binaryServerProcessing.integration.spec.ts +2 -2
- package/src/server/storage/binaryServerProcessing.spec.ts +2 -2
- package/src/server/storage/binaryServerProcessing.ts +3 -3
- package/src/server/storage/binaryServerStore.ts +3 -3
- package/src/server/storage/binaryStore.spec.ts +2 -2
- package/src/server/storage/binaryStore.ts +1 -1
- package/src/server/storage/binaryStoreFake.ts +1 -1
- package/src/server/storage/chunked.integration.spec.ts +4 -4
- package/src/server/storage/diskStore.ts +1 -1
- package/src/server/storage/fileUploadClient-chunked.integration.spec.ts +6 -6
- package/src/server/storage/fileUploadClient.integration.spec.ts +7 -7
- package/src/server/storage/files/adapter.photo.display.spec.ts +10 -10
- package/src/server/storage/files/adapter.photo.spec.ts +9 -9
- package/src/server/storage/files/adapter.spec.ts +8 -8
- package/src/server/storage/files/adapter.ts +5 -5
- package/src/server/storage/files/catalogue.media-host.spec.ts +6 -6
- package/src/server/storage/files/catalogue.orderings.spec.ts +6 -6
- package/src/server/storage/files/catalogue.recover.spec.ts +5 -5
- package/src/server/storage/files/catalogue.sort.spec.ts +6 -6
- package/src/server/storage/files/catalogue.spec.ts +7 -7
- package/src/server/storage/files/catalogue.trash-import.spec.ts +6 -6
- package/src/server/storage/files/catalogue.ts +6 -6
- package/src/server/storage/files/chunkedUpload.spec.ts +7 -7
- package/src/server/storage/files/chunkedUpload.ts +4 -4
- package/src/server/storage/files/collections.spec.ts +6 -6
- package/src/server/storage/files/fileRoutes.replace.spec.ts +8 -8
- package/src/server/storage/files/fileRoutes.spec.ts +8 -8
- package/src/server/storage/files/fileRoutes.ts +6 -6
- package/src/server/storage/files/index.ts +9 -9
- package/src/server/storage/files/migrations.ts +1 -1
- package/src/server/storage/files/stack.spec.ts +5 -5
- package/src/server/storage/files/stack.ts +12 -12
- package/src/server/storage/files/storageOps.spec.ts +4 -4
- package/src/server/storage/files/storageOps.ts +1 -1
- package/src/server/storage/files/types.ts +1 -1
- package/src/server/storage/imageThumbnail.spec.ts +2 -2
- package/src/server/storage/imageThumbnail.ts +1 -1
- package/src/server/storage/index.ts +15 -15
- package/src/server/storage/mountMediaRoutes.ts +4 -4
- package/src/server/storage/objectStore.spec.ts +1 -1
- package/src/server/storage/objectStoreMediaStore.ts +1 -1
- package/src/server/storage/s3ObjectStore.ts +1 -1
- package/src/server/storage/sources.ts +3 -3
- package/src/server/storage/storage.spec.ts +6 -6
- package/src/server/storage/streamRange.ts +1 -1
- package/src/server/storage/streamToken.ts +1 -1
- package/src/server/storage/transcodeJobs.spec.ts +1 -1
- package/src/server/storage/videoDerivativeKeys.spec.ts +1 -1
- package/src/server/storage/videoProcessor.posterOnly.spec.ts +4 -4
- package/src/server/storage/videoProcessor.ts +2 -2
- package/src/server/sync/alarm.spec.ts +1 -1
- package/src/server/sync/commands.spec.ts +1 -1
- package/src/server/sync/engine.spec.ts +4 -4
- package/src/server/sync/engine.ts +2 -2
- package/src/server/sync/http.ts +5 -5
- package/src/server/sync/httpRemote.spec.ts +1 -1
- package/src/server/sync/index.ts +11 -11
- package/src/server/sync/opLog.spec.ts +1 -1
- package/src/server/sync/opLog.ts +1 -1
- package/src/server/sync/planner.spec.ts +1 -1
- package/src/server/sync/signal.spec.ts +1 -1
- package/src/server/sync/signal.ts +1 -1
- package/src/server/sync/status.spec.ts +1 -1
- package/src/server/sync/timer.spec.ts +3 -3
- package/src/server/sync/timer.ts +3 -3
- package/src/server/sync/tokens.spec.ts +1 -1
- package/src/server/ws/eventBus.spec.ts +2 -2
- package/src/server/ws/eventBus.ts +1 -1
- package/src/server/ws/hub.integration.spec.ts +5 -5
- package/src/server/ws/hub.spec.ts +3 -3
- package/src/server/ws/hub.ts +4 -4
- package/src/server/ws/index.ts +5 -5
- package/src/server/ws/presence.spec.ts +3 -3
- package/src/server/ws/presence.ts +1 -1
- package/src/server/ws/room.spec.ts +2 -2
- package/src/server/ws/room.ts +1 -1
- package/src/server/ws/types.ts +1 -1
- package/src/testTmpRoot.spec.ts +1 -1
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* only be watching one of them.
|
|
34
34
|
*/
|
|
35
35
|
import { MASTER_LOCK_PATHS, MASTER_LOCK_PREFIX } from "cursedbelt-core/master-lock";
|
|
36
|
-
import { MASTER_LOCK_DERIVE_SOURCE } from "./lockPage";
|
|
36
|
+
import { MASTER_LOCK_DERIVE_SOURCE } from "./lockPage.js";
|
|
37
37
|
/**
|
|
38
38
|
* The page's own two assets.
|
|
39
39
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type LockPageOptions } from "./lockPage";
|
|
2
|
-
import type { MasterLock } from "./masterLock";
|
|
1
|
+
import { type LockPageOptions } from "./lockPage.js";
|
|
2
|
+
import type { MasterLock } from "./masterLock.js";
|
|
3
3
|
export interface MasterLockGuardOptions extends LockPageOptions {
|
|
4
4
|
/**
|
|
5
5
|
* The lock this guard enforces.
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* second wall, not a replacement for the first.
|
|
13
13
|
*/
|
|
14
14
|
import { MASTER_LOCK_PATHS, MASTER_LOCK_PREFIX, MASTER_LOCK_STATE_HEADER, masterLockCookieName, } from "cursedbelt-core/master-lock";
|
|
15
|
-
import { MASTER_LOCK_ACCOUNTS_PAGE_PATHS, MASTER_LOCK_ACCOUNTS_SCRIPT, MASTER_LOCK_ACCOUNTS_STYLE, accountsPageHtml, } from "./accountsPage";
|
|
16
|
-
import { LOCK_SCRIPT, LOCK_STYLE, lockPageHtml } from "./lockPage";
|
|
15
|
+
import { MASTER_LOCK_ACCOUNTS_PAGE_PATHS, MASTER_LOCK_ACCOUNTS_SCRIPT, MASTER_LOCK_ACCOUNTS_STYLE, accountsPageHtml, } from "./accountsPage.js";
|
|
16
|
+
import { LOCK_SCRIPT, LOCK_STYLE, lockPageHtml } from "./lockPage.js";
|
|
17
17
|
const noStore = { "cache-control": "no-store, no-cache, must-revalidate", pragma: "no-cache" };
|
|
18
18
|
/**
|
|
19
19
|
* The lock page's own CSP. Strict enough to stand in front of `apps/vault`'s wall without
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
* server-rendered surface under `/__lock/` reaches every app that mounts the guard with no
|
|
21
21
|
* bundle, no framework version to migrate, and no app-local copy to drift.
|
|
22
22
|
*/
|
|
23
|
-
export { MASTER_LOCK_ACCOUNTS_PAGE_PATHS, MASTER_LOCK_ACCOUNTS_SCRIPT, MASTER_LOCK_ACCOUNTS_STYLE, MASTER_LOCK_MIN_PASSWORD_LENGTH, accountsPageHtml, } from "./accountsPage";
|
|
24
|
-
export { MASTER_LOCK_CSP, type MasterLockGuard, type MasterLockGuardOptions, createMasterLockGuard, } from "./guard";
|
|
25
|
-
export { LOCK_SCRIPT, LOCK_STYLE, MASTER_LOCK_DERIVE_SOURCE, type LockPageOptions, lockPageHtml, } from "./lockPage";
|
|
26
|
-
export { MASTER_LOCK_PRINCIPAL_KEY_PREFIX, MasterLockDirectory, type MasterLockDirectoryOptions, masterLockPrincipalKey, } from "./principals";
|
|
27
|
-
export { FIRST_ACCOUNT_ID, MasterLock, type MasterLockAccount, type MasterLockAddAccountResult, type MasterLockEnrollResult, type MasterLockOptions, type MasterLockRecord, type MasterLockStore, type MasterLockUnlockResult, readRecord, } from "./masterLock";
|
|
28
|
-
export { DEFAULT_SEED_IDLE_MS, generateStagePassword, type MintMasterLockSeedOptions, mintMasterLockSeed, serializeMasterLockSeed, } from "./seed";
|
|
29
|
-
export { MASTER_LOCK_SETTING_KEY, createKvMasterLockStore, createMemoryMasterLockStore, } from "./store";
|
|
23
|
+
export { MASTER_LOCK_ACCOUNTS_PAGE_PATHS, MASTER_LOCK_ACCOUNTS_SCRIPT, MASTER_LOCK_ACCOUNTS_STYLE, MASTER_LOCK_MIN_PASSWORD_LENGTH, accountsPageHtml, } from "./accountsPage.js";
|
|
24
|
+
export { MASTER_LOCK_CSP, type MasterLockGuard, type MasterLockGuardOptions, createMasterLockGuard, } from "./guard.js";
|
|
25
|
+
export { LOCK_SCRIPT, LOCK_STYLE, MASTER_LOCK_DERIVE_SOURCE, type LockPageOptions, lockPageHtml, } from "./lockPage.js";
|
|
26
|
+
export { MASTER_LOCK_PRINCIPAL_KEY_PREFIX, MasterLockDirectory, type MasterLockDirectoryOptions, masterLockPrincipalKey, } from "./principals.js";
|
|
27
|
+
export { FIRST_ACCOUNT_ID, MasterLock, type MasterLockAccount, type MasterLockAddAccountResult, type MasterLockEnrollResult, type MasterLockOptions, type MasterLockRecord, type MasterLockStore, type MasterLockUnlockResult, readRecord, } from "./masterLock.js";
|
|
28
|
+
export { DEFAULT_SEED_IDLE_MS, generateStagePassword, type MintMasterLockSeedOptions, mintMasterLockSeed, serializeMasterLockSeed, } from "./seed.js";
|
|
29
|
+
export { MASTER_LOCK_SETTING_KEY, MASTER_LOCK_STATE_KEY, createKvMasterLockStore, createMemoryMasterLockStore, } from "./store.js";
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
* server-rendered surface under `/__lock/` reaches every app that mounts the guard with no
|
|
21
21
|
* bundle, no framework version to migrate, and no app-local copy to drift.
|
|
22
22
|
*/
|
|
23
|
-
export { MASTER_LOCK_ACCOUNTS_PAGE_PATHS, MASTER_LOCK_ACCOUNTS_SCRIPT, MASTER_LOCK_ACCOUNTS_STYLE, MASTER_LOCK_MIN_PASSWORD_LENGTH, accountsPageHtml, } from "./accountsPage";
|
|
24
|
-
export { MASTER_LOCK_CSP, createMasterLockGuard, } from "./guard";
|
|
25
|
-
export { LOCK_SCRIPT, LOCK_STYLE, MASTER_LOCK_DERIVE_SOURCE, lockPageHtml, } from "./lockPage";
|
|
26
|
-
export { MASTER_LOCK_PRINCIPAL_KEY_PREFIX, MasterLockDirectory, masterLockPrincipalKey, } from "./principals";
|
|
27
|
-
export { FIRST_ACCOUNT_ID, MasterLock, readRecord, } from "./masterLock";
|
|
28
|
-
export { DEFAULT_SEED_IDLE_MS, generateStagePassword, mintMasterLockSeed, serializeMasterLockSeed, } from "./seed";
|
|
29
|
-
export { MASTER_LOCK_SETTING_KEY, createKvMasterLockStore, createMemoryMasterLockStore, } from "./store";
|
|
23
|
+
export { MASTER_LOCK_ACCOUNTS_PAGE_PATHS, MASTER_LOCK_ACCOUNTS_SCRIPT, MASTER_LOCK_ACCOUNTS_STYLE, MASTER_LOCK_MIN_PASSWORD_LENGTH, accountsPageHtml, } from "./accountsPage.js";
|
|
24
|
+
export { MASTER_LOCK_CSP, createMasterLockGuard, } from "./guard.js";
|
|
25
|
+
export { LOCK_SCRIPT, LOCK_STYLE, MASTER_LOCK_DERIVE_SOURCE, lockPageHtml, } from "./lockPage.js";
|
|
26
|
+
export { MASTER_LOCK_PRINCIPAL_KEY_PREFIX, MasterLockDirectory, masterLockPrincipalKey, } from "./principals.js";
|
|
27
|
+
export { FIRST_ACCOUNT_ID, MasterLock, readRecord, } from "./masterLock.js";
|
|
28
|
+
export { DEFAULT_SEED_IDLE_MS, generateStagePassword, mintMasterLockSeed, serializeMasterLockSeed, } from "./seed.js";
|
|
29
|
+
export { MASTER_LOCK_SETTING_KEY, MASTER_LOCK_STATE_KEY, createKvMasterLockStore, createMemoryMasterLockStore, } from "./store.js";
|
|
@@ -1,52 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The sitewide MASTER LOCK — a second wall, in front of a whole app, that the app's own
|
|
3
|
-
* sign-in cannot open.
|
|
4
|
-
*
|
|
5
|
-
* ── What the owner asked for (2026-08-15, their words) ──────────────────────
|
|
6
|
-
* *"I want to be able to share my laptop without certain apps being at risk of other people
|
|
7
|
-
* viewing them while I am still logged in … Until the master password is entered a user
|
|
8
|
-
* logged in as me cannot see anything about the site, not even text or images, nothing at
|
|
9
|
-
* all."*
|
|
10
|
-
*
|
|
11
|
-
* So: standard auth still happens FIRST and is unchanged. This sits behind it. A request
|
|
12
|
-
* that has passed the app's own gate and carries no live unlock is answered with the lock
|
|
13
|
-
* page (for a document) or a 401 (for anything else) — never with the app.
|
|
14
|
-
*
|
|
15
|
-
* ── 🔴 BE HONEST ABOUT WHAT THIS BUYS ───────────────────────────────────────
|
|
16
|
-
* In `apps/vault` the master password IS the encryption key: the server holds ciphertext
|
|
17
|
-
* and a total breach yields noise. **This cannot work that way, and must never be described
|
|
18
|
-
* as if it does.** The apps it guards serve their bytes to browsers; those bytes are
|
|
19
|
-
* plaintext at rest by nature. This is a LOCK ON THE DOOR — an unlocked laptop, a borrowed
|
|
20
|
-
* phone, a hijacked session still cannot open the UI. The owner said the same thing back:
|
|
21
|
-
* *"I am aware that a tech savvy user of my laptop could still get around it by changing
|
|
22
|
-
* code. This work does not worry about that, we are only securing app UI access."*
|
|
23
|
-
* The same distinction is written in `fleet/rules/owner-uis-are-one-ui.md` and in
|
|
24
|
-
* binary-server's `src/admin/passcode.ts`, which is this feature's nearest relative.
|
|
25
|
-
*
|
|
26
|
-
* ── The four decisions that are not obvious ─────────────────────────────────
|
|
27
|
-
*
|
|
28
|
-
* **1. Sessions live in MEMORY, so a restart re-locks.** The correct default for a surface
|
|
29
|
-
* whose whole risk model is "the browser is somewhere it should not be". Same call as the
|
|
30
|
-
* inspector passcode.
|
|
31
|
-
*
|
|
32
|
-
* **2. The idle clock is slid by INTERACTION, never by traffic.** The owner said *"if I
|
|
33
|
-
* leave the site up but don't interact with it"* — and every app here polls. Sliding on any
|
|
34
|
-
* request would let a background refetch hold the lock open all night with nobody at the
|
|
35
|
-
* desk, which is exactly the scenario the feature exists for. So an ordinary request only
|
|
36
|
-
* READS the clock; `touch()` — reached solely by `POST /__lock/ping`, which the browser
|
|
37
|
-
* sends on real pointer/key/touch activity — is the only thing that moves it.
|
|
38
|
-
*
|
|
39
|
-
* **3. The password is never stored, and this process never sees it.** The browser derives
|
|
40
|
-
* `verifier = PBKDF2(KEK ‖ password)` (see `../../core/master-lock/kdf.ts`); the record
|
|
41
|
-
* holds `argon2id(verifier)`. It is seeded from the vault's OWN record so the owner's
|
|
42
|
-
* existing vault master password works on day one without anyone knowing it.
|
|
43
|
-
*
|
|
44
|
-
* **4. Every refusal is the same refusal.** Wrong verifier, throttled, unconfigured and
|
|
45
|
-
* "no unlock" answer with the identical status and body, and a dummy argon2 verify runs on
|
|
46
|
-
* every path so the TIMING does not separate them either. The one thing that varies is the
|
|
47
|
-
* `retryAfterMs` a throttled caller is told — which they already know, since they are the
|
|
48
|
-
* one who has been guessing.
|
|
49
|
-
*/
|
|
50
1
|
import { type MasterLockAccountSummary, type MasterLockKdfParams, type MasterLockStatus } from "cursedbelt-core/master-lock";
|
|
51
2
|
/**
|
|
52
3
|
* ONE master password, and therefore one TENANT of the app behind it.
|
|
@@ -127,8 +78,29 @@ export interface MasterLockStore {
|
|
|
127
78
|
read(): string | null;
|
|
128
79
|
write(json: string): void;
|
|
129
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Where the LIVE state goes when the process that holds it does not live — the unlocks that are
|
|
83
|
+
* open and the throttle's failure count. Synchronous by the same contract as
|
|
84
|
+
* {@link MasterLockStore}, so a Worker satisfies it from its per-invocation snapshot exactly as
|
|
85
|
+
* it does the record.
|
|
86
|
+
*
|
|
87
|
+
* 🔴 Why it exists (2026-09-22, the night `collections` moved to a Worker): the lock kept its
|
|
88
|
+
* unlocks in a `Map` on the instance, and a Worker builds the instance once per REQUEST. The
|
|
89
|
+
* owner typed the right password, got a 200 and a cookie, and the very next request was locked
|
|
90
|
+
* again — measured on `collections-stage` by `worker-stage-walk.ts`. The throttle had the same
|
|
91
|
+
* shape: every guess met a fresh counter, so nothing slowed a brute force at all.
|
|
92
|
+
*
|
|
93
|
+
* Omitted (the Mac's daemons), the state stays in memory, exactly as before: a restart locks.
|
|
94
|
+
* Tokens are never stored — only their SHA-256, so a leaked row opens nothing.
|
|
95
|
+
*/
|
|
96
|
+
export interface MasterLockStateStore {
|
|
97
|
+
read(): string | null;
|
|
98
|
+
write(json: string): void;
|
|
99
|
+
}
|
|
130
100
|
export interface MasterLockOptions {
|
|
131
101
|
store: MasterLockStore;
|
|
102
|
+
/** See {@link MasterLockStateStore}. Required wherever the instance does not outlive a request. */
|
|
103
|
+
state?: MasterLockStateStore;
|
|
132
104
|
/**
|
|
133
105
|
* The BOOTSTRAP record, as JSON, used only when the store is empty — the same shape as
|
|
134
106
|
* {@link MasterLockRecord} with `idleMs` optional.
|
|
@@ -225,6 +197,7 @@ export declare class MasterLock {
|
|
|
225
197
|
* entered again"* — one button, every device.
|
|
226
198
|
*/
|
|
227
199
|
private sessions;
|
|
200
|
+
private readonly stateStore;
|
|
228
201
|
private expiryTimer;
|
|
229
202
|
private failures;
|
|
230
203
|
private lastFailureAt;
|
|
@@ -449,6 +422,10 @@ export declare class MasterLock {
|
|
|
449
422
|
private write;
|
|
450
423
|
/** Drop the in-memory unlock without notifying — for tests between cases. */
|
|
451
424
|
resetForTest(): void;
|
|
425
|
+
/** Adopt the persisted live state, if there is a store and it holds a readable one. */
|
|
426
|
+
private loadState;
|
|
427
|
+
/** Persist the live state — every mutation of it calls this, or a Worker forgets it. */
|
|
428
|
+
private saveState;
|
|
452
429
|
/** Retire a session whose idle window has passed. Called on every read of the state, so
|
|
453
430
|
* correctness never depends on the timer having fired. */
|
|
454
431
|
private sweep;
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
* `retryAfterMs` a throttled caller is told — which they already know, since they are the
|
|
48
48
|
* one who has been guessing.
|
|
49
49
|
*/
|
|
50
|
+
import { createHash } from "node:crypto";
|
|
51
|
+
import { constantTimeEqual } from "cwip/constant-time";
|
|
50
52
|
import { clampIdleMs, isMasterLockKdfParams, windowRemaining, } from "cursedbelt-core/master-lock";
|
|
51
53
|
/** The id a legacy single-password record migrates to. Fixed, because the app that adopts
|
|
52
54
|
* this stamps its existing rows with it — a random id would orphan the library it is
|
|
@@ -87,11 +89,14 @@ export class MasterLock {
|
|
|
87
89
|
* entered again"* — one button, every device.
|
|
88
90
|
*/
|
|
89
91
|
sessions = new Map();
|
|
92
|
+
stateStore = null;
|
|
90
93
|
expiryTimer = null;
|
|
91
94
|
failures = 0;
|
|
92
95
|
lastFailureAt = 0;
|
|
93
96
|
constructor(options) {
|
|
94
97
|
this.store = options.store;
|
|
98
|
+
this.stateStore = options.state ?? null;
|
|
99
|
+
this.loadState();
|
|
95
100
|
this.now = options.now ?? Date.now;
|
|
96
101
|
this.onLockedChange = options.onLockedChange;
|
|
97
102
|
this.log = options.log ?? (() => undefined);
|
|
@@ -220,7 +225,7 @@ export class MasterLock {
|
|
|
220
225
|
if (this.sessions.size === 0)
|
|
221
226
|
return null;
|
|
222
227
|
let found = null;
|
|
223
|
-
for (const presented of presentedTokens(req)) {
|
|
228
|
+
for (const presented of presentedTokens(req).map(tokenDigest)) {
|
|
224
229
|
for (const [live, session] of this.sessions) {
|
|
225
230
|
// No early `return`: every candidate is compared against every live token so
|
|
226
231
|
// the loop's duration does not say which cookie in the jar was the right one.
|
|
@@ -307,6 +312,7 @@ export class MasterLock {
|
|
|
307
312
|
}
|
|
308
313
|
this.failures += 1;
|
|
309
314
|
this.lastFailureAt = now;
|
|
315
|
+
this.saveState();
|
|
310
316
|
return { ok: false, retryAfterMs: windowRemaining(this.failures, this.lastFailureAt, now) };
|
|
311
317
|
}
|
|
312
318
|
return { ok: true, ...this.open(opened.id, now) };
|
|
@@ -322,7 +328,8 @@ export class MasterLock {
|
|
|
322
328
|
const wasLocked = this.sessions.size === 0;
|
|
323
329
|
// ADDED, never replacing: the desk and the phone are the same person and both stay
|
|
324
330
|
// open. See the `sessions` note.
|
|
325
|
-
this.sessions.set(token, { accountId, lastActivityAt: now });
|
|
331
|
+
this.sessions.set(tokenDigest(token), { accountId, lastActivityAt: now });
|
|
332
|
+
this.saveState();
|
|
326
333
|
this.scheduleExpiry();
|
|
327
334
|
if (wasLocked)
|
|
328
335
|
this.onLockedChange?.(false);
|
|
@@ -481,7 +488,7 @@ export class MasterLock {
|
|
|
481
488
|
// phone left on the counter locks on its own schedule while the desk stays open —
|
|
482
489
|
// which is decision 2 applied per device rather than per person.
|
|
483
490
|
let slid = false;
|
|
484
|
-
for (const presented of presentedTokens(req)) {
|
|
491
|
+
for (const presented of presentedTokens(req).map(tokenDigest)) {
|
|
485
492
|
for (const [live, session] of this.sessions) {
|
|
486
493
|
// No early `return`, for the reason `accountFor` gives: the loop's duration
|
|
487
494
|
// must not say which of the jar's cookies was this app's.
|
|
@@ -491,8 +498,10 @@ export class MasterLock {
|
|
|
491
498
|
}
|
|
492
499
|
}
|
|
493
500
|
}
|
|
494
|
-
if (slid)
|
|
501
|
+
if (slid) {
|
|
502
|
+
this.saveState();
|
|
495
503
|
this.scheduleExpiry();
|
|
504
|
+
}
|
|
496
505
|
return slid;
|
|
497
506
|
}
|
|
498
507
|
/** The manual lock — the owner's *"I want a lock option to turn the site back to needing
|
|
@@ -504,6 +513,7 @@ export class MasterLock {
|
|
|
504
513
|
// owner's requirement is "no one can see anything until the master password is
|
|
505
514
|
// entered again", and a lock that left the phone open would not be that.
|
|
506
515
|
this.sessions.clear();
|
|
516
|
+
this.saveState();
|
|
507
517
|
this.clearExpiry();
|
|
508
518
|
this.onLockedChange?.(true);
|
|
509
519
|
}
|
|
@@ -588,6 +598,33 @@ export class MasterLock {
|
|
|
588
598
|
this.lastFailureAt = 0;
|
|
589
599
|
this.clearExpiry();
|
|
590
600
|
}
|
|
601
|
+
/** Adopt the persisted live state, if there is a store and it holds a readable one. */
|
|
602
|
+
loadState() {
|
|
603
|
+
if (!this.stateStore)
|
|
604
|
+
return;
|
|
605
|
+
const raw = this.stateStore.read();
|
|
606
|
+
if (!raw)
|
|
607
|
+
return;
|
|
608
|
+
try {
|
|
609
|
+
const parsed = JSON.parse(raw);
|
|
610
|
+
if (parsed.v !== 1)
|
|
611
|
+
return;
|
|
612
|
+
for (const [digest, session] of parsed.sessions ?? []) {
|
|
613
|
+
if (typeof digest === "string" && typeof session?.accountId === "string" && Number.isFinite(session.lastActivityAt)) {
|
|
614
|
+
this.sessions.set(digest, { accountId: session.accountId, lastActivityAt: session.lastActivityAt });
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
this.failures = Number.isFinite(parsed.failures) ? Number(parsed.failures) : 0;
|
|
618
|
+
this.lastFailureAt = Number.isFinite(parsed.lastFailureAt) ? Number(parsed.lastFailureAt) : 0;
|
|
619
|
+
}
|
|
620
|
+
catch {
|
|
621
|
+
// Unreadable state is LOCKED state: nothing is open, which is the safe reading.
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
/** Persist the live state — every mutation of it calls this, or a Worker forgets it. */
|
|
625
|
+
saveState() {
|
|
626
|
+
this.stateStore?.write(JSON.stringify({ v: 1, sessions: [...this.sessions], failures: this.failures, lastFailureAt: this.lastFailureAt }));
|
|
627
|
+
}
|
|
591
628
|
/** Retire a session whose idle window has passed. Called on every read of the state, so
|
|
592
629
|
* correctness never depends on the timer having fired. */
|
|
593
630
|
sweep() {
|
|
@@ -596,11 +633,14 @@ export class MasterLock {
|
|
|
596
633
|
return;
|
|
597
634
|
const now = this.now();
|
|
598
635
|
const wasOpen = this.sessions.size > 0;
|
|
636
|
+
const before = this.sessions.size;
|
|
599
637
|
for (const [token, session] of this.sessions) {
|
|
600
638
|
// Each device expires on its OWN clock, so one going idle never shortens another.
|
|
601
639
|
if (now - session.lastActivityAt > record.idleMs)
|
|
602
640
|
this.sessions.delete(token);
|
|
603
641
|
}
|
|
642
|
+
if (this.sessions.size !== before)
|
|
643
|
+
this.saveState();
|
|
604
644
|
if (wasOpen && this.sessions.size === 0) {
|
|
605
645
|
this.clearExpiry();
|
|
606
646
|
this.onLockedChange?.(true);
|
|
@@ -791,6 +831,10 @@ async function equalize(candidate) {
|
|
|
791
831
|
equalizerHash ??= Bun.password.hash("master-lock-timing-equalizer", { algorithm: "argon2id" });
|
|
792
832
|
await Bun.password.verify(candidate || "x", await equalizerHash).catch(() => false);
|
|
793
833
|
}
|
|
834
|
+
/** What a session is KEYED by — never the token itself, so persisted state opens nothing. */
|
|
835
|
+
function tokenDigest(token) {
|
|
836
|
+
return createHash("sha256").update(token).digest("base64url");
|
|
837
|
+
}
|
|
794
838
|
function randomToken() {
|
|
795
839
|
const bytes = new Uint8Array(TOKEN_BYTES);
|
|
796
840
|
crypto.getRandomValues(bytes);
|
|
@@ -822,14 +866,3 @@ function presentedTokens(req) {
|
|
|
822
866
|
}
|
|
823
867
|
return out;
|
|
824
868
|
}
|
|
825
|
-
function constantTimeEqual(a, b) {
|
|
826
|
-
const x = Buffer.from(a);
|
|
827
|
-
const y = Buffer.from(b);
|
|
828
|
-
// A length difference is already a non-match, and `timingSafeEqual` throws on one.
|
|
829
|
-
if (x.length !== y.length)
|
|
830
|
-
return false;
|
|
831
|
-
let diff = 0;
|
|
832
|
-
for (let i = 0; i < x.length; i += 1)
|
|
833
|
-
diff |= x[i] ^ y[i];
|
|
834
|
-
return diff === 0;
|
|
835
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MasterLock } from "./masterLock";
|
|
1
|
+
import { MasterLock } from "./masterLock.js";
|
|
2
2
|
/** Namespace for every per-person record, so one glance at the table says what they are. */
|
|
3
3
|
export declare const MASTER_LOCK_PRINCIPAL_KEY_PREFIX = "master_lock:principal:";
|
|
4
4
|
/**
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* record is stored under, which is the only thing it ever really was.
|
|
47
47
|
*/
|
|
48
48
|
import { createHash } from "node:crypto";
|
|
49
|
-
import { MasterLock, readRecord } from "./masterLock";
|
|
49
|
+
import { MasterLock, readRecord } from "./masterLock.js";
|
|
50
50
|
/** Namespace for every per-person record, so one glance at the table says what they are. */
|
|
51
51
|
export const MASTER_LOCK_PRINCIPAL_KEY_PREFIX = "master_lock:principal:";
|
|
52
52
|
/**
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import { DEFAULT_IDLE_MS } from "cursedbelt-core/master-lock/policy";
|
|
26
26
|
import { deriveMasterLockVerifier, newMasterLockKdfParams, } from "cursedbelt-core/master-lock/kdf";
|
|
27
|
-
import { FIRST_ACCOUNT_ID } from "./masterLock";
|
|
27
|
+
import { FIRST_ACCOUNT_ID } from "./masterLock.js";
|
|
28
28
|
/**
|
|
29
29
|
* The idle window a freshly minted lock starts with.
|
|
30
30
|
*
|
|
@@ -6,9 +6,14 @@
|
|
|
6
6
|
* `app_settings`, a `Map` in a test. Asking for a whole table would be asking each adopter
|
|
7
7
|
* to write a migration for three fields.
|
|
8
8
|
*/
|
|
9
|
-
import type { MasterLockStore } from "./masterLock";
|
|
9
|
+
import type { MasterLockStore } from "./masterLock.js";
|
|
10
10
|
/** The default key, so two apps' rows look the same when somebody goes looking. */
|
|
11
11
|
export declare const MASTER_LOCK_SETTING_KEY = "master_lock:record";
|
|
12
|
+
/**
|
|
13
|
+
* The key the LIVE state (open unlocks, the throttle) is kept under, beside the record — see
|
|
14
|
+
* `MasterLockStateStore`. `createKvMasterLockStore(kv, MASTER_LOCK_STATE_KEY)` is that store.
|
|
15
|
+
*/
|
|
16
|
+
export declare const MASTER_LOCK_STATE_KEY = "master_lock:state";
|
|
12
17
|
/** Wrap an app's existing key/value settings surface. */
|
|
13
18
|
export declare function createKvMasterLockStore(kv: {
|
|
14
19
|
get(key: string): string | null | undefined;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/** The default key, so two apps' rows look the same when somebody goes looking. */
|
|
2
2
|
export const MASTER_LOCK_SETTING_KEY = "master_lock:record";
|
|
3
|
+
/**
|
|
4
|
+
* The key the LIVE state (open unlocks, the throttle) is kept under, beside the record — see
|
|
5
|
+
* `MasterLockStateStore`. `createKvMasterLockStore(kv, MASTER_LOCK_STATE_KEY)` is that store.
|
|
6
|
+
*/
|
|
7
|
+
export const MASTER_LOCK_STATE_KEY = "master_lock:state";
|
|
3
8
|
/** Wrap an app's existing key/value settings surface. */
|
|
4
9
|
export function createKvMasterLockStore(kv, key = MASTER_LOCK_SETTING_KEY) {
|
|
5
10
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { buildProbeArgs, buildThumbnailArgs, buildTrimArgs, ffmpegTimeToSeconds, type ProbeResult, parseFfmpegProgress, parseFfprobe, type VideoCodecPlan, videoCodecPlan, } from 'cursedbelt-core/media/ffmpeg';
|
|
2
|
-
export { renderImage } from './image';
|
|
3
|
-
export { aacWebAudioArgs, buildFrameJpegArgs, buildSpriteVtt, buildStreamProbeArgs, canStreamCopy, EMPTY_PROBE, FASTSTART, faststartArgs, h264WebVideoArgs, hlsLadderArgs, imageThumbnailArgs, LIBRARY_CRF, LIBRARY_SCALE, parseProgressMicros, parseStreamProbe, planSprite, posterArgs, resolveLadder, type SpritePlan, spriteArgs, type VideoProbe, } from './streaming';
|
|
4
|
-
export { extractFrameJpeg, extractThumbnail, isFfmpegAvailable, isFfprobeAvailable, probeMedia, probeVideoStream, runFfmpegProgress, trimVideo, } from './video';
|
|
2
|
+
export { renderImage } from './image.js';
|
|
3
|
+
export { aacWebAudioArgs, buildFrameJpegArgs, buildSpriteVtt, buildStreamProbeArgs, canStreamCopy, EMPTY_PROBE, FASTSTART, faststartArgs, h264WebVideoArgs, hlsLadderArgs, imageThumbnailArgs, LIBRARY_CRF, LIBRARY_SCALE, parseProgressMicros, parseStreamProbe, planSprite, posterArgs, resolveLadder, type SpritePlan, spriteArgs, type VideoProbe, } from './streaming.js';
|
|
4
|
+
export { extractFrameJpeg, extractThumbnail, isFfmpegAvailable, isFfprobeAvailable, probeMedia, probeVideoStream, runFfmpegProgress, trimVideo, } from './video.js';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// via native ffmpeg/ffprobe. App handlers keep auth, FsNode lookup, quota, and
|
|
4
4
|
// storeFile; this owns the actual pixel/codec work.
|
|
5
5
|
export { buildProbeArgs, buildThumbnailArgs, buildTrimArgs, ffmpegTimeToSeconds, parseFfmpegProgress, parseFfprobe, videoCodecPlan, } from 'cursedbelt-core/media/ffmpeg';
|
|
6
|
-
export { renderImage } from './image';
|
|
6
|
+
export { renderImage } from './image.js';
|
|
7
7
|
// Streaming pipeline: faststart remux, HLS adaptive-bitrate ladder, scrub sprite + WebVTT,
|
|
8
8
|
// poster, codec-aware probe — pure builders/parsers (testable without ffmpeg).
|
|
9
|
-
export { aacWebAudioArgs, buildFrameJpegArgs, buildSpriteVtt, buildStreamProbeArgs, canStreamCopy, EMPTY_PROBE, FASTSTART, faststartArgs, h264WebVideoArgs, hlsLadderArgs, imageThumbnailArgs, LIBRARY_CRF, LIBRARY_SCALE, parseProgressMicros, parseStreamProbe, planSprite, posterArgs, resolveLadder, spriteArgs, } from './streaming';
|
|
10
|
-
export { extractFrameJpeg, extractThumbnail, isFfmpegAvailable, isFfprobeAvailable, probeMedia, probeVideoStream, runFfmpegProgress, trimVideo, } from './video';
|
|
9
|
+
export { aacWebAudioArgs, buildFrameJpegArgs, buildSpriteVtt, buildStreamProbeArgs, canStreamCopy, EMPTY_PROBE, FASTSTART, faststartArgs, h264WebVideoArgs, hlsLadderArgs, imageThumbnailArgs, LIBRARY_CRF, LIBRARY_SCALE, parseProgressMicros, parseStreamProbe, planSprite, posterArgs, resolveLadder, spriteArgs, } from './streaming.js';
|
|
10
|
+
export { extractFrameJpeg, extractThumbnail, isFfmpegAvailable, isFfprobeAvailable, probeMedia, probeVideoStream, runFfmpegProgress, trimVideo, } from './video.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type VideoProgressEvent, type VideoTrimSpec } from 'cursedbelt-core/media';
|
|
2
2
|
import { type ProbeResult } from 'cursedbelt-core/media/ffmpeg';
|
|
3
|
-
import { type VideoProbe } from './streaming';
|
|
3
|
+
import { type VideoProbe } from './streaming.js';
|
|
4
4
|
/** Is ffmpeg runnable? Cheap probe used to skip server media ops / tests cleanly. */
|
|
5
5
|
export declare function isFfmpegAvailable(bin?: string): Promise<boolean>;
|
|
6
6
|
/** Is ffprobe runnable? */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// `FFMPEG_PATH` / `FFPROBE_PATH`. Replaces ca's hand-rolled spawn boilerplate.
|
|
5
5
|
import { assertValidVideoTrimSpec, } from 'cursedbelt-core/media';
|
|
6
6
|
import { buildProbeArgs, buildThumbnailArgs, buildTrimArgs, parseFfmpegProgress, parseFfprobe, } from 'cursedbelt-core/media/ffmpeg';
|
|
7
|
-
import { buildFrameJpegArgs, buildStreamProbeArgs, EMPTY_PROBE, parseProgressMicros, parseStreamProbe, } from './streaming';
|
|
7
|
+
import { buildFrameJpegArgs, buildStreamProbeArgs, EMPTY_PROBE, parseProgressMicros, parseStreamProbe, } from './streaming.js';
|
|
8
8
|
const FFMPEG = process.env.FFMPEG_PATH || 'ffmpeg';
|
|
9
9
|
const FFPROBE = process.env.FFPROBE_PATH || 'ffprobe';
|
|
10
10
|
/** Is ffmpeg runnable? Cheap probe used to skip server media ops / tests cleanly. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createMetricsBuffer } from './metricsBuffer';
|
|
1
|
+
import { createMetricsBuffer } from './metricsBuffer.js';
|
|
2
2
|
/**
|
|
3
3
|
* 🔴 **The data-point layout is a WIRE FORMAT.** Analytics Engine columns are
|
|
4
4
|
* positional (`blob1`, `double1`, …), so every saved SQL query breaks if a
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MiddlewareHandler } from 'hono';
|
|
2
|
-
import type { CursedbeltEnv } from '../context';
|
|
2
|
+
import type { CursedbeltEnv } from '../context.js';
|
|
3
3
|
/**
|
|
4
4
|
* Assign every request a correlation id: reuse a safe inbound `x-correlation-id`
|
|
5
5
|
* (so a trace survives the proxy hop), else mint a `crypto.randomUUID()`. Stored on
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ErrorHandler } from 'hono';
|
|
2
|
-
import type { CursedbeltEnv } from '../context';
|
|
2
|
+
import type { CursedbeltEnv } from '../context.js';
|
|
3
3
|
/**
|
|
4
4
|
* Hono `onError` handler. Converts ANY thrown value into the ONE canonical rich
|
|
5
5
|
* envelope — `{ error: { name, message, code?, status?, category?, context?,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HTTPException } from 'hono/http-exception';
|
|
2
|
-
import { ApiError, isAppError, toErrorEnvelope } from '../errors';
|
|
2
|
+
import { ApiError, isAppError, toErrorEnvelope } from '../errors.js';
|
|
3
3
|
/**
|
|
4
4
|
* Hono `onError` handler. Converts ANY thrown value into the ONE canonical rich
|
|
5
5
|
* envelope — `{ error: { name, message, code?, status?, category?, context?,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { correlationId } from './correlationId';
|
|
2
|
-
export { type CorsOpts, corsAllowlist, corsOptsFromEnv } from './corsAllowlist';
|
|
3
|
-
export { errorEnvelope } from './errorEnvelope';
|
|
4
|
-
export { crossOriginRefusal } from './localOrigin';
|
|
5
|
-
export { clientIp, createRateLimiter, type RateLimitOpts } from './rateLimit';
|
|
6
|
-
export { type RequestLoggerOpts, requestLogger } from './requestLogger';
|
|
7
|
-
export { type AnalyticsEngineDataset, createTelemetrySink, type TelemetryEvent, type TelemetrySink, type TelemetrySinkOptions, } from '../metrics/telemetrySink';
|
|
8
|
-
export { type CspDirectives, type SecurityHeadersOpts, securityHeaders, } from './securityHeaders';
|
|
9
|
-
export { toValidationIssues, VALIDATION_ERROR_CODE, type ValidationIssue, validationEnvelope, } from '../errors';
|
|
10
|
-
export { type ZValidatorTarget, zValidator } from './zValidator';
|
|
1
|
+
export { correlationId } from './correlationId.js';
|
|
2
|
+
export { type CorsOpts, corsAllowlist, corsOptsFromEnv } from './corsAllowlist.js';
|
|
3
|
+
export { errorEnvelope } from './errorEnvelope.js';
|
|
4
|
+
export { crossOriginRefusal } from './localOrigin.js';
|
|
5
|
+
export { clientIp, createRateLimiter, type RateLimitOpts } from './rateLimit.js';
|
|
6
|
+
export { type RequestLoggerOpts, requestLogger } from './requestLogger.js';
|
|
7
|
+
export { type AnalyticsEngineDataset, createTelemetrySink, type TelemetryEvent, type TelemetrySink, type TelemetrySinkOptions, } from '../metrics/telemetrySink.js';
|
|
8
|
+
export { type CspDirectives, type SecurityHeadersOpts, securityHeaders, } from './securityHeaders.js';
|
|
9
|
+
export { toValidationIssues, VALIDATION_ERROR_CODE, type ValidationIssue, validationEnvelope, } from '../errors.js';
|
|
10
|
+
export { type ZValidatorTarget, zValidator } from './zValidator.js';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// The cross-cutting cursedbelt server middleware set.
|
|
2
|
-
export { correlationId } from './correlationId';
|
|
3
|
-
export { corsAllowlist, corsOptsFromEnv } from './corsAllowlist';
|
|
4
|
-
export { errorEnvelope } from './errorEnvelope';
|
|
5
|
-
export { crossOriginRefusal } from './localOrigin';
|
|
6
|
-
export { clientIp, createRateLimiter } from './rateLimit';
|
|
7
|
-
export { requestLogger } from './requestLogger';
|
|
2
|
+
export { correlationId } from './correlationId.js';
|
|
3
|
+
export { corsAllowlist, corsOptsFromEnv } from './corsAllowlist.js';
|
|
4
|
+
export { errorEnvelope } from './errorEnvelope.js';
|
|
5
|
+
export { crossOriginRefusal } from './localOrigin.js';
|
|
6
|
+
export { clientIp, createRateLimiter } from './rateLimit.js';
|
|
7
|
+
export { requestLogger } from './requestLogger.js';
|
|
8
8
|
// The telemetry seam `requestLogger` writes through — re-exported here so a caller
|
|
9
9
|
// that reaches `./middleware` for the logger can bind Analytics Engine in the same import.
|
|
10
|
-
export { createTelemetrySink, } from '../metrics/telemetrySink';
|
|
11
|
-
export { securityHeaders, } from './securityHeaders';
|
|
12
|
-
export { toValidationIssues, VALIDATION_ERROR_CODE, validationEnvelope, } from '../errors';
|
|
13
|
-
export { zValidator } from './zValidator';
|
|
10
|
+
export { createTelemetrySink, } from '../metrics/telemetrySink.js';
|
|
11
|
+
export { securityHeaders, } from './securityHeaders.js';
|
|
12
|
+
export { toValidationIssues, VALIDATION_ERROR_CODE, validationEnvelope, } from '../errors.js';
|
|
13
|
+
export { zValidator } from './zValidator.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Database } from 'bun:sqlite';
|
|
2
2
|
import type { MiddlewareHandler } from 'hono';
|
|
3
|
-
import type { CursedbeltEnv } from '../context';
|
|
4
|
-
import type { MetricsBuffer } from '../metrics/metricsBuffer';
|
|
5
|
-
import { type AnalyticsEngineDataset, type TelemetrySink } from '../metrics/telemetrySink';
|
|
3
|
+
import type { CursedbeltEnv } from '../context.js';
|
|
4
|
+
import type { MetricsBuffer } from '../metrics/metricsBuffer.js';
|
|
5
|
+
import { type AnalyticsEngineDataset, type TelemetrySink } from '../metrics/telemetrySink.js';
|
|
6
6
|
/**
|
|
7
7
|
* Structured request/response logging. After each request it records one
|
|
8
8
|
* telemetry event through the {@link TelemetrySink} (off the hot path) and, for
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HTTPException } from 'hono/http-exception';
|
|
2
|
-
import { isApiError } from '../errors';
|
|
3
|
-
import { normalizeRoute } from '../metrics/normalizeRoute';
|
|
4
|
-
import { createTelemetrySink, } from '../metrics/telemetrySink';
|
|
2
|
+
import { isApiError } from '../errors.js';
|
|
3
|
+
import { normalizeRoute } from '../metrics/normalizeRoute.js';
|
|
4
|
+
import { createTelemetrySink, } from '../metrics/telemetrySink.js';
|
|
5
5
|
function statusOfThrown(err) {
|
|
6
6
|
if (isApiError(err))
|
|
7
7
|
return err.status;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Env, MiddlewareHandler } from 'hono';
|
|
2
2
|
import type { ZodType, z } from 'zod';
|
|
3
|
-
import type { CursedbeltEnv } from '../context';
|
|
3
|
+
import type { CursedbeltEnv } from '../context.js';
|
|
4
4
|
/** The request locations a schema can validate. Mirrors Hono's body/non-body split. */
|
|
5
5
|
export type ZValidatorTarget = 'json' | 'form' | 'query' | 'param';
|
|
6
6
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { validationEnvelope } from '../errors';
|
|
1
|
+
import { validationEnvelope } from '../errors.js';
|
|
2
2
|
/**
|
|
3
3
|
* Read the value a target validates against. The body targets (`json`/`form`) prefer
|
|
4
4
|
* the ctgr-decoded body so a tunnelled mutation validates its real payload; the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Database } from 'bun:sqlite';
|
|
2
|
-
import type { Migration } from './types';
|
|
2
|
+
import type { Migration } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* The versioned SQLite migration runner — a tiny `_migrations`-sentinel runner, NOT
|
|
5
5
|
* a schema-first ORM. It replaces the old scattered guarded-`ALTER` /
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { isIP } from 'node:net';
|
|
35
35
|
import { lookup } from 'node:dns/promises';
|
|
36
|
-
import { AppError } from '../errors';
|
|
36
|
+
import { AppError } from '../errors.js';
|
|
37
37
|
export const OUTBOUND_URL_BLOCKED = 'OUTBOUND_URL_BLOCKED';
|
|
38
38
|
const blocked = (reason, context) => new AppError(`Outbound request refused: ${reason}.`, {
|
|
39
39
|
code: OUTBOUND_URL_BLOCKED,
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
* route that notifies somebody else; producing is server-side code calling
|
|
37
37
|
* `center.notify*`.
|
|
38
38
|
*/
|
|
39
|
-
export { createNotificationHub } from "./hub";
|
|
40
|
-
export type { NotificationHub, NotificationHubEvent, NotificationHubListener, NotificationHubOptions, } from "./hub";
|
|
41
|
-
export { NOTIFICATION_MIGRATIONS, NOTIFICATIONS_TABLE } from "./migrations";
|
|
42
|
-
export { mountNotificationRoutes } from "./routes";
|
|
43
|
-
export type { NotificationRouteCenter, NotificationRoutesOptions } from "./routes";
|
|
44
|
-
export { createNotificationService } from "./service";
|
|
45
|
-
export type { CreateNotificationServiceOptions, NotificationService, NotificationServiceMountOptions, } from "./service";
|
|
39
|
+
export { createNotificationHub } from "./hub.js";
|
|
40
|
+
export type { NotificationHub, NotificationHubEvent, NotificationHubListener, NotificationHubOptions, } from "./hub.js";
|
|
41
|
+
export { NOTIFICATION_MIGRATIONS, NOTIFICATIONS_TABLE } from "./migrations.js";
|
|
42
|
+
export { mountNotificationRoutes } from "./routes.js";
|
|
43
|
+
export type { NotificationRouteCenter, NotificationRoutesOptions } from "./routes.js";
|
|
44
|
+
export { createNotificationService } from "./service.js";
|
|
45
|
+
export type { CreateNotificationServiceOptions, NotificationService, NotificationServiceMountOptions, } from "./service.js";
|
|
46
46
|
export { createNotificationCenter, createMemoryNotificationStore, createSqliteNotificationStore, migrateNotificationsSchema, } from "cwip/notifications";
|
|
47
47
|
export type { AppNotification, ListNotificationsQuery, NotificationAudience, NotificationCenter, NotificationCenterOptions, NotificationDraft, NotificationFilter, NotificationPage, NotificationSeverity, NotificationSink, NotificationStore, Notifier, } from "cwip/notifications";
|