cursedbelt-server 1.0.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/LICENSE +15 -0
- package/dist/server/activity/index.d.ts +36 -0
- package/dist/server/activity/index.js +36 -0
- package/dist/server/activity/migrations.d.ts +21 -0
- package/dist/server/activity/migrations.js +55 -0
- package/dist/server/activity/shareSource.d.ts +11 -0
- package/dist/server/activity/shareSource.js +45 -0
- package/dist/server/activity/store.d.ts +123 -0
- package/dist/server/activity/store.js +178 -0
- package/dist/server/app.d.ts +56 -0
- package/dist/server/app.js +45 -0
- package/dist/server/audit/index.d.ts +2 -0
- package/dist/server/audit/index.js +2 -0
- package/dist/server/audit/migrations.d.ts +2 -0
- package/dist/server/audit/migrations.js +79 -0
- package/dist/server/audit/sqliteSink.d.ts +36 -0
- package/dist/server/audit/sqliteSink.js +95 -0
- package/dist/server/audit/sqliteSink.test.d.ts +1 -0
- package/dist/server/audit/sqliteSink.test.js +180 -0
- package/dist/server/auth/cookie.d.ts +22 -0
- package/dist/server/auth/cookie.js +35 -0
- package/dist/server/auth/csrf.d.ts +42 -0
- package/dist/server/auth/csrf.js +36 -0
- package/dist/server/auth/fileTokenSigner.d.ts +10 -0
- package/dist/server/auth/fileTokenSigner.js +22 -0
- package/dist/server/auth/getOnly.d.ts +20 -0
- package/dist/server/auth/getOnly.js +27 -0
- package/dist/server/auth/index.d.ts +12 -0
- package/dist/server/auth/index.js +15 -0
- package/dist/server/auth/jwt.d.ts +18 -0
- package/dist/server/auth/jwt.js +56 -0
- package/dist/server/auth/loginThrottle.d.ts +118 -0
- package/dist/server/auth/loginThrottle.js +204 -0
- package/dist/server/auth/middleware.d.ts +14 -0
- package/dist/server/auth/middleware.js +47 -0
- package/dist/server/auth/password.d.ts +14 -0
- package/dist/server/auth/password.js +65 -0
- package/dist/server/auth/sessionStore.d.ts +19 -0
- package/dist/server/auth/sessionStore.js +221 -0
- package/dist/server/auth/totp.d.ts +34 -0
- package/dist/server/auth/totp.js +81 -0
- package/dist/server/auth/types.d.ts +133 -0
- package/dist/server/auth/types.js +1 -0
- package/dist/server/auth/vault.d.ts +27 -0
- package/dist/server/auth/vault.js +57 -0
- package/dist/server/context.d.ts +35 -0
- package/dist/server/context.js +1 -0
- package/dist/server/ctgr.d.ts +32 -0
- package/dist/server/ctgr.js +69 -0
- package/dist/server/db/kysely.d.ts +14 -0
- package/dist/server/db/kysely.js +16 -0
- package/dist/server/db/plumbingTypes.d.ts +116 -0
- package/dist/server/db/plumbingTypes.js +12 -0
- package/dist/server/dropzone/duplicates.d.ts +82 -0
- package/dist/server/dropzone/duplicates.js +90 -0
- package/dist/server/dropzone/index.d.ts +13 -0
- package/dist/server/dropzone/index.js +13 -0
- package/dist/server/dropzone/scan.d.ts +166 -0
- package/dist/server/dropzone/scan.js +272 -0
- package/dist/server/errors.d.ts +7 -0
- package/dist/server/errors.js +7 -0
- package/dist/server/guard/argon2Binding.d.ts +97 -0
- package/dist/server/guard/argon2Binding.js +138 -0
- package/dist/server/guard/index.d.ts +4 -0
- package/dist/server/guard/index.js +6 -0
- package/dist/server/guard/kdfWorker.d.ts +101 -0
- package/dist/server/guard/kdfWorker.js +301 -0
- package/dist/server/guard/kdfWorkerEntry.d.ts +1 -0
- package/dist/server/guard/kdfWorkerEntry.js +15 -0
- package/dist/server/guard/passwordVerifier.d.ts +65 -0
- package/dist/server/guard/passwordVerifier.js +122 -0
- package/dist/server/guard/revocationStore.d.ts +132 -0
- package/dist/server/guard/revocationStore.js +211 -0
- package/dist/server/guard/sessionSigner.d.ts +132 -0
- package/dist/server/guard/sessionSigner.js +303 -0
- package/dist/server/guard/verifier.d.ts +21 -0
- package/dist/server/guard/verifier.js +1 -0
- package/dist/server/incidents/channels.d.ts +161 -0
- package/dist/server/incidents/channels.js +357 -0
- package/dist/server/incidents/checks.d.ts +61 -0
- package/dist/server/incidents/checks.js +55 -0
- package/dist/server/incidents/index.d.ts +51 -0
- package/dist/server/incidents/index.js +51 -0
- package/dist/server/incidents/migrations.d.ts +20 -0
- package/dist/server/incidents/migrations.js +58 -0
- package/dist/server/incidents/notifier.d.ts +79 -0
- package/dist/server/incidents/notifier.js +141 -0
- package/dist/server/incidents/reporter.d.ts +60 -0
- package/dist/server/incidents/reporter.js +49 -0
- package/dist/server/incidents/routes.d.ts +91 -0
- package/dist/server/incidents/routes.js +202 -0
- package/dist/server/incidents/store.d.ts +75 -0
- package/dist/server/incidents/store.js +176 -0
- package/dist/server/incidents/types.d.ts +107 -0
- package/dist/server/incidents/types.js +32 -0
- package/dist/server/index.d.ts +25 -0
- package/dist/server/index.js +53 -0
- package/dist/server/jobs/fireQueue.d.ts +12 -0
- package/dist/server/jobs/fireQueue.js +37 -0
- package/dist/server/jobs/index.d.ts +6 -0
- package/dist/server/jobs/index.js +10 -0
- package/dist/server/jobs/logger.d.ts +10 -0
- package/dist/server/jobs/logger.js +14 -0
- package/dist/server/jobs/plainjobAdapter.d.ts +19 -0
- package/dist/server/jobs/plainjobAdapter.js +48 -0
- package/dist/server/jobs/polling.d.ts +17 -0
- package/dist/server/jobs/polling.js +79 -0
- package/dist/server/jobs/runner.d.ts +24 -0
- package/dist/server/jobs/runner.js +186 -0
- package/dist/server/jobs/timeout.d.ts +28 -0
- package/dist/server/jobs/timeout.js +47 -0
- package/dist/server/jobs/types.d.ts +167 -0
- package/dist/server/jobs/types.js +12 -0
- package/dist/server/master-lock/guard.d.ts +53 -0
- package/dist/server/master-lock/guard.js +205 -0
- package/dist/server/master-lock/index.d.ts +21 -0
- package/dist/server/master-lock/index.js +21 -0
- package/dist/server/master-lock/lockPage.d.ts +34 -0
- package/dist/server/master-lock/lockPage.js +281 -0
- package/dist/server/master-lock/masterLock.d.ts +294 -0
- package/dist/server/master-lock/masterLock.js +523 -0
- package/dist/server/master-lock/principals.d.ts +76 -0
- package/dist/server/master-lock/principals.js +157 -0
- package/dist/server/master-lock/seed.d.ts +47 -0
- package/dist/server/master-lock/seed.js +93 -0
- package/dist/server/master-lock/store.d.ts +19 -0
- package/dist/server/master-lock/store.js +20 -0
- package/dist/server/media-bun/image.d.ts +7 -0
- package/dist/server/media-bun/image.js +96 -0
- package/dist/server/media-bun/index.d.ts +4 -0
- package/dist/server/media-bun/index.js +10 -0
- package/dist/server/media-bun/streaming.d.ts +86 -0
- package/dist/server/media-bun/streaming.js +237 -0
- package/dist/server/media-bun/video.d.ts +35 -0
- package/dist/server/media-bun/video.js +181 -0
- package/dist/server/metrics/metricsBuffer.d.ts +39 -0
- package/dist/server/metrics/metricsBuffer.js +36 -0
- package/dist/server/metrics/normalizeRoute.d.ts +5 -0
- package/dist/server/metrics/normalizeRoute.js +58 -0
- package/dist/server/middleware/correlationId.d.ts +9 -0
- package/dist/server/middleware/correlationId.js +20 -0
- package/dist/server/middleware/corsAllowlist.d.ts +38 -0
- package/dist/server/middleware/corsAllowlist.js +37 -0
- package/dist/server/middleware/errorEnvelope.d.ts +17 -0
- package/dist/server/middleware/errorEnvelope.js +32 -0
- package/dist/server/middleware/index.d.ts +9 -0
- package/dist/server/middleware/index.js +10 -0
- package/dist/server/middleware/localOrigin.d.ts +71 -0
- package/dist/server/middleware/localOrigin.js +119 -0
- package/dist/server/middleware/rateLimit.d.ts +56 -0
- package/dist/server/middleware/rateLimit.js +86 -0
- package/dist/server/middleware/requestLogger.d.ts +29 -0
- package/dist/server/middleware/requestLogger.js +47 -0
- package/dist/server/middleware/securityHeaders.d.ts +29 -0
- package/dist/server/middleware/securityHeaders.js +44 -0
- package/dist/server/middleware/zValidator.d.ts +29 -0
- package/dist/server/middleware/zValidator.js +57 -0
- package/dist/server/migration/runner.d.ts +42 -0
- package/dist/server/migration/runner.js +70 -0
- package/dist/server/migration/types.d.ts +16 -0
- package/dist/server/migration/types.js +1 -0
- package/dist/server/net/outboundGuard.d.ts +30 -0
- package/dist/server/net/outboundGuard.js +199 -0
- package/dist/server/notifications/hub.d.ts +67 -0
- package/dist/server/notifications/hub.js +187 -0
- package/dist/server/notifications/index.d.ts +47 -0
- package/dist/server/notifications/index.js +46 -0
- package/dist/server/notifications/migrations.d.ts +13 -0
- package/dist/server/notifications/migrations.js +20 -0
- package/dist/server/notifications/routes.d.ts +58 -0
- package/dist/server/notifications/routes.js +113 -0
- package/dist/server/notifications/service.d.ts +58 -0
- package/dist/server/notifications/service.js +41 -0
- package/dist/server/paths/appDataHome.d.ts +19 -0
- package/dist/server/paths/appDataHome.js +68 -0
- package/dist/server/private-media/crypto.d.ts +37 -0
- package/dist/server/private-media/crypto.js +111 -0
- package/dist/server/private-media/index-store.d.ts +31 -0
- package/dist/server/private-media/index-store.js +36 -0
- package/dist/server/private-media/mountPrivateRoutes.d.ts +26 -0
- package/dist/server/private-media/mountPrivateRoutes.js +219 -0
- package/dist/server/private-media/pipeline.d.ts +37 -0
- package/dist/server/private-media/pipeline.js +97 -0
- package/dist/server/private-media/unlock.d.ts +52 -0
- package/dist/server/private-media/unlock.js +55 -0
- package/dist/server/resume/index.d.ts +2 -0
- package/dist/server/resume/index.js +2 -0
- package/dist/server/resume/routes.d.ts +41 -0
- package/dist/server/resume/routes.js +50 -0
- package/dist/server/resume/store.d.ts +37 -0
- package/dist/server/resume/store.js +38 -0
- package/dist/server/retention/archive.d.ts +78 -0
- package/dist/server/retention/archive.js +284 -0
- package/dist/server/retention/fleet.d.ts +50 -0
- package/dist/server/retention/fleet.js +66 -0
- package/dist/server/retention/index.d.ts +38 -0
- package/dist/server/retention/index.js +38 -0
- package/dist/server/retention/policy.d.ts +263 -0
- package/dist/server/retention/policy.js +264 -0
- package/dist/server/retention/store.d.ts +101 -0
- package/dist/server/retention/store.js +251 -0
- package/dist/server/retention/sweeper.d.ts +69 -0
- package/dist/server/retention/sweeper.js +289 -0
- package/dist/server/retention/target.d.ts +143 -0
- package/dist/server/retention/target.js +438 -0
- package/dist/server/search/index.d.ts +2 -0
- package/dist/server/search/index.js +6 -0
- package/dist/server/search/pgSearchProvider.d.ts +91 -0
- package/dist/server/search/pgSearchProvider.js +330 -0
- package/dist/server/search/pgSearchProvider.pg.test.d.ts +1 -0
- package/dist/server/search/pgSearchProvider.pg.test.js +338 -0
- package/dist/server/search/pgSearchSchema.d.ts +81 -0
- package/dist/server/search/pgSearchSchema.js +89 -0
- package/dist/server/sharing/index.d.ts +18 -0
- package/dist/server/sharing/index.js +16 -0
- package/dist/server/sharing/migrations.d.ts +6 -0
- package/dist/server/sharing/migrations.js +79 -0
- package/dist/server/sharing/router.d.ts +111 -0
- package/dist/server/sharing/router.js +93 -0
- package/dist/server/sharing/sql.d.ts +67 -0
- package/dist/server/sharing/sql.js +88 -0
- package/dist/server/sharing/store.d.ts +173 -0
- package/dist/server/sharing/store.js +484 -0
- package/dist/server/sqlite/backup.d.ts +48 -0
- package/dist/server/sqlite/backup.js +97 -0
- package/dist/server/sqlite/browse.d.ts +42 -0
- package/dist/server/sqlite/browse.js +84 -0
- package/dist/server/sqlite/export.d.ts +32 -0
- package/dist/server/sqlite/export.js +42 -0
- package/dist/server/sqlite/fts5.d.ts +106 -0
- package/dist/server/sqlite/fts5.js +154 -0
- package/dist/server/sqlite/health.d.ts +44 -0
- package/dist/server/sqlite/health.js +52 -0
- package/dist/server/sqlite/import.d.ts +36 -0
- package/dist/server/sqlite/import.js +108 -0
- package/dist/server/sqlite/index.d.ts +9 -0
- package/dist/server/sqlite/index.js +15 -0
- package/dist/server/sqlite/readonlySql.d.ts +15 -0
- package/dist/server/sqlite/readonlySql.js +65 -0
- package/dist/server/sqlite/stats.d.ts +22 -0
- package/dist/server/sqlite/stats.js +32 -0
- package/dist/server/sqlite/viewer.d.ts +17 -0
- package/dist/server/sqlite/viewer.js +56 -0
- package/dist/server/storage/binaryServerProcessing.d.ts +23 -0
- package/dist/server/storage/binaryServerProcessing.js +81 -0
- package/dist/server/storage/binaryServerStore.d.ts +3 -0
- package/dist/server/storage/binaryServerStore.js +95 -0
- package/dist/server/storage/diskStore.d.ts +2 -0
- package/dist/server/storage/diskStore.js +88 -0
- package/dist/server/storage/files/adapter.d.ts +33 -0
- package/dist/server/storage/files/adapter.js +203 -0
- package/dist/server/storage/files/catalogue.d.ts +72 -0
- package/dist/server/storage/files/catalogue.js +1033 -0
- package/dist/server/storage/files/chunkedUpload.d.ts +56 -0
- package/dist/server/storage/files/chunkedUpload.js +70 -0
- package/dist/server/storage/files/fileRoutes.d.ts +51 -0
- package/dist/server/storage/files/fileRoutes.js +405 -0
- package/dist/server/storage/files/index.d.ts +9 -0
- package/dist/server/storage/files/index.js +11 -0
- package/dist/server/storage/files/migrations.d.ts +2 -0
- package/dist/server/storage/files/migrations.js +163 -0
- package/dist/server/storage/files/mimeByExt.d.ts +1 -0
- package/dist/server/storage/files/mimeByExt.js +13 -0
- package/dist/server/storage/files/stack.d.ts +136 -0
- package/dist/server/storage/files/stack.js +132 -0
- package/dist/server/storage/files/storageOps.d.ts +54 -0
- package/dist/server/storage/files/storageOps.js +110 -0
- package/dist/server/storage/files/types.d.ts +261 -0
- package/dist/server/storage/files/types.js +22 -0
- package/dist/server/storage/imageThumbnail.d.ts +3 -0
- package/dist/server/storage/imageThumbnail.js +50 -0
- package/dist/server/storage/index.d.ts +15 -0
- package/dist/server/storage/index.js +27 -0
- package/dist/server/storage/mountMediaRoutes.d.ts +28 -0
- package/dist/server/storage/mountMediaRoutes.js +141 -0
- package/dist/server/storage/objectStoreMediaStore.d.ts +4 -0
- package/dist/server/storage/objectStoreMediaStore.js +57 -0
- package/dist/server/storage/s3ObjectStore.d.ts +63 -0
- package/dist/server/storage/s3ObjectStore.js +187 -0
- package/dist/server/storage/sources.d.ts +47 -0
- package/dist/server/storage/sources.js +148 -0
- package/dist/server/storage/streamRange.d.ts +19 -0
- package/dist/server/storage/streamRange.js +69 -0
- package/dist/server/storage/streamToken.d.ts +16 -0
- package/dist/server/storage/streamToken.js +54 -0
- package/dist/server/storage/transcodeJobs.d.ts +65 -0
- package/dist/server/storage/transcodeJobs.js +104 -0
- package/dist/server/storage/types.d.ts +193 -0
- package/dist/server/storage/types.js +41 -0
- package/dist/server/storage/videoDerivativeKeys.d.ts +127 -0
- package/dist/server/storage/videoDerivativeKeys.js +149 -0
- package/dist/server/storage/videoProcessor.d.ts +30 -0
- package/dist/server/storage/videoProcessor.js +148 -0
- package/dist/server/sync/alarm.d.ts +34 -0
- package/dist/server/sync/alarm.js +91 -0
- package/dist/server/sync/commands.d.ts +87 -0
- package/dist/server/sync/commands.js +241 -0
- package/dist/server/sync/engine.d.ts +62 -0
- package/dist/server/sync/engine.js +184 -0
- package/dist/server/sync/http.d.ts +106 -0
- package/dist/server/sync/http.js +243 -0
- package/dist/server/sync/index.d.ts +41 -0
- package/dist/server/sync/index.js +41 -0
- package/dist/server/sync/opLog.d.ts +61 -0
- package/dist/server/sync/opLog.js +96 -0
- package/dist/server/sync/planner.d.ts +31 -0
- package/dist/server/sync/planner.js +30 -0
- package/dist/server/sync/status.d.ts +63 -0
- package/dist/server/sync/status.js +49 -0
- package/dist/server/sync/timer.d.ts +52 -0
- package/dist/server/sync/timer.js +170 -0
- package/dist/server/sync/tokens.d.ts +25 -0
- package/dist/server/sync/tokens.js +51 -0
- package/dist/server/sync/types.d.ts +101 -0
- package/dist/server/sync/types.js +29 -0
- package/dist/server/ws/eventBus.d.ts +14 -0
- package/dist/server/ws/eventBus.js +42 -0
- package/dist/server/ws/hub.d.ts +20 -0
- package/dist/server/ws/hub.js +154 -0
- package/dist/server/ws/index.d.ts +5 -0
- package/dist/server/ws/index.js +7 -0
- package/dist/server/ws/presence.d.ts +11 -0
- package/dist/server/ws/presence.js +20 -0
- package/dist/server/ws/room.d.ts +17 -0
- package/dist/server/ws/room.js +23 -0
- package/dist/server/ws/types.d.ts +122 -0
- package/dist/server/ws/types.js +1 -0
- package/package.json +234 -0
- package/src/declaredDepsAreImported.spec.ts +87 -0
- package/src/leafSubpathsImportNothing.spec.ts +358 -0
- package/src/lockfileIsTracked.spec.ts +50 -0
- package/src/namedSubpathsResolve.spec.ts +122 -0
- package/src/noPathDeps.spec.ts +24 -0
- package/src/publishShape.spec.ts +89 -0
- package/src/server/activity/index.ts +59 -0
- package/src/server/activity/migrations.ts +67 -0
- package/src/server/activity/shareSource.ts +57 -0
- package/src/server/activity/store.spec.ts +255 -0
- package/src/server/activity/store.ts +368 -0
- package/src/server/app.spec.ts +243 -0
- package/src/server/app.ts +89 -0
- package/src/server/audit/index.ts +2 -0
- package/src/server/audit/migrations.ts +88 -0
- package/src/server/audit/sqliteSink.test.ts +200 -0
- package/src/server/audit/sqliteSink.ts +162 -0
- package/src/server/auth/cookie.spec.ts +46 -0
- package/src/server/auth/cookie.ts +42 -0
- package/src/server/auth/csrf.spec.ts +81 -0
- package/src/server/auth/csrf.ts +83 -0
- package/src/server/auth/fileTokenSigner.ts +40 -0
- package/src/server/auth/getOnly.spec.ts +53 -0
- package/src/server/auth/getOnly.ts +32 -0
- package/src/server/auth/index.ts +51 -0
- package/src/server/auth/jwt.spec.ts +106 -0
- package/src/server/auth/jwt.ts +75 -0
- package/src/server/auth/loginThrottle.spec.ts +213 -0
- package/src/server/auth/loginThrottle.ts +261 -0
- package/src/server/auth/middleware.spec.ts +148 -0
- package/src/server/auth/middleware.ts +56 -0
- package/src/server/auth/password.spec.ts +48 -0
- package/src/server/auth/password.ts +71 -0
- package/src/server/auth/sessionStore.spec.ts +189 -0
- package/src/server/auth/sessionStore.ts +261 -0
- package/src/server/auth/totp.spec.ts +73 -0
- package/src/server/auth/totp.ts +92 -0
- package/src/server/auth/types.ts +146 -0
- package/src/server/auth/vault.spec.ts +51 -0
- package/src/server/auth/vault.ts +71 -0
- package/src/server/context.ts +37 -0
- package/src/server/ctgr.spec.ts +138 -0
- package/src/server/ctgr.ts +108 -0
- package/src/server/db/kysely.spec.ts +62 -0
- package/src/server/db/kysely.ts +21 -0
- package/src/server/db/plumbingTypes.ts +126 -0
- package/src/server/dropzone/duplicates.ts +121 -0
- package/src/server/dropzone/index.ts +30 -0
- package/src/server/dropzone/scan.spec.ts +255 -0
- package/src/server/dropzone/scan.ts +342 -0
- package/src/server/errors.spec.ts +76 -0
- package/src/server/errors.ts +22 -0
- package/src/server/guard/argon2Binding.spec.ts +117 -0
- package/src/server/guard/argon2Binding.ts +195 -0
- package/src/server/guard/argon2Kat.spec.ts +250 -0
- package/src/server/guard/guard.spec.ts +390 -0
- package/src/server/guard/index.ts +6 -0
- package/src/server/guard/kdfWorker.spec.ts +283 -0
- package/src/server/guard/kdfWorker.ts +367 -0
- package/src/server/guard/kdfWorkerEntry.ts +16 -0
- package/src/server/guard/passwordVerifier.spec.ts +71 -0
- package/src/server/guard/passwordVerifier.ts +175 -0
- package/src/server/guard/revocationStore.spec.ts +135 -0
- package/src/server/guard/revocationStore.ts +291 -0
- package/src/server/guard/sessionSigner.ts +425 -0
- package/src/server/guard/verifier.ts +27 -0
- package/src/server/incidents/channels.ts +487 -0
- package/src/server/incidents/checks.ts +120 -0
- package/src/server/incidents/incidents.spec.ts +463 -0
- package/src/server/incidents/index.ts +96 -0
- package/src/server/incidents/migrations.ts +66 -0
- package/src/server/incidents/notifier.ts +215 -0
- package/src/server/incidents/reporter.ts +110 -0
- package/src/server/incidents/routes.ts +314 -0
- package/src/server/incidents/store.ts +329 -0
- package/src/server/incidents/types.ts +116 -0
- package/src/server/index.ts +248 -0
- package/src/server/jobs/fireQueue.spec.ts +85 -0
- package/src/server/jobs/fireQueue.ts +37 -0
- package/src/server/jobs/index.ts +26 -0
- package/src/server/jobs/logger.ts +16 -0
- package/src/server/jobs/plainjobAdapter.spec.ts +34 -0
- package/src/server/jobs/plainjobAdapter.ts +54 -0
- package/src/server/jobs/polling.spec.ts +219 -0
- package/src/server/jobs/polling.ts +81 -0
- package/src/server/jobs/runner.spec.ts +213 -0
- package/src/server/jobs/runner.ts +213 -0
- package/src/server/jobs/timeout.spec.ts +35 -0
- package/src/server/jobs/timeout.ts +53 -0
- package/src/server/jobs/types.ts +188 -0
- package/src/server/master-lock/guard.spec.ts +347 -0
- package/src/server/master-lock/guard.ts +290 -0
- package/src/server/master-lock/index.ts +44 -0
- package/src/server/master-lock/lockPage.spec.ts +88 -0
- package/src/server/master-lock/lockPage.ts +313 -0
- package/src/server/master-lock/masterLock.spec.ts +338 -0
- package/src/server/master-lock/masterLock.ts +627 -0
- package/src/server/master-lock/principals.spec.ts +378 -0
- package/src/server/master-lock/principals.ts +175 -0
- package/src/server/master-lock/seed.spec.ts +69 -0
- package/src/server/master-lock/seed.ts +112 -0
- package/src/server/master-lock/store.ts +35 -0
- package/src/server/media-bun/image.spec.ts +115 -0
- package/src/server/media-bun/image.ts +134 -0
- package/src/server/media-bun/index.ts +52 -0
- package/src/server/media-bun/streaming.spec.ts +134 -0
- package/src/server/media-bun/streaming.ts +347 -0
- package/src/server/media-bun/video.spec.ts +115 -0
- package/src/server/media-bun/video.ts +232 -0
- package/src/server/metrics/metricsBuffer.ts +92 -0
- package/src/server/metrics/normalizeRoute.spec.ts +51 -0
- package/src/server/metrics/normalizeRoute.ts +63 -0
- package/src/server/middleware/correlationId.ts +24 -0
- package/src/server/middleware/corsAllowlist.spec.ts +118 -0
- package/src/server/middleware/corsAllowlist.ts +69 -0
- package/src/server/middleware/errorEnvelope.ts +38 -0
- package/src/server/middleware/index.ts +19 -0
- package/src/server/middleware/localOrigin.spec.ts +168 -0
- package/src/server/middleware/localOrigin.ts +139 -0
- package/src/server/middleware/rateLimit.spec.ts +72 -0
- package/src/server/middleware/rateLimit.ts +125 -0
- package/src/server/middleware/requestLogger.ts +95 -0
- package/src/server/middleware/securityHeaders.ts +78 -0
- package/src/server/middleware/zValidator.spec.ts +251 -0
- package/src/server/middleware/zValidator.ts +114 -0
- package/src/server/migration/runner.spec.ts +88 -0
- package/src/server/migration/runner.ts +87 -0
- package/src/server/migration/types.ts +17 -0
- package/src/server/net/outboundGuard.spec.ts +90 -0
- package/src/server/net/outboundGuard.ts +205 -0
- package/src/server/notifications/hub.ts +245 -0
- package/src/server/notifications/index.ts +77 -0
- package/src/server/notifications/migrations.ts +39 -0
- package/src/server/notifications/routes.ts +177 -0
- package/src/server/notifications/service.spec.ts +305 -0
- package/src/server/notifications/service.ts +112 -0
- package/src/server/paths/appDataHome.spec.ts +87 -0
- package/src/server/paths/appDataHome.ts +84 -0
- package/src/server/private-media/blobRoute.spec.ts +165 -0
- package/src/server/private-media/crypto.spec.ts +81 -0
- package/src/server/private-media/crypto.ts +155 -0
- package/src/server/private-media/gatePolicy.spec.ts +98 -0
- package/src/server/private-media/index-store.ts +83 -0
- package/src/server/private-media/mountPrivateRoutes.ts +265 -0
- package/src/server/private-media/pipeline.spec.ts +111 -0
- package/src/server/private-media/pipeline.ts +170 -0
- package/src/server/private-media/routes.spec.ts +265 -0
- package/src/server/private-media/unlock.ts +112 -0
- package/src/server/resume/index.ts +8 -0
- package/src/server/resume/resume.spec.ts +118 -0
- package/src/server/resume/routes.ts +92 -0
- package/src/server/resume/store.ts +82 -0
- package/src/server/retention/archive.spec.ts +181 -0
- package/src/server/retention/archive.ts +353 -0
- package/src/server/retention/fleet.ts +104 -0
- package/src/server/retention/index.ts +101 -0
- package/src/server/retention/policy.spec.ts +132 -0
- package/src/server/retention/policy.ts +392 -0
- package/src/server/retention/store.spec.ts +236 -0
- package/src/server/retention/store.ts +338 -0
- package/src/server/retention/sweeper.spec.ts +321 -0
- package/src/server/retention/sweeper.ts +367 -0
- package/src/server/retention/target.spec.ts +592 -0
- package/src/server/retention/target.ts +613 -0
- package/src/server/search/index.ts +12 -0
- package/src/server/search/pgSearchProvider.pg.test.ts +392 -0
- package/src/server/search/pgSearchProvider.ts +421 -0
- package/src/server/search/pgSearchSchema.ts +147 -0
- package/src/server/sharing/index.ts +65 -0
- package/src/server/sharing/migrations.ts +128 -0
- package/src/server/sharing/router.spec.ts +167 -0
- package/src/server/sharing/router.ts +194 -0
- package/src/server/sharing/sql.ts +109 -0
- package/src/server/sharing/store.spec.ts +408 -0
- package/src/server/sharing/store.ts +737 -0
- package/src/server/sqlite/backup.spec.ts +114 -0
- package/src/server/sqlite/backup.ts +154 -0
- package/src/server/sqlite/browse.spec.ts +70 -0
- package/src/server/sqlite/browse.ts +120 -0
- package/src/server/sqlite/export.spec.ts +43 -0
- package/src/server/sqlite/export.ts +74 -0
- package/src/server/sqlite/fts5.spec.ts +175 -0
- package/src/server/sqlite/fts5.ts +255 -0
- package/src/server/sqlite/health.spec.ts +79 -0
- package/src/server/sqlite/health.ts +105 -0
- package/src/server/sqlite/import.spec.ts +75 -0
- package/src/server/sqlite/import.ts +141 -0
- package/src/server/sqlite/index.ts +64 -0
- package/src/server/sqlite/readonlySql.spec.ts +58 -0
- package/src/server/sqlite/readonlySql.ts +67 -0
- package/src/server/sqlite/stats.spec.ts +21 -0
- package/src/server/sqlite/stats.ts +61 -0
- package/src/server/sqlite/viewer.spec.ts +127 -0
- package/src/server/sqlite/viewer.ts +72 -0
- package/src/server/storage/binaryServerProcessing.integration.spec.ts +222 -0
- package/src/server/storage/binaryServerProcessing.spec.ts +150 -0
- package/src/server/storage/binaryServerProcessing.ts +127 -0
- package/src/server/storage/binaryServerStore.ts +102 -0
- package/src/server/storage/chunked.integration.spec.ts +185 -0
- package/src/server/storage/diskStore.ts +83 -0
- package/src/server/storage/files/adapter.photo.display.spec.ts +169 -0
- package/src/server/storage/files/adapter.photo.spec.ts +128 -0
- package/src/server/storage/files/adapter.spec.ts +121 -0
- package/src/server/storage/files/adapter.ts +255 -0
- package/src/server/storage/files/catalogue.media-host.spec.ts +184 -0
- package/src/server/storage/files/catalogue.orderings.spec.ts +157 -0
- package/src/server/storage/files/catalogue.private.spec.ts +106 -0
- package/src/server/storage/files/catalogue.recover.spec.ts +131 -0
- package/src/server/storage/files/catalogue.sort.spec.ts +154 -0
- package/src/server/storage/files/catalogue.spec.ts +133 -0
- package/src/server/storage/files/catalogue.trash-import.spec.ts +125 -0
- package/src/server/storage/files/catalogue.ts +1326 -0
- package/src/server/storage/files/chunkedUpload.spec.ts +111 -0
- package/src/server/storage/files/chunkedUpload.ts +146 -0
- package/src/server/storage/files/collections.spec.ts +294 -0
- package/src/server/storage/files/fileRoutes.replace.spec.ts +88 -0
- package/src/server/storage/files/fileRoutes.spec.ts +327 -0
- package/src/server/storage/files/fileRoutes.ts +462 -0
- package/src/server/storage/files/index.ts +66 -0
- package/src/server/storage/files/migrations.ts +187 -0
- package/src/server/storage/files/mimeByExt.ts +14 -0
- package/src/server/storage/files/stack.spec.ts +258 -0
- package/src/server/storage/files/stack.ts +284 -0
- package/src/server/storage/files/storageOps.spec.ts +126 -0
- package/src/server/storage/files/storageOps.ts +213 -0
- package/src/server/storage/files/types.ts +285 -0
- package/src/server/storage/imageThumbnail.spec.ts +81 -0
- package/src/server/storage/imageThumbnail.ts +60 -0
- package/src/server/storage/index.ts +122 -0
- package/src/server/storage/mountMediaRoutes.ts +231 -0
- package/src/server/storage/objectStore.spec.ts +272 -0
- package/src/server/storage/objectStoreMediaStore.ts +63 -0
- package/src/server/storage/s3ObjectStore.ts +239 -0
- package/src/server/storage/sources.ts +245 -0
- package/src/server/storage/storage.spec.ts +219 -0
- package/src/server/storage/streamRange.ts +92 -0
- package/src/server/storage/streamToken.ts +76 -0
- package/src/server/storage/transcode.integration.spec.ts +134 -0
- package/src/server/storage/transcodeJobs.spec.ts +152 -0
- package/src/server/storage/transcodeJobs.ts +171 -0
- package/src/server/storage/types.ts +230 -0
- package/src/server/storage/videoDerivativeKeys.spec.ts +112 -0
- package/src/server/storage/videoDerivativeKeys.ts +172 -0
- package/src/server/storage/videoProcessor.posterOnly.spec.ts +106 -0
- package/src/server/storage/videoProcessor.ts +229 -0
- package/src/server/sync/alarm.spec.ts +149 -0
- package/src/server/sync/alarm.ts +137 -0
- package/src/server/sync/commands.spec.ts +145 -0
- package/src/server/sync/commands.ts +361 -0
- package/src/server/sync/engine.spec.ts +496 -0
- package/src/server/sync/engine.ts +255 -0
- package/src/server/sync/http.ts +316 -0
- package/src/server/sync/httpRemote.spec.ts +158 -0
- package/src/server/sync/index.ts +90 -0
- package/src/server/sync/opLog.spec.ts +110 -0
- package/src/server/sync/opLog.ts +189 -0
- package/src/server/sync/planner.spec.ts +53 -0
- package/src/server/sync/planner.ts +62 -0
- package/src/server/sync/status.spec.ts +92 -0
- package/src/server/sync/status.ts +108 -0
- package/src/server/sync/timer.spec.ts +150 -0
- package/src/server/sync/timer.ts +207 -0
- package/src/server/sync/tokens.spec.ts +38 -0
- package/src/server/sync/tokens.ts +94 -0
- package/src/server/sync/types.ts +108 -0
- package/src/server/ws/eventBus.spec.ts +67 -0
- package/src/server/ws/eventBus.ts +46 -0
- package/src/server/ws/hub.integration.spec.ts +93 -0
- package/src/server/ws/hub.spec.ts +282 -0
- package/src/server/ws/hub.ts +168 -0
- package/src/server/ws/index.ts +20 -0
- package/src/server/ws/presence.spec.ts +27 -0
- package/src/server/ws/presence.ts +26 -0
- package/src/server/ws/room.spec.ts +36 -0
- package/src/server/ws/room.ts +29 -0
- package/src/server/ws/types.ts +134 -0
- package/src/skippedTestsAreAnswered.spec.ts +215 -0
- package/src/testTmpRoot.spec.ts +102 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The incident store, and the reconcile step that is the whole dedupe promise.
|
|
3
|
+
*
|
|
4
|
+
* ── The one rule ────────────────────────────────────────────────────────────
|
|
5
|
+
* `reconcile()` is the ONLY way an incident changes state, and it is what
|
|
6
|
+
* decides whether anything is notified. A detector hands it the complete set of
|
|
7
|
+
* conditions that are true RIGHT NOW; the store diffs that against what it
|
|
8
|
+
* already holds. Three things can come out of the diff — opened, escalated,
|
|
9
|
+
* resolved — and everything else is a counter bump that notifies nobody.
|
|
10
|
+
* Because the diff is set-shaped rather than event-shaped, a poller running
|
|
11
|
+
* every five minutes for a week produces exactly two messages about one broken
|
|
12
|
+
* thing: one when it broke, one when it was fixed.
|
|
13
|
+
*
|
|
14
|
+
* 🔴 The subtle half is the RESOLVE, and it is where a naive version of this
|
|
15
|
+
* lies to its owner. A detector that throws, times out, or is not registered on
|
|
16
|
+
* this host reports nothing — and "reported nothing" must never be read as
|
|
17
|
+
* "everything it watches is fixed", or a crashed detector cheerfully announces
|
|
18
|
+
* that an outage is over. Two things prevent that: `reconcile` only ever
|
|
19
|
+
* resolves fingerprints belonging to the check it was called for AND inside the
|
|
20
|
+
* namespaces that check declares it is authoritative for, and `runIncidentSweep`
|
|
21
|
+
* (`checks.ts`) does not call `reconcile` at all for a check that threw.
|
|
22
|
+
*
|
|
23
|
+
* ── Where the file lives ────────────────────────────────────────────────────
|
|
24
|
+
* Whatever `Database` the caller opens. The console keeps it in an incidents
|
|
25
|
+
* database of its own under the host's app-data root, deliberately NOT in the
|
|
26
|
+
* metrics database: metrics are capped, regenerable telemetry that trims on write, and
|
|
27
|
+
* an incident is a governed record whose whole value is that it survives — most
|
|
28
|
+
* of all across the restart a deploy of the console itself performs.
|
|
29
|
+
*/
|
|
30
|
+
import type { Database } from "bun:sqlite";
|
|
31
|
+
import { runMigrations } from "../migration/runner";
|
|
32
|
+
import { INCIDENT_MIGRATIONS, INCIDENTS_TABLE } from "./migrations";
|
|
33
|
+
import {
|
|
34
|
+
fingerprint,
|
|
35
|
+
type Incident,
|
|
36
|
+
type IncidentFact,
|
|
37
|
+
type IncidentReport,
|
|
38
|
+
type IncidentTransitions,
|
|
39
|
+
} from "./types";
|
|
40
|
+
|
|
41
|
+
interface Row {
|
|
42
|
+
fingerprint: string;
|
|
43
|
+
source: string;
|
|
44
|
+
kind: string;
|
|
45
|
+
subject: string;
|
|
46
|
+
severity: string;
|
|
47
|
+
state: string;
|
|
48
|
+
title: string;
|
|
49
|
+
what_broke: string;
|
|
50
|
+
what_it_blocks: string;
|
|
51
|
+
what_to_do: string;
|
|
52
|
+
facts_json: string | null;
|
|
53
|
+
first_seen: number;
|
|
54
|
+
last_seen: number;
|
|
55
|
+
seen_count: number;
|
|
56
|
+
episodes: number;
|
|
57
|
+
acknowledged_at: number | null;
|
|
58
|
+
resolved_at: number | null;
|
|
59
|
+
notified_at: number | null;
|
|
60
|
+
notify_result: string | null;
|
|
61
|
+
resolved_notified_at: number | null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const toIncident = (r: Row): Incident => ({
|
|
65
|
+
fingerprint: r.fingerprint,
|
|
66
|
+
source: r.source,
|
|
67
|
+
kind: r.kind,
|
|
68
|
+
subject: r.subject,
|
|
69
|
+
severity: r.severity === "blocking" ? "blocking" : "warning",
|
|
70
|
+
state: r.state === "open" ? "open" : r.state === "acknowledged" ? "acknowledged" : "resolved",
|
|
71
|
+
title: r.title,
|
|
72
|
+
whatBroke: r.what_broke,
|
|
73
|
+
whatItBlocks: r.what_it_blocks,
|
|
74
|
+
whatToDo: r.what_to_do,
|
|
75
|
+
facts: r.facts_json ? (JSON.parse(r.facts_json) as Record<string, IncidentFact>) : undefined,
|
|
76
|
+
firstSeen: r.first_seen,
|
|
77
|
+
lastSeen: r.last_seen,
|
|
78
|
+
seenCount: r.seen_count,
|
|
79
|
+
episodes: r.episodes,
|
|
80
|
+
acknowledgedAt: r.acknowledged_at,
|
|
81
|
+
resolvedAt: r.resolved_at,
|
|
82
|
+
notifiedAt: r.notified_at,
|
|
83
|
+
notifyResult: r.notify_result,
|
|
84
|
+
resolvedNotifiedAt: r.resolved_notified_at,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The privacy gate, enforced rather than reviewed. `facts` is for numbers —
|
|
89
|
+
* bytes free, items failed, commits behind — and a string slipping in there is
|
|
90
|
+
* how a file name reaches an SMS. See the header of `types.ts`.
|
|
91
|
+
*
|
|
92
|
+
* It throws rather than sanitising, because a detector author meets the failure
|
|
93
|
+
* in their own test run, which is the only moment the mistake is cheap.
|
|
94
|
+
*/
|
|
95
|
+
export function assertNoContent(report: IncidentReport): void {
|
|
96
|
+
for (const [key, value] of Object.entries(report.facts ?? {})) {
|
|
97
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null) continue;
|
|
98
|
+
throw new Error(
|
|
99
|
+
`incident ${fingerprint(report)}: fact "${key}" is a ${typeof value}. ` +
|
|
100
|
+
"facts take numbers, booleans and null only — a string here is how private " +
|
|
101
|
+
"content reaches a text message. Put the words in whatBroke / whatItBlocks / " +
|
|
102
|
+
"whatToDo, which a detector's author writes and reviews.",
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface ReconcileOptions {
|
|
108
|
+
/**
|
|
109
|
+
* The `source:kind:` prefixes this check is authoritative for on this run.
|
|
110
|
+
* Resolving is confined to them, so one detector can never resolve another's
|
|
111
|
+
* incidents — and a check that RAN and found nothing can still clear its own,
|
|
112
|
+
* which a report list alone cannot express (an empty array is
|
|
113
|
+
* indistinguishable from "did not run"). `runIncidentSweep` derives these
|
|
114
|
+
* from the check's declared `kinds`; omitted, they fall back to whatever the
|
|
115
|
+
* reports mention, which is the safe direction to be wrong in.
|
|
116
|
+
*/
|
|
117
|
+
namespaces?: string[];
|
|
118
|
+
now?: number;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface IncidentStore {
|
|
122
|
+
readonly db: Database;
|
|
123
|
+
/** Newest activity first. `state: "active"` means open + acknowledged. */
|
|
124
|
+
list: (opts?: { state?: Incident["state"] | "active"; limit?: number }) => Incident[];
|
|
125
|
+
get: (fp: string) => Incident | null;
|
|
126
|
+
/** The dedupe engine. See the module header. */
|
|
127
|
+
reconcile: (
|
|
128
|
+
checkKey: string,
|
|
129
|
+
reports: IncidentReport[],
|
|
130
|
+
opts?: ReconcileOptions,
|
|
131
|
+
) => IncidentTransitions;
|
|
132
|
+
/** Record that the OPEN notification for these fingerprints went out. */
|
|
133
|
+
markNotified: (fps: string[], result: string, now?: number) => void;
|
|
134
|
+
/** Record that the RESOLVED notification went out. */
|
|
135
|
+
markResolvedNotified: (fps: string[], now?: number) => void;
|
|
136
|
+
/** The owner has seen it: stop counting it as needing attention, keep it listed. */
|
|
137
|
+
acknowledge: (fp: string, now?: number) => boolean;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Open the store over an existing database. The caller owns the `Database` (and
|
|
142
|
+
* its lifetime) — this primitive owns one table in it.
|
|
143
|
+
*/
|
|
144
|
+
export function createIncidentStore(db: Database): IncidentStore {
|
|
145
|
+
runMigrations(db, INCIDENT_MIGRATIONS);
|
|
146
|
+
|
|
147
|
+
const selectOne = db.prepare(`SELECT * FROM ${INCIDENTS_TABLE} WHERE fingerprint = ?`);
|
|
148
|
+
const insert = db.prepare(`INSERT INTO ${INCIDENTS_TABLE} (
|
|
149
|
+
fingerprint, source, check_key, kind, subject, severity, state, title,
|
|
150
|
+
what_broke, what_it_blocks, what_to_do, facts_json,
|
|
151
|
+
first_seen, last_seen, seen_count, episodes
|
|
152
|
+
) VALUES (?, ?, ?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, 1, 1)`);
|
|
153
|
+
/** A NEW episode of a fingerprint that had resolved. Counters restart; `episodes` does not. */
|
|
154
|
+
const reopen = db.prepare(`UPDATE ${INCIDENTS_TABLE} SET
|
|
155
|
+
state = 'open', severity = ?, title = ?, what_broke = ?, what_it_blocks = ?,
|
|
156
|
+
what_to_do = ?, facts_json = ?, first_seen = ?, last_seen = ?, seen_count = 1,
|
|
157
|
+
episodes = episodes + 1, acknowledged_at = NULL, resolved_at = NULL,
|
|
158
|
+
notified_at = NULL, notify_result = NULL, resolved_notified_at = NULL
|
|
159
|
+
WHERE fingerprint = ?`);
|
|
160
|
+
/**
|
|
161
|
+
* Observed again. The words and the facts are REFRESHED — the numbers move,
|
|
162
|
+
* and "17 GB free" must not stay frozen at whatever it was on Tuesday — but
|
|
163
|
+
* nothing about the lifecycle moves, so no transition is emitted and nothing
|
|
164
|
+
* is sent. This statement is the dedupe, in one place.
|
|
165
|
+
*/
|
|
166
|
+
const touch = db.prepare(`UPDATE ${INCIDENTS_TABLE} SET
|
|
167
|
+
last_seen = ?, seen_count = seen_count + 1, title = ?, what_broke = ?,
|
|
168
|
+
what_it_blocks = ?, what_to_do = ?, facts_json = ?, severity = ?
|
|
169
|
+
WHERE fingerprint = ?`);
|
|
170
|
+
const resolveStmt = db.prepare(
|
|
171
|
+
`UPDATE ${INCIDENTS_TABLE} SET state = 'resolved', resolved_at = ? WHERE fingerprint = ?`,
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const store: IncidentStore = {
|
|
175
|
+
db,
|
|
176
|
+
|
|
177
|
+
list(opts = {}) {
|
|
178
|
+
const limit = opts.limit ?? 200;
|
|
179
|
+
if (opts.state === "active") {
|
|
180
|
+
return (
|
|
181
|
+
db
|
|
182
|
+
.prepare(
|
|
183
|
+
`SELECT * FROM ${INCIDENTS_TABLE} WHERE state IN ('open','acknowledged')
|
|
184
|
+
ORDER BY last_seen DESC LIMIT ?`,
|
|
185
|
+
)
|
|
186
|
+
.all(limit) as Row[]
|
|
187
|
+
).map(toIncident);
|
|
188
|
+
}
|
|
189
|
+
if (opts.state) {
|
|
190
|
+
return (
|
|
191
|
+
db
|
|
192
|
+
.prepare(
|
|
193
|
+
`SELECT * FROM ${INCIDENTS_TABLE} WHERE state = ? ORDER BY last_seen DESC LIMIT ?`,
|
|
194
|
+
)
|
|
195
|
+
.all(opts.state, limit) as Row[]
|
|
196
|
+
).map(toIncident);
|
|
197
|
+
}
|
|
198
|
+
return (
|
|
199
|
+
db
|
|
200
|
+
.prepare(`SELECT * FROM ${INCIDENTS_TABLE} ORDER BY last_seen DESC LIMIT ?`)
|
|
201
|
+
.all(limit) as Row[]
|
|
202
|
+
).map(toIncident);
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
get(fp) {
|
|
206
|
+
const row = selectOne.get(fp) as Row | null;
|
|
207
|
+
return row ? toIncident(row) : null;
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
reconcile(checkKey, reports, opts = {}) {
|
|
211
|
+
const now = opts.now ?? Date.now();
|
|
212
|
+
const out: IncidentTransitions = { opened: [], escalated: [], resolved: [], unchanged: [] };
|
|
213
|
+
const seen = new Set<string>();
|
|
214
|
+
|
|
215
|
+
for (const report of reports) {
|
|
216
|
+
assertNoContent(report);
|
|
217
|
+
const fp = fingerprint(report);
|
|
218
|
+
seen.add(fp);
|
|
219
|
+
const facts = report.facts ? JSON.stringify(report.facts) : null;
|
|
220
|
+
const existing = selectOne.get(fp) as Row | null;
|
|
221
|
+
|
|
222
|
+
if (!existing) {
|
|
223
|
+
insert.run(
|
|
224
|
+
fp,
|
|
225
|
+
report.source,
|
|
226
|
+
checkKey,
|
|
227
|
+
report.kind,
|
|
228
|
+
report.subject,
|
|
229
|
+
report.severity,
|
|
230
|
+
report.title,
|
|
231
|
+
report.whatBroke,
|
|
232
|
+
report.whatItBlocks,
|
|
233
|
+
report.whatToDo,
|
|
234
|
+
facts,
|
|
235
|
+
now,
|
|
236
|
+
now,
|
|
237
|
+
);
|
|
238
|
+
const opened = store.get(fp);
|
|
239
|
+
if (opened) out.opened.push(opened);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (existing.state === "resolved") {
|
|
244
|
+
reopen.run(
|
|
245
|
+
report.severity,
|
|
246
|
+
report.title,
|
|
247
|
+
report.whatBroke,
|
|
248
|
+
report.whatItBlocks,
|
|
249
|
+
report.whatToDo,
|
|
250
|
+
facts,
|
|
251
|
+
now,
|
|
252
|
+
now,
|
|
253
|
+
fp,
|
|
254
|
+
);
|
|
255
|
+
const reopened = store.get(fp);
|
|
256
|
+
if (reopened) out.opened.push(reopened);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Still open, or acknowledged. The one thing left that can be worth a
|
|
261
|
+
// message is a WARNING that has become BLOCKING, because that changes
|
|
262
|
+
// which channels the incident is entitled to. Everything else is noise.
|
|
263
|
+
const escalating = existing.severity !== "blocking" && report.severity === "blocking";
|
|
264
|
+
touch.run(
|
|
265
|
+
now,
|
|
266
|
+
report.title,
|
|
267
|
+
report.whatBroke,
|
|
268
|
+
report.whatItBlocks,
|
|
269
|
+
report.whatToDo,
|
|
270
|
+
facts,
|
|
271
|
+
report.severity,
|
|
272
|
+
fp,
|
|
273
|
+
);
|
|
274
|
+
const current = store.get(fp);
|
|
275
|
+
if (!current) continue;
|
|
276
|
+
if (escalating) out.escalated.push(current);
|
|
277
|
+
else out.unchanged.push(current);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const prefixes = opts.namespaces ?? [
|
|
281
|
+
...new Set(reports.map((r) => `${r.source}:${r.kind}:`)),
|
|
282
|
+
];
|
|
283
|
+
const candidates = db
|
|
284
|
+
.prepare(
|
|
285
|
+
`SELECT * FROM ${INCIDENTS_TABLE} WHERE check_key = ? AND state IN ('open','acknowledged')`,
|
|
286
|
+
)
|
|
287
|
+
.all(checkKey) as Row[];
|
|
288
|
+
for (const row of candidates) {
|
|
289
|
+
if (seen.has(row.fingerprint)) continue;
|
|
290
|
+
// Outside the namespaces this run is authoritative for — leave it alone.
|
|
291
|
+
// With no namespaces at all (a check that declared none and reported
|
|
292
|
+
// none) nothing resolves, which is the correct reading of "I have no
|
|
293
|
+
// idea" rather than "everything is fine".
|
|
294
|
+
if (!prefixes.some((p) => row.fingerprint.startsWith(p))) continue;
|
|
295
|
+
resolveStmt.run(now, row.fingerprint);
|
|
296
|
+
const resolved = store.get(row.fingerprint);
|
|
297
|
+
if (resolved) out.resolved.push(resolved);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return out;
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
markNotified(fps, result, now = Date.now()) {
|
|
304
|
+
const stmt = db.prepare(
|
|
305
|
+
`UPDATE ${INCIDENTS_TABLE} SET notified_at = ?, notify_result = ? WHERE fingerprint = ?`,
|
|
306
|
+
);
|
|
307
|
+
for (const fp of fps) stmt.run(now, result, fp);
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
markResolvedNotified(fps, now = Date.now()) {
|
|
311
|
+
const stmt = db.prepare(
|
|
312
|
+
`UPDATE ${INCIDENTS_TABLE} SET resolved_notified_at = ? WHERE fingerprint = ?`,
|
|
313
|
+
);
|
|
314
|
+
for (const fp of fps) stmt.run(now, fp);
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
acknowledge(fp, now = Date.now()) {
|
|
318
|
+
const row = selectOne.get(fp) as Row | null;
|
|
319
|
+
if (!row || row.state !== "open") return false;
|
|
320
|
+
db.prepare(
|
|
321
|
+
`UPDATE ${INCIDENTS_TABLE} SET state = 'acknowledged', acknowledged_at = ?
|
|
322
|
+
WHERE fingerprint = ?`,
|
|
323
|
+
).run(now, fp);
|
|
324
|
+
return true;
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
return store;
|
|
329
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The incident contract — what a detector reports, and what the store keeps.
|
|
3
|
+
*
|
|
4
|
+
* ── Why an INCIDENT and not an event (2026-08-13, the owner) ────────────────
|
|
5
|
+
* "auto notifying me once per incident (it needs to avoid sending me the same
|
|
6
|
+
* problem over and over in duplicated notifications if it's polling for
|
|
7
|
+
* problems)". A poller that re-sends every five minutes is the failure mode
|
|
8
|
+
* that gets the whole feature muted, which puts him back where he started but
|
|
9
|
+
* with more noise. So the unit of this module is a *condition that is true for
|
|
10
|
+
* a while*, identified by a stable {@link fingerprint}, with a lifecycle —
|
|
11
|
+
* and a notification is attached to a TRANSITION of that lifecycle, never to
|
|
12
|
+
* an observation. Observing the same broken thing for the ninth hour running
|
|
13
|
+
* bumps a counter and sends nothing.
|
|
14
|
+
*
|
|
15
|
+
* ── 🔴 An incident carries WHAT failed, never the content ───────────────────
|
|
16
|
+
* These messages go to a phone and to an inbox, and several apps on this fleet
|
|
17
|
+
* are private (notes) or zero-knowledge by construction (vault). A file name,
|
|
18
|
+
* a note title or a vault key in an SMS is a leak by a different door. So the
|
|
19
|
+
* shape below has no free-form payload: `subject` is a stable IDENTIFIER (an
|
|
20
|
+
* app key, a launchd label, a queue name), the three human fields are written
|
|
21
|
+
* by the detector's own author, and {@link IncidentReport.facts} takes NUMBERS
|
|
22
|
+
* and enum-ish strings only. `assertNoContent` in `store.ts` enforces the last
|
|
23
|
+
* one at write time rather than trusting a reviewer.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** How loud an incident is. There are only two, on purpose — see `notifier.ts`. */
|
|
27
|
+
export type IncidentSeverity =
|
|
28
|
+
/** The owner's own examples: "can't deploy, can't ingest files". Email AND text. */
|
|
29
|
+
| "blocking"
|
|
30
|
+
/** Worth knowing, in-app only. A warning that texts him is a warning that mutes the channel. */
|
|
31
|
+
| "warning";
|
|
32
|
+
|
|
33
|
+
/** Where an incident is in its life. */
|
|
34
|
+
export type IncidentState =
|
|
35
|
+
/** Still true, not yet dealt with. */
|
|
36
|
+
| "open"
|
|
37
|
+
/** Still true; the owner has seen it and does not want to be told again. */
|
|
38
|
+
| "acknowledged"
|
|
39
|
+
/** No longer reported by its detector. */
|
|
40
|
+
| "resolved";
|
|
41
|
+
|
|
42
|
+
/** A fact attached to an incident. Numbers and enum-ish strings only — see the header. */
|
|
43
|
+
export type IncidentFact = number | boolean | null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* One condition, as a detector reports it. The detector does NOT decide whether
|
|
47
|
+
* this is new, whether to notify, or what the current state is — that is the
|
|
48
|
+
* store's job, and keeping it there is the whole dedupe guarantee.
|
|
49
|
+
*/
|
|
50
|
+
export interface IncidentReport {
|
|
51
|
+
/** Which app or service noticed it: `binary-server`, `station`, `orch`. */
|
|
52
|
+
source: string;
|
|
53
|
+
/** The detector that produced it, e.g. `disk-below-reserve`. Stable across runs. */
|
|
54
|
+
kind: string;
|
|
55
|
+
/**
|
|
56
|
+
* WHAT the condition is about, as a stable identifier — an app key, a launchd
|
|
57
|
+
* label, a queue name. Never a file name, a title, or anything a person typed.
|
|
58
|
+
*/
|
|
59
|
+
subject: string;
|
|
60
|
+
severity: IncidentSeverity;
|
|
61
|
+
/** One line, for a notification subject and a table row. Names the app. */
|
|
62
|
+
title: string;
|
|
63
|
+
/** ELI5: what actually broke. Assume he does not know what your daemon is. */
|
|
64
|
+
whatBroke: string;
|
|
65
|
+
/** ELI5: what it stops him doing. This is the sentence that earns the text message. */
|
|
66
|
+
whatItBlocks: string;
|
|
67
|
+
/** ELI5: what to do about it. A runnable command carries its own `cd` (fleet rule). */
|
|
68
|
+
whatToDo: string;
|
|
69
|
+
/** Numbers only — bytes free, items failed, commits behind. See the header. */
|
|
70
|
+
facts?: Record<string, IncidentFact>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** A stored incident: a report, plus everything the store knows about its life. */
|
|
74
|
+
export interface Incident extends IncidentReport {
|
|
75
|
+
fingerprint: string;
|
|
76
|
+
state: IncidentState;
|
|
77
|
+
/** Epoch ms of the first observation of this episode. */
|
|
78
|
+
firstSeen: number;
|
|
79
|
+
/** Epoch ms of the most recent observation. */
|
|
80
|
+
lastSeen: number;
|
|
81
|
+
/** How many sweeps have observed it in this episode. */
|
|
82
|
+
seenCount: number;
|
|
83
|
+
/** How many times this fingerprint has opened, ever. A flapper is visible. */
|
|
84
|
+
episodes: number;
|
|
85
|
+
acknowledgedAt: number | null;
|
|
86
|
+
resolvedAt: number | null;
|
|
87
|
+
/** When the OPEN notification went out, and what happened to each channel. */
|
|
88
|
+
notifiedAt: number | null;
|
|
89
|
+
notifyResult: string | null;
|
|
90
|
+
/** When the RESOLVED notification went out. */
|
|
91
|
+
resolvedNotifiedAt: number | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* What one sweep changed. Only these three lists produce notifications — an
|
|
96
|
+
* incident merely observed again appears in none of them.
|
|
97
|
+
*/
|
|
98
|
+
export interface IncidentTransitions {
|
|
99
|
+
/** Newly true, or true again after a resolve. Notify. */
|
|
100
|
+
opened: Incident[];
|
|
101
|
+
/** Was a warning, is now blocking. Notify — the channel set changed. */
|
|
102
|
+
escalated: Incident[];
|
|
103
|
+
/** No longer reported. Notify once, so "is it fixed?" is answered without asking. */
|
|
104
|
+
resolved: Incident[];
|
|
105
|
+
/** Observed again while already open. **Never notified.** Here so a test can see it. */
|
|
106
|
+
unchanged: Incident[];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* A stable identity for a condition. Deliberately NOT a hash of the message:
|
|
111
|
+
* an author who improves the wording of `whatToDo` must not thereby re-alert
|
|
112
|
+
* the owner about a problem he already knows about.
|
|
113
|
+
*/
|
|
114
|
+
export function fingerprint(report: Pick<IncidentReport, "source" | "kind" | "subject">): string {
|
|
115
|
+
return `${report.source}:${report.kind}:${report.subject}`;
|
|
116
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// cursedbelt server toolkit — native Hono on Bun.serve. Consumed by ca + ru.
|
|
2
|
+
//
|
|
3
|
+
// HTTP app + middleware + the canonical error envelope + a versioned SQLite
|
|
4
|
+
// migration runner + Kysely-typed access for the plumbing tables. Business routes,
|
|
5
|
+
// auth model, sharing, jobs, and `data JSON` tables stay in the apps; cursedbelt
|
|
6
|
+
// owns the plumbing.
|
|
7
|
+
|
|
8
|
+
// ── ctgr (isomorphic codec re-exports + the Hono GET-tunnel transport) ───────
|
|
9
|
+
export {
|
|
10
|
+
ChunkStore,
|
|
11
|
+
type ChunkStoreOpts,
|
|
12
|
+
CTGR_WIRE_VERSION,
|
|
13
|
+
type CtgrDecoded,
|
|
14
|
+
type CtgrMethod,
|
|
15
|
+
decodeRequest,
|
|
16
|
+
type EncodedRequest,
|
|
17
|
+
type EncodeOpts,
|
|
18
|
+
encodeRequest,
|
|
19
|
+
type UploadedFile,
|
|
20
|
+
} from 'cursedbelt-core/ctgr';
|
|
21
|
+
// ── HTTP app ────────────────────────────────────────────────────────────────
|
|
22
|
+
export { type CreateAppOpts, createApp, type ServeBunOpts, serveBun } from './app';
|
|
23
|
+
// ── Auth toolkit (task 26): jose JWT, cookies, CSRF, getOnly, session store, ──
|
|
24
|
+
// login throttle, argon2id passwords, TOTP, vault crypto, the composed middleware.
|
|
25
|
+
export {
|
|
26
|
+
type AppJwtPayload,
|
|
27
|
+
AUTH_COOKIE_NAME,
|
|
28
|
+
type AuthEnv,
|
|
29
|
+
type AuthUser,
|
|
30
|
+
type AuthVariables,
|
|
31
|
+
type CreateSessionInput,
|
|
32
|
+
CSRF_COOKIE_NAME,
|
|
33
|
+
CSRF_HEADER_NAME,
|
|
34
|
+
type CsrfOptions,
|
|
35
|
+
clearAuthCookie,
|
|
36
|
+
createAuthMiddleware,
|
|
37
|
+
createCsrfMiddleware,
|
|
38
|
+
clientKeyOf,
|
|
39
|
+
clientKeyOfContext,
|
|
40
|
+
createLoginThrottle,
|
|
41
|
+
createSessionStore,
|
|
42
|
+
createRs256FileTokenSigner,
|
|
43
|
+
DEFAULT_TOTP_ISSUER,
|
|
44
|
+
decryptVaultItem,
|
|
45
|
+
deriveVaultKey,
|
|
46
|
+
encryptVaultItem,
|
|
47
|
+
generateRecoveryCodes,
|
|
48
|
+
generateTotpSecret,
|
|
49
|
+
getOnlyEnforcement,
|
|
50
|
+
getTotpUri,
|
|
51
|
+
hashPassword,
|
|
52
|
+
isGetOnlyViolation,
|
|
53
|
+
type LoginThrottle,
|
|
54
|
+
type LoginThrottleOptions,
|
|
55
|
+
type ThrottleVerdict,
|
|
56
|
+
needsRehash,
|
|
57
|
+
type Rs256FileTokenSignerOptions,
|
|
58
|
+
type Session,
|
|
59
|
+
type SessionStore,
|
|
60
|
+
type SessionStoreOptions,
|
|
61
|
+
signToken,
|
|
62
|
+
type TokenPurpose,
|
|
63
|
+
verifyPassword,
|
|
64
|
+
verifyPurposeToken,
|
|
65
|
+
verifyRecoveryCode,
|
|
66
|
+
verifyToken,
|
|
67
|
+
verifyTotpCode,
|
|
68
|
+
} from './auth';
|
|
69
|
+
export type { CursedbeltEnv, CursedbeltVariables } from './context';
|
|
70
|
+
export { buildRoutes, CTGR_ROUTE_PATTERN, getCtgrDecoded, unGETify } from './ctgr';
|
|
71
|
+
// ── Kysely-typed plumbing tables ────────────────────────────────────────────
|
|
72
|
+
export { createKysely, type PlumbingDb } from './db/kysely';
|
|
73
|
+
export type {
|
|
74
|
+
AppConfigRow,
|
|
75
|
+
AuthSessionRow,
|
|
76
|
+
EmailFailureRow,
|
|
77
|
+
EventLogRow,
|
|
78
|
+
JobRunRow,
|
|
79
|
+
JobStateRow,
|
|
80
|
+
MigrationRow,
|
|
81
|
+
PlumbingSchema,
|
|
82
|
+
RequestMetricRow,
|
|
83
|
+
SystemSampleRow,
|
|
84
|
+
} from './db/plumbingTypes';
|
|
85
|
+
// ── Errors ──────────────────────────────────────────────────────────────────
|
|
86
|
+
export {
|
|
87
|
+
ApiError,
|
|
88
|
+
type ApiErrorOptions,
|
|
89
|
+
type ErrorEnvelope,
|
|
90
|
+
isApiError,
|
|
91
|
+
toErrorEnvelope,
|
|
92
|
+
toValidationIssues,
|
|
93
|
+
VALIDATION_ERROR_CODE,
|
|
94
|
+
type ValidationIssue,
|
|
95
|
+
validationEnvelope,
|
|
96
|
+
} from './errors';
|
|
97
|
+
// ── Jobs & scheduler (task 29): plainjob-backed cron runner + restart-aware ───
|
|
98
|
+
// pollers + the due-row fire queue. App job *definitions* stay business.
|
|
99
|
+
export {
|
|
100
|
+
type CreateJobRunnerOptions,
|
|
101
|
+
createFireQueue,
|
|
102
|
+
createJobRunner,
|
|
103
|
+
createPollingJob,
|
|
104
|
+
DEFAULT_FIRE_INTERVAL_MS,
|
|
105
|
+
DEFAULT_JOB_TIMEOUT_MS,
|
|
106
|
+
defaultJobLogger,
|
|
107
|
+
type FireQueue,
|
|
108
|
+
type FireQueueOpts,
|
|
109
|
+
type JobContext,
|
|
110
|
+
type JobDef,
|
|
111
|
+
type JobLogger,
|
|
112
|
+
type JobRunner,
|
|
113
|
+
type JobRunRecord,
|
|
114
|
+
JobTimeoutError,
|
|
115
|
+
type PollingJob,
|
|
116
|
+
type PollingJobOpts,
|
|
117
|
+
} from './jobs';
|
|
118
|
+
// ── Media adapter (task 19): image rendering via sharp (lazy/optional peer) + ──
|
|
119
|
+
// video trim / probe / thumbnail via native ffmpeg. Also at the dedicated
|
|
120
|
+
// media-bun entry below; sharp is imported lazily inside renderImage,
|
|
121
|
+
// so importing this barrel never loads the native binary.
|
|
122
|
+
export {
|
|
123
|
+
buildProbeArgs,
|
|
124
|
+
buildThumbnailArgs,
|
|
125
|
+
buildTrimArgs,
|
|
126
|
+
extractThumbnail,
|
|
127
|
+
ffmpegTimeToSeconds,
|
|
128
|
+
isFfmpegAvailable,
|
|
129
|
+
isFfprobeAvailable,
|
|
130
|
+
type ProbeResult,
|
|
131
|
+
parseFfmpegProgress,
|
|
132
|
+
parseFfprobe,
|
|
133
|
+
probeMedia,
|
|
134
|
+
renderImage,
|
|
135
|
+
trimVideo,
|
|
136
|
+
type VideoCodecPlan,
|
|
137
|
+
videoCodecPlan,
|
|
138
|
+
} from './media-bun';
|
|
139
|
+
// ── Metrics ───────────────────────────────────────────────────────────────────
|
|
140
|
+
export {
|
|
141
|
+
createMetricsBuffer,
|
|
142
|
+
type MetricRow,
|
|
143
|
+
type MetricsBuffer,
|
|
144
|
+
type MetricsBufferOptions,
|
|
145
|
+
} from './metrics/metricsBuffer';
|
|
146
|
+
export { normalizeRoute } from './metrics/normalizeRoute';
|
|
147
|
+
// ── Middleware ────────────────────────────────────────────────────────────────
|
|
148
|
+
export { correlationId } from './middleware/correlationId';
|
|
149
|
+
export { type CorsOpts, corsAllowlist, corsOptsFromEnv } from './middleware/corsAllowlist';
|
|
150
|
+
export { errorEnvelope } from './middleware/errorEnvelope';
|
|
151
|
+
export { crossOriginRefusal } from './middleware/localOrigin';
|
|
152
|
+
export { clientIp, createRateLimiter, type RateLimitOpts } from './middleware/rateLimit';
|
|
153
|
+
export { type RequestLoggerOpts, requestLogger } from './middleware/requestLogger';
|
|
154
|
+
export {
|
|
155
|
+
type CspDirectives,
|
|
156
|
+
type SecurityHeadersOpts,
|
|
157
|
+
securityHeaders,
|
|
158
|
+
} from './middleware/securityHeaders';
|
|
159
|
+
// ── zod validation toolkit ────────────────────────────────────────────────────
|
|
160
|
+
// (the `validationEnvelope`/`toValidationIssues`/`ValidationIssue` builders now
|
|
161
|
+
// live with the canonical envelope in `./errors`, re-exported above.)
|
|
162
|
+
export { type ZValidatorTarget, zValidator } from './middleware/zValidator';
|
|
163
|
+
// ── Migration runner ──────────────────────────────────────────────────────────
|
|
164
|
+
export { addColumnIfMissing, applyRecommendedPragmas, columnExists, runMigrations } from './migration/runner';
|
|
165
|
+
export type { Migration } from './migration/types';
|
|
166
|
+
// ── Audit log: the SQLite-backed AuditSink cursedshell's service dispatch ─────
|
|
167
|
+
// writes to (see `cwip/audit` for the storage-agnostic contract + the
|
|
168
|
+
// zero-config in-memory default).
|
|
169
|
+
export {
|
|
170
|
+
AUDIT_LOG_MIGRATIONS,
|
|
171
|
+
auditStateAt,
|
|
172
|
+
auditStateAtVersion,
|
|
173
|
+
auditStep,
|
|
174
|
+
createSqliteAuditSink,
|
|
175
|
+
} from './audit';
|
|
176
|
+
// ── SQLite toolkit extras (task 30): FTS5 ranked search + DDL generator, the ───
|
|
177
|
+
// read-only DB viewer middleware, the VACUUM-INTO backup service, DB health probes.
|
|
178
|
+
export {
|
|
179
|
+
applyFtsSchema,
|
|
180
|
+
type BackupInfo,
|
|
181
|
+
buildFtsSchema,
|
|
182
|
+
clampLimit,
|
|
183
|
+
clampOffset,
|
|
184
|
+
collectSqliteStats,
|
|
185
|
+
createFts5Search,
|
|
186
|
+
createSqliteBackupService,
|
|
187
|
+
createSqliteHealthChecks,
|
|
188
|
+
createSqliteViewerMiddleware,
|
|
189
|
+
type DbStats,
|
|
190
|
+
exportSqliteSnapshot,
|
|
191
|
+
exportSqliteTable,
|
|
192
|
+
type Fts5Search,
|
|
193
|
+
type FtsHighlightOpts,
|
|
194
|
+
type FtsResult,
|
|
195
|
+
type FtsSearchOpts,
|
|
196
|
+
type FtsSnippetOpts,
|
|
197
|
+
type FtsTableSpec,
|
|
198
|
+
type ImportMode,
|
|
199
|
+
type ImportResult,
|
|
200
|
+
importRowsIntoSqliteTable,
|
|
201
|
+
isKnownTable,
|
|
202
|
+
isReadOnlySql,
|
|
203
|
+
listSqliteTables,
|
|
204
|
+
NotReadOnlyError,
|
|
205
|
+
quoteIdent,
|
|
206
|
+
type RestoreResult,
|
|
207
|
+
readSqliteTable,
|
|
208
|
+
restoreSqliteSnapshot,
|
|
209
|
+
runReadonlySqlite,
|
|
210
|
+
type SnapshotExport,
|
|
211
|
+
type SqliteBackupOpts,
|
|
212
|
+
type SqliteBackupS3Opts,
|
|
213
|
+
type SqliteBackupService,
|
|
214
|
+
type SqliteHealthCheck,
|
|
215
|
+
type SqliteHealthOpts,
|
|
216
|
+
type SqliteHealthResult,
|
|
217
|
+
type SqliteHealthStatus,
|
|
218
|
+
type SqliteTableInfo,
|
|
219
|
+
type SqliteTablePage,
|
|
220
|
+
sanitizeFtsQuery,
|
|
221
|
+
snapshotSqlite,
|
|
222
|
+
type TableExport,
|
|
223
|
+
type TableExportFormat,
|
|
224
|
+
type TableStat,
|
|
225
|
+
UnknownTableError,
|
|
226
|
+
} from './sqlite';
|
|
227
|
+
// ── WebSocket hub (task 28): Bun-native upgrade, channel registry, heartbeat, ──
|
|
228
|
+
// presence-as-a-view, room helpers, and the push-only event-bus subset (ru).
|
|
229
|
+
export {
|
|
230
|
+
computePresence,
|
|
231
|
+
createEventBus,
|
|
232
|
+
createWsHub,
|
|
233
|
+
type EventBus,
|
|
234
|
+
type EventBusData,
|
|
235
|
+
joinRoom,
|
|
236
|
+
leaveRoom,
|
|
237
|
+
type PresenceEntry,
|
|
238
|
+
type PresenceState,
|
|
239
|
+
ROOM_META_KEY,
|
|
240
|
+
roomOf,
|
|
241
|
+
type WsChannel,
|
|
242
|
+
type WsClient,
|
|
243
|
+
type WsData,
|
|
244
|
+
type WsHandshake,
|
|
245
|
+
type WsHub,
|
|
246
|
+
type WsHubOpts,
|
|
247
|
+
type WsMessage,
|
|
248
|
+
} from './ws';
|