@de-otio/trellis 0.4.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/db.d.ts +36 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +39 -0
- package/dist/db.js.map +1 -0
- package/dist/env.d.ts +107 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +268 -0
- package/dist/env.js.map +1 -0
- package/dist/extensions.d.ts +15 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +35 -0
- package/dist/extensions.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/lambda/cleanup-cron.d.ts +2 -0
- package/dist/lambda/cleanup-cron.d.ts.map +1 -0
- package/dist/lambda/cleanup-cron.js +38 -0
- package/dist/lambda/cleanup-cron.js.map +1 -0
- package/dist/lambda/create-auth-challenge.d.ts +2 -0
- package/dist/lambda/create-auth-challenge.d.ts.map +1 -0
- package/dist/lambda/create-auth-challenge.js +108 -0
- package/dist/lambda/create-auth-challenge.js.map +1 -0
- package/dist/lambda/custom-message.d.ts +3 -0
- package/dist/lambda/custom-message.d.ts.map +1 -0
- package/dist/lambda/custom-message.js +29 -0
- package/dist/lambda/custom-message.js.map +1 -0
- package/dist/lambda/define-auth-challenge.d.ts +2 -0
- package/dist/lambda/define-auth-challenge.d.ts.map +1 -0
- package/dist/lambda/define-auth-challenge.js +27 -0
- package/dist/lambda/define-auth-challenge.js.map +1 -0
- package/dist/lambda/delete-account-worker.d.ts +3 -0
- package/dist/lambda/delete-account-worker.d.ts.map +1 -0
- package/dist/lambda/delete-account-worker.js +122 -0
- package/dist/lambda/delete-account-worker.js.map +1 -0
- package/dist/lambda/diagnostics-proxy.d.ts +6 -0
- package/dist/lambda/diagnostics-proxy.d.ts.map +1 -0
- package/dist/lambda/diagnostics-proxy.js +154 -0
- package/dist/lambda/diagnostics-proxy.js.map +1 -0
- package/dist/lambda/e2e-sweeper.d.ts +18 -0
- package/dist/lambda/e2e-sweeper.d.ts.map +1 -0
- package/dist/lambda/e2e-sweeper.js +127 -0
- package/dist/lambda/e2e-sweeper.js.map +1 -0
- package/dist/lambda/federation-outbox-worker.d.ts +3 -0
- package/dist/lambda/federation-outbox-worker.d.ts.map +1 -0
- package/dist/lambda/federation-outbox-worker.js +11 -0
- package/dist/lambda/federation-outbox-worker.js.map +1 -0
- package/dist/lambda/followers-events-worker.d.ts +3 -0
- package/dist/lambda/followers-events-worker.d.ts.map +1 -0
- package/dist/lambda/followers-events-worker.js +11 -0
- package/dist/lambda/followers-events-worker.js.map +1 -0
- package/dist/lambda/hourly-cron.d.ts +2 -0
- package/dist/lambda/hourly-cron.d.ts.map +1 -0
- package/dist/lambda/hourly-cron.js +101 -0
- package/dist/lambda/hourly-cron.js.map +1 -0
- package/dist/lambda/link-check-worker.d.ts +3 -0
- package/dist/lambda/link-check-worker.d.ts.map +1 -0
- package/dist/lambda/link-check-worker.js +11 -0
- package/dist/lambda/link-check-worker.js.map +1 -0
- package/dist/lambda/maintenance-cron.d.ts +2 -0
- package/dist/lambda/maintenance-cron.d.ts.map +1 -0
- package/dist/lambda/maintenance-cron.js +127 -0
- package/dist/lambda/maintenance-cron.js.map +1 -0
- package/dist/lambda/media-processing-worker.d.ts +3 -0
- package/dist/lambda/media-processing-worker.d.ts.map +1 -0
- package/dist/lambda/media-processing-worker.js +95 -0
- package/dist/lambda/media-processing-worker.js.map +1 -0
- package/dist/lambda/media-reconciliation-worker.d.ts +3 -0
- package/dist/lambda/media-reconciliation-worker.d.ts.map +1 -0
- package/dist/lambda/media-reconciliation-worker.js +11 -0
- package/dist/lambda/media-reconciliation-worker.js.map +1 -0
- package/dist/lambda/nightly-cron.d.ts +2 -0
- package/dist/lambda/nightly-cron.d.ts.map +1 -0
- package/dist/lambda/nightly-cron.js +348 -0
- package/dist/lambda/nightly-cron.js.map +1 -0
- package/dist/lambda/post-confirmation.d.ts +3 -0
- package/dist/lambda/post-confirmation.d.ts.map +1 -0
- package/dist/lambda/post-confirmation.js +79 -0
- package/dist/lambda/post-confirmation.js.map +1 -0
- package/dist/lambda/pre-signup.d.ts +3 -0
- package/dist/lambda/pre-signup.d.ts.map +1 -0
- package/dist/lambda/pre-signup.js +35 -0
- package/dist/lambda/pre-signup.js.map +1 -0
- package/dist/lambda/pre-token-generation.d.ts +3 -0
- package/dist/lambda/pre-token-generation.d.ts.map +1 -0
- package/dist/lambda/pre-token-generation.js +79 -0
- package/dist/lambda/pre-token-generation.js.map +1 -0
- package/dist/lambda/tools/check-health.d.ts +6 -0
- package/dist/lambda/tools/check-health.d.ts.map +1 -0
- package/dist/lambda/tools/check-health.js +24 -0
- package/dist/lambda/tools/check-health.js.map +1 -0
- package/dist/lambda/tools/describe-services.d.ts +20 -0
- package/dist/lambda/tools/describe-services.d.ts.map +1 -0
- package/dist/lambda/tools/describe-services.js +41 -0
- package/dist/lambda/tools/describe-services.js.map +1 -0
- package/dist/lambda/tools/get-cost-report.d.ts +16 -0
- package/dist/lambda/tools/get-cost-report.d.ts.map +1 -0
- package/dist/lambda/tools/get-cost-report.js +54 -0
- package/dist/lambda/tools/get-cost-report.js.map +1 -0
- package/dist/lambda/tools/get-errors.d.ts +11 -0
- package/dist/lambda/tools/get-errors.d.ts.map +1 -0
- package/dist/lambda/tools/get-errors.js +62 -0
- package/dist/lambda/tools/get-errors.js.map +1 -0
- package/dist/lambda/tools/get-feature-flags.d.ts +8 -0
- package/dist/lambda/tools/get-feature-flags.d.ts.map +1 -0
- package/dist/lambda/tools/get-feature-flags.js +23 -0
- package/dist/lambda/tools/get-feature-flags.js.map +1 -0
- package/dist/lambda/tools/get-queue-status.d.ts +9 -0
- package/dist/lambda/tools/get-queue-status.d.ts.map +1 -0
- package/dist/lambda/tools/get-queue-status.js +46 -0
- package/dist/lambda/tools/get-queue-status.js.map +1 -0
- package/dist/lambda/tools/search-logs.d.ts +19 -0
- package/dist/lambda/tools/search-logs.d.ts.map +1 -0
- package/dist/lambda/tools/search-logs.js +55 -0
- package/dist/lambda/tools/search-logs.js.map +1 -0
- package/dist/lambda/tools/send-alert.d.ts +8 -0
- package/dist/lambda/tools/send-alert.d.ts.map +1 -0
- package/dist/lambda/tools/send-alert.js +29 -0
- package/dist/lambda/tools/send-alert.js.map +1 -0
- package/dist/lambda/verify-auth-challenge.d.ts +2 -0
- package/dist/lambda/verify-auth-challenge.d.ts.map +1 -0
- package/dist/lambda/verify-auth-challenge.js +35 -0
- package/dist/lambda/verify-auth-challenge.js.map +1 -0
- package/dist/lib/abuse-metrics.d.ts +44 -0
- package/dist/lib/abuse-metrics.d.ts.map +1 -0
- package/dist/lib/abuse-metrics.js +322 -0
- package/dist/lib/abuse-metrics.js.map +1 -0
- package/dist/lib/activitypub/activity-processor.d.ts +89 -0
- package/dist/lib/activitypub/activity-processor.d.ts.map +1 -0
- package/dist/lib/activitypub/activity-processor.js +709 -0
- package/dist/lib/activitypub/activity-processor.js.map +1 -0
- package/dist/lib/activitypub/activity-service.d.ts +47 -0
- package/dist/lib/activitypub/activity-service.d.ts.map +1 -0
- package/dist/lib/activitypub/activity-service.js +165 -0
- package/dist/lib/activitypub/activity-service.js.map +1 -0
- package/dist/lib/activitypub/actor.d.ts +44 -0
- package/dist/lib/activitypub/actor.d.ts.map +1 -0
- package/dist/lib/activitypub/actor.js +116 -0
- package/dist/lib/activitypub/actor.js.map +1 -0
- package/dist/lib/activitypub/audience-service.d.ts +52 -0
- package/dist/lib/activitypub/audience-service.d.ts.map +1 -0
- package/dist/lib/activitypub/audience-service.js +245 -0
- package/dist/lib/activitypub/audience-service.js.map +1 -0
- package/dist/lib/activitypub/crypto.d.ts +42 -0
- package/dist/lib/activitypub/crypto.d.ts.map +1 -0
- package/dist/lib/activitypub/crypto.js +129 -0
- package/dist/lib/activitypub/crypto.js.map +1 -0
- package/dist/lib/activitypub/delivery-service.d.ts +44 -0
- package/dist/lib/activitypub/delivery-service.d.ts.map +1 -0
- package/dist/lib/activitypub/delivery-service.js +259 -0
- package/dist/lib/activitypub/delivery-service.js.map +1 -0
- package/dist/lib/activitypub/dispatchers/entity-actor.d.ts +50 -0
- package/dist/lib/activitypub/dispatchers/entity-actor.d.ts.map +1 -0
- package/dist/lib/activitypub/dispatchers/entity-actor.js +247 -0
- package/dist/lib/activitypub/dispatchers/entity-actor.js.map +1 -0
- package/dist/lib/activitypub/dispatchers/group-actor.d.ts +47 -0
- package/dist/lib/activitypub/dispatchers/group-actor.d.ts.map +1 -0
- package/dist/lib/activitypub/dispatchers/group-actor.js +202 -0
- package/dist/lib/activitypub/dispatchers/group-actor.js.map +1 -0
- package/dist/lib/activitypub/dispatchers/user-actor.d.ts +47 -0
- package/dist/lib/activitypub/dispatchers/user-actor.d.ts.map +1 -0
- package/dist/lib/activitypub/dispatchers/user-actor.js +207 -0
- package/dist/lib/activitypub/dispatchers/user-actor.js.map +1 -0
- package/dist/lib/activitypub/dm-service.d.ts +35 -0
- package/dist/lib/activitypub/dm-service.d.ts.map +1 -0
- package/dist/lib/activitypub/dm-service.js +73 -0
- package/dist/lib/activitypub/dm-service.js.map +1 -0
- package/dist/lib/activitypub/entity-profile-service.d.ts +43 -0
- package/dist/lib/activitypub/entity-profile-service.d.ts.map +1 -0
- package/dist/lib/activitypub/entity-profile-service.js +80 -0
- package/dist/lib/activitypub/entity-profile-service.js.map +1 -0
- package/dist/lib/activitypub/fedify/config.d.ts +15 -0
- package/dist/lib/activitypub/fedify/config.d.ts.map +1 -0
- package/dist/lib/activitypub/fedify/config.js +38 -0
- package/dist/lib/activitypub/fedify/config.js.map +1 -0
- package/dist/lib/activitypub/fedify/context.d.ts +21 -0
- package/dist/lib/activitypub/fedify/context.d.ts.map +1 -0
- package/dist/lib/activitypub/fedify/context.js +67 -0
- package/dist/lib/activitypub/fedify/context.js.map +1 -0
- package/dist/lib/activitypub/fedify/runtime.d.ts +18 -0
- package/dist/lib/activitypub/fedify/runtime.d.ts.map +1 -0
- package/dist/lib/activitypub/fedify/runtime.js +26 -0
- package/dist/lib/activitypub/fedify/runtime.js.map +1 -0
- package/dist/lib/activitypub/friendship-service.d.ts +15 -0
- package/dist/lib/activitypub/friendship-service.d.ts.map +1 -0
- package/dist/lib/activitypub/friendship-service.js +26 -0
- package/dist/lib/activitypub/friendship-service.js.map +1 -0
- package/dist/lib/activitypub/group-service.d.ts +83 -0
- package/dist/lib/activitypub/group-service.d.ts.map +1 -0
- package/dist/lib/activitypub/group-service.js +301 -0
- package/dist/lib/activitypub/group-service.js.map +1 -0
- package/dist/lib/activitypub/http-signatures.d.ts +41 -0
- package/dist/lib/activitypub/http-signatures.d.ts.map +1 -0
- package/dist/lib/activitypub/http-signatures.js +284 -0
- package/dist/lib/activitypub/http-signatures.js.map +1 -0
- package/dist/lib/activitypub/jsonld.d.ts +39 -0
- package/dist/lib/activitypub/jsonld.d.ts.map +1 -0
- package/dist/lib/activitypub/jsonld.js +97 -0
- package/dist/lib/activitypub/jsonld.js.map +1 -0
- package/dist/lib/activitypub/listeners/friends-collection.d.ts +20 -0
- package/dist/lib/activitypub/listeners/friends-collection.d.ts.map +1 -0
- package/dist/lib/activitypub/listeners/friends-collection.js +105 -0
- package/dist/lib/activitypub/listeners/friends-collection.js.map +1 -0
- package/dist/lib/activitypub/listeners/http-signatures.d.ts +29 -0
- package/dist/lib/activitypub/listeners/http-signatures.d.ts.map +1 -0
- package/dist/lib/activitypub/listeners/http-signatures.js +208 -0
- package/dist/lib/activitypub/listeners/http-signatures.js.map +1 -0
- package/dist/lib/activitypub/listeners/inbox.d.ts +34 -0
- package/dist/lib/activitypub/listeners/inbox.d.ts.map +1 -0
- package/dist/lib/activitypub/listeners/inbox.js +226 -0
- package/dist/lib/activitypub/listeners/inbox.js.map +1 -0
- package/dist/lib/activitypub/listeners/outbox.d.ts +20 -0
- package/dist/lib/activitypub/listeners/outbox.d.ts.map +1 -0
- package/dist/lib/activitypub/listeners/outbox.js +117 -0
- package/dist/lib/activitypub/listeners/outbox.js.map +1 -0
- package/dist/lib/activitypub/remote-fetch-service.d.ts +108 -0
- package/dist/lib/activitypub/remote-fetch-service.d.ts.map +1 -0
- package/dist/lib/activitypub/remote-fetch-service.js +364 -0
- package/dist/lib/activitypub/remote-fetch-service.js.map +1 -0
- package/dist/lib/activitypub/services/abuse-prevention.d.ts +52 -0
- package/dist/lib/activitypub/services/abuse-prevention.d.ts.map +1 -0
- package/dist/lib/activitypub/services/abuse-prevention.js +118 -0
- package/dist/lib/activitypub/services/abuse-prevention.js.map +1 -0
- package/dist/lib/activitypub/services/dm-service-fedify.d.ts +46 -0
- package/dist/lib/activitypub/services/dm-service-fedify.d.ts.map +1 -0
- package/dist/lib/activitypub/services/dm-service-fedify.js +168 -0
- package/dist/lib/activitypub/services/dm-service-fedify.js.map +1 -0
- package/dist/lib/activitypub/services/fedify-converters.d.ts +51 -0
- package/dist/lib/activitypub/services/fedify-converters.d.ts.map +1 -0
- package/dist/lib/activitypub/services/fedify-converters.js +109 -0
- package/dist/lib/activitypub/services/fedify-converters.js.map +1 -0
- package/dist/lib/activitypub/services/fedify-delivery.d.ts +41 -0
- package/dist/lib/activitypub/services/fedify-delivery.d.ts.map +1 -0
- package/dist/lib/activitypub/services/fedify-delivery.js +186 -0
- package/dist/lib/activitypub/services/fedify-delivery.js.map +1 -0
- package/dist/lib/activitypub/services/follow-activity-service.d.ts +34 -0
- package/dist/lib/activitypub/services/follow-activity-service.d.ts.map +1 -0
- package/dist/lib/activitypub/services/follow-activity-service.js +64 -0
- package/dist/lib/activitypub/services/follow-activity-service.js.map +1 -0
- package/dist/lib/activitypub/services/post-service-fedify.d.ts +49 -0
- package/dist/lib/activitypub/services/post-service-fedify.d.ts.map +1 -0
- package/dist/lib/activitypub/services/post-service-fedify.js +281 -0
- package/dist/lib/activitypub/services/post-service-fedify.js.map +1 -0
- package/dist/lib/activitypub/services/remote-activity-handler.d.ts +22 -0
- package/dist/lib/activitypub/services/remote-activity-handler.d.ts.map +1 -0
- package/dist/lib/activitypub/services/remote-activity-handler.js +136 -0
- package/dist/lib/activitypub/services/remote-activity-handler.js.map +1 -0
- package/dist/lib/activitypub/standalone-mode.d.ts +34 -0
- package/dist/lib/activitypub/standalone-mode.d.ts.map +1 -0
- package/dist/lib/activitypub/standalone-mode.js +127 -0
- package/dist/lib/activitypub/standalone-mode.js.map +1 -0
- package/dist/lib/activitypub/webfinger/server.d.ts +16 -0
- package/dist/lib/activitypub/webfinger/server.d.ts.map +1 -0
- package/dist/lib/activitypub/webfinger/server.js +221 -0
- package/dist/lib/activitypub/webfinger/server.js.map +1 -0
- package/dist/lib/age-gate-middleware.d.ts +19 -0
- package/dist/lib/age-gate-middleware.d.ts.map +1 -0
- package/dist/lib/age-gate-middleware.js +26 -0
- package/dist/lib/age-gate-middleware.js.map +1 -0
- package/dist/lib/age-gate.d.ts +37 -0
- package/dist/lib/age-gate.d.ts.map +1 -0
- package/dist/lib/age-gate.js +96 -0
- package/dist/lib/age-gate.js.map +1 -0
- package/dist/lib/age-tier-transition.d.ts +21 -0
- package/dist/lib/age-tier-transition.d.ts.map +1 -0
- package/dist/lib/age-tier-transition.js +190 -0
- package/dist/lib/age-tier-transition.js.map +1 -0
- package/dist/lib/audit-logger.d.ts +142 -0
- package/dist/lib/audit-logger.d.ts.map +1 -0
- package/dist/lib/audit-logger.js +326 -0
- package/dist/lib/audit-logger.js.map +1 -0
- package/dist/lib/auth/cognito-jwt.d.ts +20 -0
- package/dist/lib/auth/cognito-jwt.d.ts.map +1 -0
- package/dist/lib/auth/cognito-jwt.js +56 -0
- package/dist/lib/auth/cognito-jwt.js.map +1 -0
- package/dist/lib/auth-context-manager.d.ts +116 -0
- package/dist/lib/auth-context-manager.d.ts.map +1 -0
- package/dist/lib/auth-context-manager.js +130 -0
- package/dist/lib/auth-context-manager.js.map +1 -0
- package/dist/lib/auth-handler.d.ts +19 -0
- package/dist/lib/auth-handler.d.ts.map +1 -0
- package/dist/lib/auth-handler.js +76 -0
- package/dist/lib/auth-handler.js.map +1 -0
- package/dist/lib/badge-handler.d.ts +20 -0
- package/dist/lib/badge-handler.d.ts.map +1 -0
- package/dist/lib/badge-handler.js +142 -0
- package/dist/lib/badge-handler.js.map +1 -0
- package/dist/lib/circle-handler.d.ts +22 -0
- package/dist/lib/circle-handler.d.ts.map +1 -0
- package/dist/lib/circle-handler.js +224 -0
- package/dist/lib/circle-handler.js.map +1 -0
- package/dist/lib/circuit-breaker.d.ts +27 -0
- package/dist/lib/circuit-breaker.d.ts.map +1 -0
- package/dist/lib/circuit-breaker.js +63 -0
- package/dist/lib/circuit-breaker.js.map +1 -0
- package/dist/lib/comment-handler.d.ts +77 -0
- package/dist/lib/comment-handler.d.ts.map +1 -0
- package/dist/lib/comment-handler.js +953 -0
- package/dist/lib/comment-handler.js.map +1 -0
- package/dist/lib/connection-code-handler.d.ts +17 -0
- package/dist/lib/connection-code-handler.d.ts.map +1 -0
- package/dist/lib/connection-code-handler.js +293 -0
- package/dist/lib/connection-code-handler.js.map +1 -0
- package/dist/lib/content-discovery.d.ts +113 -0
- package/dist/lib/content-discovery.d.ts.map +1 -0
- package/dist/lib/content-discovery.js +519 -0
- package/dist/lib/content-discovery.js.map +1 -0
- package/dist/lib/context-aware-data-access.d.ts +89 -0
- package/dist/lib/context-aware-data-access.d.ts.map +1 -0
- package/dist/lib/context-aware-data-access.js +97 -0
- package/dist/lib/context-aware-data-access.js.map +1 -0
- package/dist/lib/cors-handler.d.ts +29 -0
- package/dist/lib/cors-handler.d.ts.map +1 -0
- package/dist/lib/cors-handler.js +225 -0
- package/dist/lib/cors-handler.js.map +1 -0
- package/dist/lib/cost-accumulator.d.ts +58 -0
- package/dist/lib/cost-accumulator.d.ts.map +1 -0
- package/dist/lib/cost-accumulator.js +173 -0
- package/dist/lib/cost-accumulator.js.map +1 -0
- package/dist/lib/crypto/encryption-service.d.ts +100 -0
- package/dist/lib/crypto/encryption-service.d.ts.map +1 -0
- package/dist/lib/crypto/encryption-service.js +293 -0
- package/dist/lib/crypto/encryption-service.js.map +1 -0
- package/dist/lib/crypto/index.d.ts +22 -0
- package/dist/lib/crypto/index.d.ts.map +1 -0
- package/dist/lib/crypto/index.js +28 -0
- package/dist/lib/crypto/index.js.map +1 -0
- package/dist/lib/crypto/types.d.ts +71 -0
- package/dist/lib/crypto/types.d.ts.map +1 -0
- package/dist/lib/crypto/types.js +3 -0
- package/dist/lib/crypto/types.js.map +1 -0
- package/dist/lib/crypto/versioning.d.ts +112 -0
- package/dist/lib/crypto/versioning.d.ts.map +1 -0
- package/dist/lib/crypto/versioning.js +148 -0
- package/dist/lib/crypto/versioning.js.map +1 -0
- package/dist/lib/crypto/voting/elgamal-encryption.d.ts +156 -0
- package/dist/lib/crypto/voting/elgamal-encryption.d.ts.map +1 -0
- package/dist/lib/crypto/voting/elgamal-encryption.js +172 -0
- package/dist/lib/crypto/voting/elgamal-encryption.js.map +1 -0
- package/dist/lib/crypto/voting/encryption-scheme.d.ts +138 -0
- package/dist/lib/crypto/voting/encryption-scheme.d.ts.map +1 -0
- package/dist/lib/crypto/voting/encryption-scheme.js +13 -0
- package/dist/lib/crypto/voting/encryption-scheme.js.map +1 -0
- package/dist/lib/crypto/voting/hash-utils.d.ts +58 -0
- package/dist/lib/crypto/voting/hash-utils.d.ts.map +1 -0
- package/dist/lib/crypto/voting/hash-utils.js +73 -0
- package/dist/lib/crypto/voting/hash-utils.js.map +1 -0
- package/dist/lib/crypto/voting/hybrid-encryption.d.ts +109 -0
- package/dist/lib/crypto/voting/hybrid-encryption.d.ts.map +1 -0
- package/dist/lib/crypto/voting/hybrid-encryption.js +134 -0
- package/dist/lib/crypto/voting/hybrid-encryption.js.map +1 -0
- package/dist/lib/crypto/voting/index.d.ts +18 -0
- package/dist/lib/crypto/voting/index.d.ts.map +1 -0
- package/dist/lib/crypto/voting/index.js +27 -0
- package/dist/lib/crypto/voting/index.js.map +1 -0
- package/dist/lib/crypto/voting/post-quantum-encryption.d.ts +107 -0
- package/dist/lib/crypto/voting/post-quantum-encryption.d.ts.map +1 -0
- package/dist/lib/crypto/voting/post-quantum-encryption.js +123 -0
- package/dist/lib/crypto/voting/post-quantum-encryption.js.map +1 -0
- package/dist/lib/csrf.d.ts +95 -0
- package/dist/lib/csrf.d.ts.map +1 -0
- package/dist/lib/csrf.js +174 -0
- package/dist/lib/csrf.js.map +1 -0
- package/dist/lib/data-router.d.ts +209 -0
- package/dist/lib/data-router.d.ts.map +1 -0
- package/dist/lib/data-router.js +792 -0
- package/dist/lib/data-router.js.map +1 -0
- package/dist/lib/database-circuit-breaker.d.ts +75 -0
- package/dist/lib/database-circuit-breaker.d.ts.map +1 -0
- package/dist/lib/database-circuit-breaker.js +155 -0
- package/dist/lib/database-circuit-breaker.js.map +1 -0
- package/dist/lib/database-config.d.ts +20 -0
- package/dist/lib/database-config.d.ts.map +1 -0
- package/dist/lib/database-config.js +46 -0
- package/dist/lib/database-config.js.map +1 -0
- package/dist/lib/database-connection-manager.d.ts +99 -0
- package/dist/lib/database-connection-manager.d.ts.map +1 -0
- package/dist/lib/database-connection-manager.js +495 -0
- package/dist/lib/database-connection-manager.js.map +1 -0
- package/dist/lib/database-monitor.d.ts +89 -0
- package/dist/lib/database-monitor.d.ts.map +1 -0
- package/dist/lib/database-monitor.js +199 -0
- package/dist/lib/database-monitor.js.map +1 -0
- package/dist/lib/database-rate-limiter.d.ts +41 -0
- package/dist/lib/database-rate-limiter.d.ts.map +1 -0
- package/dist/lib/database-rate-limiter.js +90 -0
- package/dist/lib/database-rate-limiter.js.map +1 -0
- package/dist/lib/database-wrapper-helper.d.ts +44 -0
- package/dist/lib/database-wrapper-helper.d.ts.map +1 -0
- package/dist/lib/database-wrapper-helper.js +104 -0
- package/dist/lib/database-wrapper-helper.js.map +1 -0
- package/dist/lib/database-wrapper.d.ts +51 -0
- package/dist/lib/database-wrapper.d.ts.map +1 -0
- package/dist/lib/database-wrapper.js +109 -0
- package/dist/lib/database-wrapper.js.map +1 -0
- package/dist/lib/db-query-helper.d.ts +130 -0
- package/dist/lib/db-query-helper.d.ts.map +1 -0
- package/dist/lib/db-query-helper.js +105 -0
- package/dist/lib/db-query-helper.js.map +1 -0
- package/dist/lib/discovery-handler.d.ts +19 -0
- package/dist/lib/discovery-handler.d.ts.map +1 -0
- package/dist/lib/discovery-handler.js +195 -0
- package/dist/lib/discovery-handler.js.map +1 -0
- package/dist/lib/domain-reputation-service.d.ts +112 -0
- package/dist/lib/domain-reputation-service.d.ts.map +1 -0
- package/dist/lib/domain-reputation-service.js +344 -0
- package/dist/lib/domain-reputation-service.js.map +1 -0
- package/dist/lib/email-privacy.d.ts +54 -0
- package/dist/lib/email-privacy.d.ts.map +1 -0
- package/dist/lib/email-privacy.js +72 -0
- package/dist/lib/email-privacy.js.map +1 -0
- package/dist/lib/email-provider.d.ts +133 -0
- package/dist/lib/email-provider.d.ts.map +1 -0
- package/dist/lib/email-provider.js +391 -0
- package/dist/lib/email-provider.js.map +1 -0
- package/dist/lib/encryption-key-service.d.ts +115 -0
- package/dist/lib/encryption-key-service.d.ts.map +1 -0
- package/dist/lib/encryption-key-service.js +272 -0
- package/dist/lib/encryption-key-service.js.map +1 -0
- package/dist/lib/entity-handler.d.ts +59 -0
- package/dist/lib/entity-handler.d.ts.map +1 -0
- package/dist/lib/entity-handler.js +866 -0
- package/dist/lib/entity-handler.js.map +1 -0
- package/dist/lib/entity-relationship-handler.d.ts +19 -0
- package/dist/lib/entity-relationship-handler.d.ts.map +1 -0
- package/dist/lib/entity-relationship-handler.js +242 -0
- package/dist/lib/entity-relationship-handler.js.map +1 -0
- package/dist/lib/entity-tagging-errors.d.ts +32 -0
- package/dist/lib/entity-tagging-errors.d.ts.map +1 -0
- package/dist/lib/entity-tagging-errors.js +53 -0
- package/dist/lib/entity-tagging-errors.js.map +1 -0
- package/dist/lib/entity-tagging-validator.d.ts +47 -0
- package/dist/lib/entity-tagging-validator.d.ts.map +1 -0
- package/dist/lib/entity-tagging-validator.js +84 -0
- package/dist/lib/entity-tagging-validator.js.map +1 -0
- package/dist/lib/exif-stripper.d.ts +37 -0
- package/dist/lib/exif-stripper.d.ts.map +1 -0
- package/dist/lib/exif-stripper.js +62 -0
- package/dist/lib/exif-stripper.js.map +1 -0
- package/dist/lib/extension-context.d.ts +19 -0
- package/dist/lib/extension-context.d.ts.map +1 -0
- package/dist/lib/extension-context.js +78 -0
- package/dist/lib/extension-context.js.map +1 -0
- package/dist/lib/extension-route-wrapper.d.ts +21 -0
- package/dist/lib/extension-route-wrapper.d.ts.map +1 -0
- package/dist/lib/extension-route-wrapper.js +113 -0
- package/dist/lib/extension-route-wrapper.js.map +1 -0
- package/dist/lib/extension-validator.d.ts +12 -0
- package/dist/lib/extension-validator.d.ts.map +1 -0
- package/dist/lib/extension-validator.js +60 -0
- package/dist/lib/extension-validator.js.map +1 -0
- package/dist/lib/feature-flags.d.ts +56 -0
- package/dist/lib/feature-flags.d.ts.map +1 -0
- package/dist/lib/feature-flags.js +140 -0
- package/dist/lib/feature-flags.js.map +1 -0
- package/dist/lib/feature-toggle-service.d.ts +48 -0
- package/dist/lib/feature-toggle-service.d.ts.map +1 -0
- package/dist/lib/feature-toggle-service.js +167 -0
- package/dist/lib/feature-toggle-service.js.map +1 -0
- package/dist/lib/feed-handler.d.ts +152 -0
- package/dist/lib/feed-handler.d.ts.map +1 -0
- package/dist/lib/feed-handler.js +784 -0
- package/dist/lib/feed-handler.js.map +1 -0
- package/dist/lib/feed-pagination.d.ts +42 -0
- package/dist/lib/feed-pagination.d.ts.map +1 -0
- package/dist/lib/feed-pagination.js +54 -0
- package/dist/lib/feed-pagination.js.map +1 -0
- package/dist/lib/feed-personalization.d.ts +52 -0
- package/dist/lib/feed-personalization.d.ts.map +1 -0
- package/dist/lib/feed-personalization.js +105 -0
- package/dist/lib/feed-personalization.js.map +1 -0
- package/dist/lib/followers-events.d.ts +37 -0
- package/dist/lib/followers-events.d.ts.map +1 -0
- package/dist/lib/followers-events.js +149 -0
- package/dist/lib/followers-events.js.map +1 -0
- package/dist/lib/followers-handler.d.ts +21 -0
- package/dist/lib/followers-handler.d.ts.map +1 -0
- package/dist/lib/followers-handler.js +35 -0
- package/dist/lib/followers-handler.js.map +1 -0
- package/dist/lib/friends-handler.d.ts +78 -0
- package/dist/lib/friends-handler.d.ts.map +1 -0
- package/dist/lib/friends-handler.js +390 -0
- package/dist/lib/friends-handler.js.map +1 -0
- package/dist/lib/graph/dual-write-service.d.ts +116 -0
- package/dist/lib/graph/dual-write-service.d.ts.map +1 -0
- package/dist/lib/graph/dual-write-service.js +332 -0
- package/dist/lib/graph/dual-write-service.js.map +1 -0
- package/dist/lib/graph/dual-write.d.ts +396 -0
- package/dist/lib/graph/dual-write.d.ts.map +1 -0
- package/dist/lib/graph/dual-write.js +53 -0
- package/dist/lib/graph/dual-write.js.map +1 -0
- package/dist/lib/graph/errors.d.ts +90 -0
- package/dist/lib/graph/errors.d.ts.map +1 -0
- package/dist/lib/graph/errors.js +131 -0
- package/dist/lib/graph/errors.js.map +1 -0
- package/dist/lib/graph/graph-factory.d.ts +64 -0
- package/dist/lib/graph/graph-factory.d.ts.map +1 -0
- package/dist/lib/graph/graph-factory.js +190 -0
- package/dist/lib/graph/graph-factory.js.map +1 -0
- package/dist/lib/graph/graph-schema-init.d.ts +31 -0
- package/dist/lib/graph/graph-schema-init.d.ts.map +1 -0
- package/dist/lib/graph/graph-schema-init.js +105 -0
- package/dist/lib/graph/graph-schema-init.js.map +1 -0
- package/dist/lib/graph/graph-service.d.ts +479 -0
- package/dist/lib/graph/graph-service.d.ts.map +1 -0
- package/dist/lib/graph/graph-service.js +21 -0
- package/dist/lib/graph/graph-service.js.map +1 -0
- package/dist/lib/graph/index.d.ts +40 -0
- package/dist/lib/graph/index.d.ts.map +1 -0
- package/dist/lib/graph/index.js +74 -0
- package/dist/lib/graph/index.js.map +1 -0
- package/dist/lib/graph/neo4j-graph-service.d.ts +186 -0
- package/dist/lib/graph/neo4j-graph-service.d.ts.map +1 -0
- package/dist/lib/graph/neo4j-graph-service.js +1625 -0
- package/dist/lib/graph/neo4j-graph-service.js.map +1 -0
- package/dist/lib/graph/reconciliation-service.d.ts +113 -0
- package/dist/lib/graph/reconciliation-service.d.ts.map +1 -0
- package/dist/lib/graph/reconciliation-service.js +533 -0
- package/dist/lib/graph/reconciliation-service.js.map +1 -0
- package/dist/lib/graph/scoring-engine.d.ts +154 -0
- package/dist/lib/graph/scoring-engine.d.ts.map +1 -0
- package/dist/lib/graph/scoring-engine.js +286 -0
- package/dist/lib/graph/scoring-engine.js.map +1 -0
- package/dist/lib/graph/types.d.ts +480 -0
- package/dist/lib/graph/types.d.ts.map +1 -0
- package/dist/lib/graph/types.js +10 -0
- package/dist/lib/graph/types.js.map +1 -0
- package/dist/lib/hook-dispatcher.d.ts +21 -0
- package/dist/lib/hook-dispatcher.d.ts.map +1 -0
- package/dist/lib/hook-dispatcher.js +62 -0
- package/dist/lib/hook-dispatcher.js.map +1 -0
- package/dist/lib/id-generator.d.ts +29 -0
- package/dist/lib/id-generator.d.ts.map +1 -0
- package/dist/lib/id-generator.js +51 -0
- package/dist/lib/id-generator.js.map +1 -0
- package/dist/lib/input-sanitizer.d.ts +55 -0
- package/dist/lib/input-sanitizer.d.ts.map +1 -0
- package/dist/lib/input-sanitizer.js +167 -0
- package/dist/lib/input-sanitizer.js.map +1 -0
- package/dist/lib/internal-docs-dashboard.json +112 -0
- package/dist/lib/internal-docs-handler.d.ts +60 -0
- package/dist/lib/internal-docs-handler.d.ts.map +1 -0
- package/dist/lib/internal-docs-handler.js +570 -0
- package/dist/lib/internal-docs-handler.js.map +1 -0
- package/dist/lib/internal-docs-navigation.d.ts +42 -0
- package/dist/lib/internal-docs-navigation.d.ts.map +1 -0
- package/dist/lib/internal-docs-navigation.js +73 -0
- package/dist/lib/internal-docs-navigation.js.map +1 -0
- package/dist/lib/internal-docs-navigation.json +169 -0
- package/dist/lib/invitation-handler.d.ts +133 -0
- package/dist/lib/invitation-handler.d.ts.map +1 -0
- package/dist/lib/invitation-handler.js +1335 -0
- package/dist/lib/invitation-handler.js.map +1 -0
- package/dist/lib/ip-scrubber.d.ts +59 -0
- package/dist/lib/ip-scrubber.d.ts.map +1 -0
- package/dist/lib/ip-scrubber.js +101 -0
- package/dist/lib/ip-scrubber.js.map +1 -0
- package/dist/lib/kv/dynamodb-kv.d.ts +39 -0
- package/dist/lib/kv/dynamodb-kv.d.ts.map +1 -0
- package/dist/lib/kv/dynamodb-kv.js +239 -0
- package/dist/lib/kv/dynamodb-kv.js.map +1 -0
- package/dist/lib/link-security-handler.d.ts +140 -0
- package/dist/lib/link-security-handler.d.ts.map +1 -0
- package/dist/lib/link-security-handler.js +460 -0
- package/dist/lib/link-security-handler.js.map +1 -0
- package/dist/lib/logger.d.ts +100 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +201 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/media-cleanup-handler.d.ts +46 -0
- package/dist/lib/media-cleanup-handler.d.ts.map +1 -0
- package/dist/lib/media-cleanup-handler.js +190 -0
- package/dist/lib/media-cleanup-handler.js.map +1 -0
- package/dist/lib/media-handler.d.ts +150 -0
- package/dist/lib/media-handler.d.ts.map +1 -0
- package/dist/lib/media-handler.js +1544 -0
- package/dist/lib/media-handler.js.map +1 -0
- package/dist/lib/media-metadata-extractor.d.ts +71 -0
- package/dist/lib/media-metadata-extractor.d.ts.map +1 -0
- package/dist/lib/media-metadata-extractor.js +278 -0
- package/dist/lib/media-metadata-extractor.js.map +1 -0
- package/dist/lib/media-metrics.d.ts +57 -0
- package/dist/lib/media-metrics.d.ts.map +1 -0
- package/dist/lib/media-metrics.js +202 -0
- package/dist/lib/media-metrics.js.map +1 -0
- package/dist/lib/metadata/index.d.ts +6 -0
- package/dist/lib/metadata/index.d.ts.map +1 -0
- package/dist/lib/metadata/index.js +22 -0
- package/dist/lib/metadata/index.js.map +1 -0
- package/dist/lib/metadata/metadata-config.d.ts +17 -0
- package/dist/lib/metadata/metadata-config.d.ts.map +1 -0
- package/dist/lib/metadata/metadata-config.js +23 -0
- package/dist/lib/metadata/metadata-config.js.map +1 -0
- package/dist/lib/metadata/metadata-errors.d.ts +18 -0
- package/dist/lib/metadata/metadata-errors.d.ts.map +1 -0
- package/dist/lib/metadata/metadata-errors.js +26 -0
- package/dist/lib/metadata/metadata-errors.js.map +1 -0
- package/dist/lib/metadata/metadata-extractor.d.ts +17 -0
- package/dist/lib/metadata/metadata-extractor.d.ts.map +1 -0
- package/dist/lib/metadata/metadata-extractor.js +264 -0
- package/dist/lib/metadata/metadata-extractor.js.map +1 -0
- package/dist/lib/metadata/metadata-sanitizer.d.ts +9 -0
- package/dist/lib/metadata/metadata-sanitizer.d.ts.map +1 -0
- package/dist/lib/metadata/metadata-sanitizer.js +100 -0
- package/dist/lib/metadata/metadata-sanitizer.js.map +1 -0
- package/dist/lib/metadata/metadata-schemas.d.ts +131 -0
- package/dist/lib/metadata/metadata-schemas.d.ts.map +1 -0
- package/dist/lib/metadata/metadata-schemas.js +71 -0
- package/dist/lib/metadata/metadata-schemas.js.map +1 -0
- package/dist/lib/mfa/mfa-handler.d.ts +60 -0
- package/dist/lib/mfa/mfa-handler.d.ts.map +1 -0
- package/dist/lib/mfa/mfa-handler.js +150 -0
- package/dist/lib/mfa/mfa-handler.js.map +1 -0
- package/dist/lib/mfa/totp-service.d.ts +41 -0
- package/dist/lib/mfa/totp-service.d.ts.map +1 -0
- package/dist/lib/mfa/totp-service.js +183 -0
- package/dist/lib/mfa/totp-service.js.map +1 -0
- package/dist/lib/middleware/comment-rate-limit.d.ts +19 -0
- package/dist/lib/middleware/comment-rate-limit.d.ts.map +1 -0
- package/dist/lib/middleware/comment-rate-limit.js +113 -0
- package/dist/lib/middleware/comment-rate-limit.js.map +1 -0
- package/dist/lib/middleware/feature-toggle-rate-limit.d.ts +53 -0
- package/dist/lib/middleware/feature-toggle-rate-limit.d.ts.map +1 -0
- package/dist/lib/middleware/feature-toggle-rate-limit.js +164 -0
- package/dist/lib/middleware/feature-toggle-rate-limit.js.map +1 -0
- package/dist/lib/middleware.d.ts +70 -0
- package/dist/lib/middleware.d.ts.map +1 -0
- package/dist/lib/middleware.js +375 -0
- package/dist/lib/middleware.js.map +1 -0
- package/dist/lib/moderation-handler.d.ts +55 -0
- package/dist/lib/moderation-handler.d.ts.map +1 -0
- package/dist/lib/moderation-handler.js +230 -0
- package/dist/lib/moderation-handler.js.map +1 -0
- package/dist/lib/notification-handler.d.ts +65 -0
- package/dist/lib/notification-handler.d.ts.map +1 -0
- package/dist/lib/notification-handler.js +236 -0
- package/dist/lib/notification-handler.js.map +1 -0
- package/dist/lib/notification-preferences-handler.d.ts +27 -0
- package/dist/lib/notification-preferences-handler.d.ts.map +1 -0
- package/dist/lib/notification-preferences-handler.js +119 -0
- package/dist/lib/notification-preferences-handler.js.map +1 -0
- package/dist/lib/openai-budget.d.ts +45 -0
- package/dist/lib/openai-budget.d.ts.map +1 -0
- package/dist/lib/openai-budget.js +175 -0
- package/dist/lib/openai-budget.js.map +1 -0
- package/dist/lib/orphaned-media-handler.d.ts +60 -0
- package/dist/lib/orphaned-media-handler.d.ts.map +1 -0
- package/dist/lib/orphaned-media-handler.js +487 -0
- package/dist/lib/orphaned-media-handler.js.map +1 -0
- package/dist/lib/parental-control-handler.d.ts +42 -0
- package/dist/lib/parental-control-handler.d.ts.map +1 -0
- package/dist/lib/parental-control-handler.js +327 -0
- package/dist/lib/parental-control-handler.js.map +1 -0
- package/dist/lib/parental-link-handler.d.ts +38 -0
- package/dist/lib/parental-link-handler.d.ts.map +1 -0
- package/dist/lib/parental-link-handler.js +217 -0
- package/dist/lib/parental-link-handler.js.map +1 -0
- package/dist/lib/performance-metrics.d.ts +125 -0
- package/dist/lib/performance-metrics.d.ts.map +1 -0
- package/dist/lib/performance-metrics.js +277 -0
- package/dist/lib/performance-metrics.js.map +1 -0
- package/dist/lib/post-handler.d.ts +94 -0
- package/dist/lib/post-handler.d.ts.map +1 -0
- package/dist/lib/post-handler.js +1346 -0
- package/dist/lib/post-handler.js.map +1 -0
- package/dist/lib/privacy-defaults.d.ts +32 -0
- package/dist/lib/privacy-defaults.d.ts.map +1 -0
- package/dist/lib/privacy-defaults.js +85 -0
- package/dist/lib/privacy-defaults.js.map +1 -0
- package/dist/lib/privacy-handler.d.ts +43 -0
- package/dist/lib/privacy-handler.d.ts.map +1 -0
- package/dist/lib/privacy-handler.js +124 -0
- package/dist/lib/privacy-handler.js.map +1 -0
- package/dist/lib/queue/sqs-queue.d.ts +16 -0
- package/dist/lib/queue/sqs-queue.d.ts.map +1 -0
- package/dist/lib/queue/sqs-queue.js +39 -0
- package/dist/lib/queue/sqs-queue.js.map +1 -0
- package/dist/lib/queue-consumers/media-reconciliation-consumer.d.ts +9 -0
- package/dist/lib/queue-consumers/media-reconciliation-consumer.d.ts.map +1 -0
- package/dist/lib/queue-consumers/media-reconciliation-consumer.js +37 -0
- package/dist/lib/queue-consumers/media-reconciliation-consumer.js.map +1 -0
- package/dist/lib/quiet-hours.d.ts +33 -0
- package/dist/lib/quiet-hours.d.ts.map +1 -0
- package/dist/lib/quiet-hours.js +51 -0
- package/dist/lib/quiet-hours.js.map +1 -0
- package/dist/lib/rate-limit.d.ts +95 -0
- package/dist/lib/rate-limit.d.ts.map +1 -0
- package/dist/lib/rate-limit.js +247 -0
- package/dist/lib/rate-limit.js.map +1 -0
- package/dist/lib/reaction-handler.d.ts +68 -0
- package/dist/lib/reaction-handler.d.ts.map +1 -0
- package/dist/lib/reaction-handler.js +858 -0
- package/dist/lib/reaction-handler.js.map +1 -0
- package/dist/lib/recaptcha.d.ts +16 -0
- package/dist/lib/recaptcha.d.ts.map +1 -0
- package/dist/lib/recaptcha.js +71 -0
- package/dist/lib/recaptcha.js.map +1 -0
- package/dist/lib/redirect-resolver.d.ts +78 -0
- package/dist/lib/redirect-resolver.d.ts.map +1 -0
- package/dist/lib/redirect-resolver.js +276 -0
- package/dist/lib/redirect-resolver.js.map +1 -0
- package/dist/lib/region-config.d.ts +179 -0
- package/dist/lib/region-config.d.ts.map +1 -0
- package/dist/lib/region-config.js +474 -0
- package/dist/lib/region-config.js.map +1 -0
- package/dist/lib/region-detection.d.ts +110 -0
- package/dist/lib/region-detection.d.ts.map +1 -0
- package/dist/lib/region-detection.js +408 -0
- package/dist/lib/region-detection.js.map +1 -0
- package/dist/lib/relationship-handler.d.ts +19 -0
- package/dist/lib/relationship-handler.d.ts.map +1 -0
- package/dist/lib/relationship-handler.js +233 -0
- package/dist/lib/relationship-handler.js.map +1 -0
- package/dist/lib/request-context.d.ts +103 -0
- package/dist/lib/request-context.d.ts.map +1 -0
- package/dist/lib/request-context.js +179 -0
- package/dist/lib/request-context.js.map +1 -0
- package/dist/lib/route-helpers.d.ts +74 -0
- package/dist/lib/route-helpers.d.ts.map +1 -0
- package/dist/lib/route-helpers.js +190 -0
- package/dist/lib/route-helpers.js.map +1 -0
- package/dist/lib/route-matcher.d.ts +24 -0
- package/dist/lib/route-matcher.d.ts.map +1 -0
- package/dist/lib/route-matcher.js +96 -0
- package/dist/lib/route-matcher.js.map +1 -0
- package/dist/lib/router.d.ts +26 -0
- package/dist/lib/router.d.ts.map +1 -0
- package/dist/lib/router.js +90 -0
- package/dist/lib/router.js.map +1 -0
- package/dist/lib/routes/activitypub/actor.d.ts +12 -0
- package/dist/lib/routes/activitypub/actor.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/actor.js +141 -0
- package/dist/lib/routes/activitypub/actor.js.map +1 -0
- package/dist/lib/routes/activitypub/audiences.d.ts +12 -0
- package/dist/lib/routes/activitypub/audiences.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/audiences.js +325 -0
- package/dist/lib/routes/activitypub/audiences.js.map +1 -0
- package/dist/lib/routes/activitypub/collections.d.ts +12 -0
- package/dist/lib/routes/activitypub/collections.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/collections.js +127 -0
- package/dist/lib/routes/activitypub/collections.js.map +1 -0
- package/dist/lib/routes/activitypub/entity-profile.d.ts +9 -0
- package/dist/lib/routes/activitypub/entity-profile.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/entity-profile.js +136 -0
- package/dist/lib/routes/activitypub/entity-profile.js.map +1 -0
- package/dist/lib/routes/activitypub/friends.d.ts +15 -0
- package/dist/lib/routes/activitypub/friends.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/friends.js +33 -0
- package/dist/lib/routes/activitypub/friends.js.map +1 -0
- package/dist/lib/routes/activitypub/group.d.ts +8 -0
- package/dist/lib/routes/activitypub/group.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/group.js +436 -0
- package/dist/lib/routes/activitypub/group.js.map +1 -0
- package/dist/lib/routes/activitypub/inbox.d.ts +15 -0
- package/dist/lib/routes/activitypub/inbox.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/inbox.js +125 -0
- package/dist/lib/routes/activitypub/inbox.js.map +1 -0
- package/dist/lib/routes/activitypub/messages.d.ts +12 -0
- package/dist/lib/routes/activitypub/messages.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/messages.js +374 -0
- package/dist/lib/routes/activitypub/messages.js.map +1 -0
- package/dist/lib/routes/activitypub/outbox.d.ts +15 -0
- package/dist/lib/routes/activitypub/outbox.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/outbox.js +33 -0
- package/dist/lib/routes/activitypub/outbox.js.map +1 -0
- package/dist/lib/routes/activitypub/post.d.ts +12 -0
- package/dist/lib/routes/activitypub/post.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/post.js +213 -0
- package/dist/lib/routes/activitypub/post.js.map +1 -0
- package/dist/lib/routes/activitypub/webfinger.d.ts +11 -0
- package/dist/lib/routes/activitypub/webfinger.d.ts.map +1 -0
- package/dist/lib/routes/activitypub/webfinger.js +27 -0
- package/dist/lib/routes/activitypub/webfinger.js.map +1 -0
- package/dist/lib/routes/admin-costs.d.ts +8 -0
- package/dist/lib/routes/admin-costs.d.ts.map +1 -0
- package/dist/lib/routes/admin-costs.js +89 -0
- package/dist/lib/routes/admin-costs.js.map +1 -0
- package/dist/lib/routes/admin.d.ts +6 -0
- package/dist/lib/routes/admin.d.ts.map +1 -0
- package/dist/lib/routes/admin.js +1450 -0
- package/dist/lib/routes/admin.js.map +1 -0
- package/dist/lib/routes/auth.d.ts +6 -0
- package/dist/lib/routes/auth.d.ts.map +1 -0
- package/dist/lib/routes/auth.js +49 -0
- package/dist/lib/routes/auth.js.map +1 -0
- package/dist/lib/routes/badges.d.ts +6 -0
- package/dist/lib/routes/badges.d.ts.map +1 -0
- package/dist/lib/routes/badges.js +66 -0
- package/dist/lib/routes/badges.js.map +1 -0
- package/dist/lib/routes/circles.d.ts +8 -0
- package/dist/lib/routes/circles.d.ts.map +1 -0
- package/dist/lib/routes/circles.js +135 -0
- package/dist/lib/routes/circles.js.map +1 -0
- package/dist/lib/routes/comments.d.ts +6 -0
- package/dist/lib/routes/comments.d.ts.map +1 -0
- package/dist/lib/routes/comments.js +228 -0
- package/dist/lib/routes/comments.js.map +1 -0
- package/dist/lib/routes/connection-codes.d.ts +8 -0
- package/dist/lib/routes/connection-codes.d.ts.map +1 -0
- package/dist/lib/routes/connection-codes.js +84 -0
- package/dist/lib/routes/connection-codes.js.map +1 -0
- package/dist/lib/routes/content-discovery.d.ts +11 -0
- package/dist/lib/routes/content-discovery.d.ts.map +1 -0
- package/dist/lib/routes/content-discovery.js +211 -0
- package/dist/lib/routes/content-discovery.js.map +1 -0
- package/dist/lib/routes/dashboard.d.ts +8 -0
- package/dist/lib/routes/dashboard.d.ts.map +1 -0
- package/dist/lib/routes/dashboard.js +1139 -0
- package/dist/lib/routes/dashboard.js.map +1 -0
- package/dist/lib/routes/deletion.d.ts +6 -0
- package/dist/lib/routes/deletion.d.ts.map +1 -0
- package/dist/lib/routes/deletion.js +213 -0
- package/dist/lib/routes/deletion.js.map +1 -0
- package/dist/lib/routes/discovery.d.ts +8 -0
- package/dist/lib/routes/discovery.d.ts.map +1 -0
- package/dist/lib/routes/discovery.js +67 -0
- package/dist/lib/routes/discovery.js.map +1 -0
- package/dist/lib/routes/employees.d.ts +6 -0
- package/dist/lib/routes/employees.d.ts.map +1 -0
- package/dist/lib/routes/employees.js +82 -0
- package/dist/lib/routes/employees.js.map +1 -0
- package/dist/lib/routes/entities.d.ts +8 -0
- package/dist/lib/routes/entities.d.ts.map +1 -0
- package/dist/lib/routes/entities.js +467 -0
- package/dist/lib/routes/entities.js.map +1 -0
- package/dist/lib/routes/entity-relationships.d.ts +8 -0
- package/dist/lib/routes/entity-relationships.d.ts.map +1 -0
- package/dist/lib/routes/entity-relationships.js +118 -0
- package/dist/lib/routes/entity-relationships.js.map +1 -0
- package/dist/lib/routes/export.d.ts +6 -0
- package/dist/lib/routes/export.d.ts.map +1 -0
- package/dist/lib/routes/export.js +118 -0
- package/dist/lib/routes/export.js.map +1 -0
- package/dist/lib/routes/feature-flags.d.ts +8 -0
- package/dist/lib/routes/feature-flags.d.ts.map +1 -0
- package/dist/lib/routes/feature-flags.js +75 -0
- package/dist/lib/routes/feature-flags.js.map +1 -0
- package/dist/lib/routes/feeds.d.ts +6 -0
- package/dist/lib/routes/feeds.d.ts.map +1 -0
- package/dist/lib/routes/feeds.js +131 -0
- package/dist/lib/routes/feeds.js.map +1 -0
- package/dist/lib/routes/followers.d.ts +6 -0
- package/dist/lib/routes/followers.d.ts.map +1 -0
- package/dist/lib/routes/followers.js +405 -0
- package/dist/lib/routes/followers.js.map +1 -0
- package/dist/lib/routes/friends.d.ts +6 -0
- package/dist/lib/routes/friends.d.ts.map +1 -0
- package/dist/lib/routes/friends.js +116 -0
- package/dist/lib/routes/friends.js.map +1 -0
- package/dist/lib/routes/health.d.ts +6 -0
- package/dist/lib/routes/health.d.ts.map +1 -0
- package/dist/lib/routes/health.js +129 -0
- package/dist/lib/routes/health.js.map +1 -0
- package/dist/lib/routes/index.d.ts +21 -0
- package/dist/lib/routes/index.d.ts.map +1 -0
- package/dist/lib/routes/index.js +212 -0
- package/dist/lib/routes/index.js.map +1 -0
- package/dist/lib/routes/internal-docs.d.ts +6 -0
- package/dist/lib/routes/internal-docs.d.ts.map +1 -0
- package/dist/lib/routes/internal-docs.js +44 -0
- package/dist/lib/routes/internal-docs.js.map +1 -0
- package/dist/lib/routes/invitations.d.ts +6 -0
- package/dist/lib/routes/invitations.d.ts.map +1 -0
- package/dist/lib/routes/invitations.js +67 -0
- package/dist/lib/routes/invitations.js.map +1 -0
- package/dist/lib/routes/link-reports.d.ts +11 -0
- package/dist/lib/routes/link-reports.d.ts.map +1 -0
- package/dist/lib/routes/link-reports.js +287 -0
- package/dist/lib/routes/link-reports.js.map +1 -0
- package/dist/lib/routes/map.d.ts +6 -0
- package/dist/lib/routes/map.d.ts.map +1 -0
- package/dist/lib/routes/map.js +21 -0
- package/dist/lib/routes/map.js.map +1 -0
- package/dist/lib/routes/media-metadata-visibility.d.ts +3 -0
- package/dist/lib/routes/media-metadata-visibility.d.ts.map +1 -0
- package/dist/lib/routes/media-metadata-visibility.js +184 -0
- package/dist/lib/routes/media-metadata-visibility.js.map +1 -0
- package/dist/lib/routes/media.d.ts +9 -0
- package/dist/lib/routes/media.d.ts.map +1 -0
- package/dist/lib/routes/media.js +1910 -0
- package/dist/lib/routes/media.js.map +1 -0
- package/dist/lib/routes/mfa.d.ts +8 -0
- package/dist/lib/routes/mfa.d.ts.map +1 -0
- package/dist/lib/routes/mfa.js +193 -0
- package/dist/lib/routes/mfa.js.map +1 -0
- package/dist/lib/routes/notifications.d.ts +9 -0
- package/dist/lib/routes/notifications.d.ts.map +1 -0
- package/dist/lib/routes/notifications.js +230 -0
- package/dist/lib/routes/notifications.js.map +1 -0
- package/dist/lib/routes/orphaned-media-health.d.ts +9 -0
- package/dist/lib/routes/orphaned-media-health.d.ts.map +1 -0
- package/dist/lib/routes/orphaned-media-health.js +121 -0
- package/dist/lib/routes/orphaned-media-health.js.map +1 -0
- package/dist/lib/routes/orphaned-media.d.ts +8 -0
- package/dist/lib/routes/orphaned-media.d.ts.map +1 -0
- package/dist/lib/routes/orphaned-media.js +111 -0
- package/dist/lib/routes/orphaned-media.js.map +1 -0
- package/dist/lib/routes/out.d.ts +17 -0
- package/dist/lib/routes/out.d.ts.map +1 -0
- package/dist/lib/routes/out.js +339 -0
- package/dist/lib/routes/out.js.map +1 -0
- package/dist/lib/routes/parental-controls.d.ts +8 -0
- package/dist/lib/routes/parental-controls.d.ts.map +1 -0
- package/dist/lib/routes/parental-controls.js +282 -0
- package/dist/lib/routes/parental-controls.js.map +1 -0
- package/dist/lib/routes/posts.d.ts +6 -0
- package/dist/lib/routes/posts.d.ts.map +1 -0
- package/dist/lib/routes/posts.js +518 -0
- package/dist/lib/routes/posts.js.map +1 -0
- package/dist/lib/routes/privacy.d.ts +6 -0
- package/dist/lib/routes/privacy.d.ts.map +1 -0
- package/dist/lib/routes/privacy.js +66 -0
- package/dist/lib/routes/privacy.js.map +1 -0
- package/dist/lib/routes/products.d.ts +9 -0
- package/dist/lib/routes/products.d.ts.map +1 -0
- package/dist/lib/routes/products.js +224 -0
- package/dist/lib/routes/products.js.map +1 -0
- package/dist/lib/routes/relationships.d.ts +8 -0
- package/dist/lib/routes/relationships.d.ts.map +1 -0
- package/dist/lib/routes/relationships.js +118 -0
- package/dist/lib/routes/relationships.js.map +1 -0
- package/dist/lib/routes/sentiments.d.ts +6 -0
- package/dist/lib/routes/sentiments.d.ts.map +1 -0
- package/dist/lib/routes/sentiments.js +285 -0
- package/dist/lib/routes/sentiments.js.map +1 -0
- package/dist/lib/routes/taxonomy-analytics.d.ts +8 -0
- package/dist/lib/routes/taxonomy-analytics.d.ts.map +1 -0
- package/dist/lib/routes/taxonomy-analytics.js +151 -0
- package/dist/lib/routes/taxonomy-analytics.js.map +1 -0
- package/dist/lib/routes/taxonomy.d.ts +15 -0
- package/dist/lib/routes/taxonomy.d.ts.map +1 -0
- package/dist/lib/routes/taxonomy.js +370 -0
- package/dist/lib/routes/taxonomy.js.map +1 -0
- package/dist/lib/routes/types.d.ts +46 -0
- package/dist/lib/routes/types.d.ts.map +1 -0
- package/dist/lib/routes/types.js +8 -0
- package/dist/lib/routes/types.js.map +1 -0
- package/dist/lib/routes/upload-sessions.d.ts +9 -0
- package/dist/lib/routes/upload-sessions.d.ts.map +1 -0
- package/dist/lib/routes/upload-sessions.js +268 -0
- package/dist/lib/routes/upload-sessions.js.map +1 -0
- package/dist/lib/routes/user.d.ts +8 -0
- package/dist/lib/routes/user.d.ts.map +1 -0
- package/dist/lib/routes/user.js +287 -0
- package/dist/lib/routes/user.js.map +1 -0
- package/dist/lib/routes-all.d.ts +9 -0
- package/dist/lib/routes-all.d.ts.map +1 -0
- package/dist/lib/routes-all.js +170 -0
- package/dist/lib/routes-all.js.map +1 -0
- package/dist/lib/routes.d.ts +10 -0
- package/dist/lib/routes.d.ts.map +1 -0
- package/dist/lib/routes.js +16 -0
- package/dist/lib/routes.js.map +1 -0
- package/dist/lib/scaling-health.d.ts +48 -0
- package/dist/lib/scaling-health.d.ts.map +1 -0
- package/dist/lib/scaling-health.js +363 -0
- package/dist/lib/scaling-health.js.map +1 -0
- package/dist/lib/scheduled/media-stale-cleanup.d.ts +11 -0
- package/dist/lib/scheduled/media-stale-cleanup.d.ts.map +1 -0
- package/dist/lib/scheduled/media-stale-cleanup.js +79 -0
- package/dist/lib/scheduled/media-stale-cleanup.js.map +1 -0
- package/dist/lib/scheduled/orphaned-media-monitor.d.ts +97 -0
- package/dist/lib/scheduled/orphaned-media-monitor.d.ts.map +1 -0
- package/dist/lib/scheduled/orphaned-media-monitor.js +399 -0
- package/dist/lib/scheduled/orphaned-media-monitor.js.map +1 -0
- package/dist/lib/schemas.d.ts +314 -0
- package/dist/lib/schemas.d.ts.map +1 -0
- package/dist/lib/schemas.js +235 -0
- package/dist/lib/schemas.js.map +1 -0
- package/dist/lib/secret-resolver.d.ts +88 -0
- package/dist/lib/secret-resolver.d.ts.map +1 -0
- package/dist/lib/secret-resolver.js +183 -0
- package/dist/lib/secret-resolver.js.map +1 -0
- package/dist/lib/security-event-cleaner.d.ts +61 -0
- package/dist/lib/security-event-cleaner.d.ts.map +1 -0
- package/dist/lib/security-event-cleaner.js +74 -0
- package/dist/lib/security-event-cleaner.js.map +1 -0
- package/dist/lib/security-headers.d.ts +36 -0
- package/dist/lib/security-headers.d.ts.map +1 -0
- package/dist/lib/security-headers.js +87 -0
- package/dist/lib/security-headers.js.map +1 -0
- package/dist/lib/security-monitor.d.ts +92 -0
- package/dist/lib/security-monitor.d.ts.map +1 -0
- package/dist/lib/security-monitor.js +287 -0
- package/dist/lib/security-monitor.js.map +1 -0
- package/dist/lib/sentiment-digest.d.ts +19 -0
- package/dist/lib/sentiment-digest.d.ts.map +1 -0
- package/dist/lib/sentiment-digest.js +99 -0
- package/dist/lib/sentiment-digest.js.map +1 -0
- package/dist/lib/sentiment-display.d.ts +20 -0
- package/dist/lib/sentiment-display.d.ts.map +1 -0
- package/dist/lib/sentiment-display.js +38 -0
- package/dist/lib/sentiment-display.js.map +1 -0
- package/dist/lib/services/image-normalizer.d.ts +15 -0
- package/dist/lib/services/image-normalizer.d.ts.map +1 -0
- package/dist/lib/services/image-normalizer.js +22 -0
- package/dist/lib/services/image-normalizer.js.map +1 -0
- package/dist/lib/services/media-reconciliation-service.d.ts +25 -0
- package/dist/lib/services/media-reconciliation-service.d.ts.map +1 -0
- package/dist/lib/services/media-reconciliation-service.js +191 -0
- package/dist/lib/services/media-reconciliation-service.js.map +1 -0
- package/dist/lib/services/media-upload-service.d.ts +25 -0
- package/dist/lib/services/media-upload-service.d.ts.map +1 -0
- package/dist/lib/services/media-upload-service.js +240 -0
- package/dist/lib/services/media-upload-service.js.map +1 -0
- package/dist/lib/services/user-data-deletion.d.ts +30 -0
- package/dist/lib/services/user-data-deletion.d.ts.map +1 -0
- package/dist/lib/services/user-data-deletion.js +118 -0
- package/dist/lib/services/user-data-deletion.js.map +1 -0
- package/dist/lib/session-awareness.d.ts +35 -0
- package/dist/lib/session-awareness.d.ts.map +1 -0
- package/dist/lib/session-awareness.js +79 -0
- package/dist/lib/session-awareness.js.map +1 -0
- package/dist/lib/session-config.d.ts +87 -0
- package/dist/lib/session-config.d.ts.map +1 -0
- package/dist/lib/session-config.js +165 -0
- package/dist/lib/session-config.js.map +1 -0
- package/dist/lib/session-manager.d.ts +103 -0
- package/dist/lib/session-manager.d.ts.map +1 -0
- package/dist/lib/session-manager.js +492 -0
- package/dist/lib/session-manager.js.map +1 -0
- package/dist/lib/sso-auth-handler.d.ts +12 -0
- package/dist/lib/sso-auth-handler.d.ts.map +1 -0
- package/dist/lib/sso-auth-handler.js +24 -0
- package/dist/lib/sso-auth-handler.js.map +1 -0
- package/dist/lib/storage/s3-storage.d.ts +29 -0
- package/dist/lib/storage/s3-storage.d.ts.map +1 -0
- package/dist/lib/storage/s3-storage.js +135 -0
- package/dist/lib/storage/s3-storage.js.map +1 -0
- package/dist/lib/tag-suggestions-handler.d.ts +52 -0
- package/dist/lib/tag-suggestions-handler.d.ts.map +1 -0
- package/dist/lib/tag-suggestions-handler.js +195 -0
- package/dist/lib/tag-suggestions-handler.js.map +1 -0
- package/dist/lib/taxonomy-handler-factory.d.ts +18 -0
- package/dist/lib/taxonomy-handler-factory.d.ts.map +1 -0
- package/dist/lib/taxonomy-handler-factory.js +29 -0
- package/dist/lib/taxonomy-handler-factory.js.map +1 -0
- package/dist/lib/taxonomy-handler.d.ts +142 -0
- package/dist/lib/taxonomy-handler.d.ts.map +1 -0
- package/dist/lib/taxonomy-handler.js +636 -0
- package/dist/lib/taxonomy-handler.js.map +1 -0
- package/dist/lib/taxonomy-metrics.d.ts +76 -0
- package/dist/lib/taxonomy-metrics.d.ts.map +1 -0
- package/dist/lib/taxonomy-metrics.js +201 -0
- package/dist/lib/taxonomy-metrics.js.map +1 -0
- package/dist/lib/taxonomy-search-metrics.d.ts +45 -0
- package/dist/lib/taxonomy-search-metrics.d.ts.map +1 -0
- package/dist/lib/taxonomy-search-metrics.js +75 -0
- package/dist/lib/taxonomy-search-metrics.js.map +1 -0
- package/dist/lib/tenant-context.d.ts +35 -0
- package/dist/lib/tenant-context.d.ts.map +1 -0
- package/dist/lib/tenant-context.js +54 -0
- package/dist/lib/tenant-context.js.map +1 -0
- package/dist/lib/terminology.d.ts +25 -0
- package/dist/lib/terminology.d.ts.map +1 -0
- package/dist/lib/terminology.js +44 -0
- package/dist/lib/terminology.js.map +1 -0
- package/dist/lib/theme.d.ts +29 -0
- package/dist/lib/theme.d.ts.map +1 -0
- package/dist/lib/theme.js +38 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/threat-intel-service.d.ts +67 -0
- package/dist/lib/threat-intel-service.d.ts.map +1 -0
- package/dist/lib/threat-intel-service.js +193 -0
- package/dist/lib/threat-intel-service.js.map +1 -0
- package/dist/lib/types/media-reconciliation.d.ts +64 -0
- package/dist/lib/types/media-reconciliation.d.ts.map +1 -0
- package/dist/lib/types/media-reconciliation.js +8 -0
- package/dist/lib/types/media-reconciliation.js.map +1 -0
- package/dist/lib/upload-session-handler.d.ts +56 -0
- package/dist/lib/upload-session-handler.d.ts.map +1 -0
- package/dist/lib/upload-session-handler.js +312 -0
- package/dist/lib/upload-session-handler.js.map +1 -0
- package/dist/lib/user-badge.d.ts +56 -0
- package/dist/lib/user-badge.d.ts.map +1 -0
- package/dist/lib/user-badge.js +92 -0
- package/dist/lib/user-badge.js.map +1 -0
- package/dist/lib/user-deletion-handler-enhanced.d.ts +96 -0
- package/dist/lib/user-deletion-handler-enhanced.d.ts.map +1 -0
- package/dist/lib/user-deletion-handler-enhanced.js +401 -0
- package/dist/lib/user-deletion-handler-enhanced.js.map +1 -0
- package/dist/lib/user-deprovisioning.d.ts +43 -0
- package/dist/lib/user-deprovisioning.d.ts.map +1 -0
- package/dist/lib/user-deprovisioning.js +138 -0
- package/dist/lib/user-deprovisioning.js.map +1 -0
- package/dist/lib/user-export-handler.d.ts +172 -0
- package/dist/lib/user-export-handler.d.ts.map +1 -0
- package/dist/lib/user-export-handler.js +435 -0
- package/dist/lib/user-export-handler.js.map +1 -0
- package/dist/lib/validate-request.d.ts +46 -0
- package/dist/lib/validate-request.d.ts.map +1 -0
- package/dist/lib/validate-request.js +127 -0
- package/dist/lib/validate-request.js.map +1 -0
- package/dist/lib/validation/feature-toggle-schemas.d.ts +410 -0
- package/dist/lib/validation/feature-toggle-schemas.d.ts.map +1 -0
- package/dist/lib/validation/feature-toggle-schemas.js +274 -0
- package/dist/lib/validation/feature-toggle-schemas.js.map +1 -0
- package/dist/lib/validation/validate-request.d.ts +75 -0
- package/dist/lib/validation/validate-request.d.ts.map +1 -0
- package/dist/lib/validation/validate-request.js +183 -0
- package/dist/lib/validation/validate-request.js.map +1 -0
- package/dist/lib/validation.d.ts +50 -0
- package/dist/lib/validation.d.ts.map +1 -0
- package/dist/lib/validation.js +122 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/lib/version.d.ts +36 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +44 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +254 -0
- package/dist/server.js.map +1 -0
- package/dist/types/cloudflare-compat.d.ts +134 -0
- package/dist/types/cloudflare-compat.d.ts.map +1 -0
- package/dist/types/cloudflare-compat.js +7 -0
- package/dist/types/cloudflare-compat.js.map +1 -0
- package/dist/worker.d.ts +16 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +21 -0
- package/dist/worker.js.map +1 -0
- package/package.json +91 -0
- package/src/lambda/cleanup-cron.ts +37 -0
- package/src/lambda/create-auth-challenge.ts +112 -0
- package/src/lambda/custom-message.ts +30 -0
- package/src/lambda/define-auth-challenge.ts +24 -0
- package/src/lambda/delete-account-worker.ts +96 -0
- package/src/lambda/diagnostics-proxy.ts +139 -0
- package/src/lambda/e2e-sweeper.ts +140 -0
- package/src/lambda/federation-outbox-worker.ts +8 -0
- package/src/lambda/followers-events-worker.ts +8 -0
- package/src/lambda/hourly-cron.ts +103 -0
- package/src/lambda/link-check-worker.ts +8 -0
- package/src/lambda/maintenance-cron.ts +95 -0
- package/src/lambda/media-processing-worker.ts +68 -0
- package/src/lambda/media-reconciliation-worker.ts +8 -0
- package/src/lambda/nightly-cron.ts +338 -0
- package/src/lambda/post-confirmation.ts +80 -0
- package/src/lambda/pre-signup.ts +39 -0
- package/src/lambda/pre-token-generation.ts +93 -0
- package/src/lambda/tools/check-health.ts +22 -0
- package/src/lambda/tools/describe-services.ts +45 -0
- package/src/lambda/tools/get-cost-report.ts +64 -0
- package/src/lambda/tools/get-errors.ts +78 -0
- package/src/lambda/tools/get-feature-flags.ts +27 -0
- package/src/lambda/tools/get-queue-status.ts +60 -0
- package/src/lambda/tools/search-logs.ts +75 -0
- package/src/lambda/tools/send-alert.ts +37 -0
- package/src/lambda/verify-auth-challenge.ts +37 -0
|
@@ -0,0 +1,1450 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Admin Routes
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.adminRoutes = void 0;
|
|
40
|
+
const zod_1 = require("zod");
|
|
41
|
+
const db_1 = require("../../db");
|
|
42
|
+
const worker_1 = require("../../worker");
|
|
43
|
+
const data_router_1 = require("../data-router");
|
|
44
|
+
const database_connection_manager_1 = require("../database-connection-manager");
|
|
45
|
+
const db_query_helper_1 = require("../db-query-helper");
|
|
46
|
+
const domain_reputation_service_1 = require("../domain-reputation-service");
|
|
47
|
+
const feature_toggle_service_1 = require("../feature-toggle-service");
|
|
48
|
+
const logger_1 = require("../logger");
|
|
49
|
+
const middleware_1 = require("../middleware");
|
|
50
|
+
const feature_toggle_rate_limit_1 = require("../middleware/feature-toggle-rate-limit");
|
|
51
|
+
const region_detection_1 = require("../region-detection");
|
|
52
|
+
const secret_resolver_1 = require("../secret-resolver");
|
|
53
|
+
const security_headers_1 = require("../security-headers");
|
|
54
|
+
const session_manager_1 = require("../session-manager");
|
|
55
|
+
const feature_toggle_schemas_1 = require("../validation/feature-toggle-schemas");
|
|
56
|
+
const validate_request_1 = require("../validation/validate-request");
|
|
57
|
+
const version_1 = require("../version");
|
|
58
|
+
exports.adminRoutes = [
|
|
59
|
+
// Test-only endpoints (must be before wildcard routes)
|
|
60
|
+
// Test-only endpoint: Create test user (dev environment only, no auth required for tests)
|
|
61
|
+
{
|
|
62
|
+
path: "/api/admin/test/users",
|
|
63
|
+
method: "POST",
|
|
64
|
+
handler: async (request, env) => {
|
|
65
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
66
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
67
|
+
// SECURITY: Only allow in dev/test environments
|
|
68
|
+
// Note: env.ENVIRONMENT falls back to NODE_ENV (which is "production" in Docker),
|
|
69
|
+
// so prefer env.STAGE which is explicitly set by CDK to the deployment stage.
|
|
70
|
+
const environment = (env.STAGE ||
|
|
71
|
+
env.DEPLOY_ENV ||
|
|
72
|
+
"dev").toLowerCase();
|
|
73
|
+
if (environment === "prod" || environment === "production") {
|
|
74
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
75
|
+
error: "Forbidden: Test endpoints not available in production",
|
|
76
|
+
}), { status: 403, headers: { "content-type": "application/json" } });
|
|
77
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const body = (await request.json());
|
|
81
|
+
const userId = body.id || crypto.randomUUID();
|
|
82
|
+
const email = body.email ||
|
|
83
|
+
`test-${Date.now()}-${Math.random().toString(36).substring(7)}@test.example.com`;
|
|
84
|
+
const role = (body.role || "END_USER");
|
|
85
|
+
// OPTIMIZATION: Detect test users and skip authentication check for speed
|
|
86
|
+
// Test users are identified by email pattern (@test.example.com or test- prefix)
|
|
87
|
+
const isTestUser = email.includes("@test.example.com") || email.includes("test-");
|
|
88
|
+
const isCI = env.CI === "true" || env.GITHUB_ACTIONS === "true";
|
|
89
|
+
// FAST PATH: For test users, use default region from env (skip region detection)
|
|
90
|
+
// This avoids any region detection overhead and uses the fastest default
|
|
91
|
+
const defaultRegion = (env.DEFAULT_REGION || "US");
|
|
92
|
+
const region = body.region || (isTestUser ? defaultRegion : "US");
|
|
93
|
+
const dataRegion = body.dataRegion || region;
|
|
94
|
+
// SECURITY: For non-test users or non-CI environments, check authentication
|
|
95
|
+
// This is safe because:
|
|
96
|
+
// 1. Only works in dev/test environments (checked above)
|
|
97
|
+
// 2. Test users are identified by email pattern
|
|
98
|
+
// 3. Tests need fast user creation without authentication overhead
|
|
99
|
+
if (!isTestUser && !isCI) {
|
|
100
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
101
|
+
const sessionSecret = secret_resolver_1.Secrets.getSessionSecret(env);
|
|
102
|
+
const session = await sessionManager.getSession(request, sessionSecret, env);
|
|
103
|
+
if (session) {
|
|
104
|
+
// Use fast query with timeout for role check (non-blocking for test user creation)
|
|
105
|
+
const detectedRegion = (0, region_detection_1.detectRegionSync)(request, env);
|
|
106
|
+
const user = await (0, db_query_helper_1.withQueryTimeoutAndRetry)(database_connection_manager_1.sharedDatabaseConnectionManager, detectedRegion, env, async (db) => {
|
|
107
|
+
return await db.user.findUnique({
|
|
108
|
+
where: { id: session.userId },
|
|
109
|
+
select: { role: true },
|
|
110
|
+
});
|
|
111
|
+
}, {
|
|
112
|
+
...db_query_helper_1.QueryTimeoutPresets.USER_FACING, // Fast timeout (1s + 1s retry)
|
|
113
|
+
defaultValue: null, // Return null on timeout (allow test user creation)
|
|
114
|
+
context: {
|
|
115
|
+
operation: "checkUserRoleForTestEndpoint",
|
|
116
|
+
userId: session.userId,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
if (!user || user.role !== "SUPER_ADMIN") {
|
|
120
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
121
|
+
error: "Forbidden: Super-admin access required",
|
|
122
|
+
}), {
|
|
123
|
+
status: 403,
|
|
124
|
+
headers: { "content-type": "application/json" },
|
|
125
|
+
});
|
|
126
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// OPTIMIZATION: For test users, don't pass request object to avoid any overhead
|
|
131
|
+
// This ensures the fastest possible path for test user creation
|
|
132
|
+
const userCreationStartTime = Date.now();
|
|
133
|
+
// ✅ BEST PRACTICE: Defense-in-depth timeout wrapper
|
|
134
|
+
// The database query timeout (2-3s) should be sufficient, but we add a safety net
|
|
135
|
+
// to catch cases where the entire operation hangs (e.g., connection acquisition issues).
|
|
136
|
+
// Calculate based on actual database timeout configuration:
|
|
137
|
+
// - Local: 2s timeout, 0 retries = 2s max
|
|
138
|
+
// - CI: 3s timeout, 1 retry (1s) = 4s max
|
|
139
|
+
// Add 50% buffer for connection acquisition and overhead
|
|
140
|
+
const dbTimeoutMs = isCI ? 3000 : 2000;
|
|
141
|
+
const dbRetryTimeoutMs = isCI ? 1000 : 500;
|
|
142
|
+
const dbMaxRetries = isCI ? 1 : 0;
|
|
143
|
+
const maxExpectedDbTime = dbTimeoutMs + dbRetryTimeoutMs * dbMaxRetries;
|
|
144
|
+
const safetyBufferMs = Math.ceil(maxExpectedDbTime * 0.5); // 50% buffer
|
|
145
|
+
const TEST_USER_CREATION_TIMEOUT_MS = maxExpectedDbTime + safetyBufferMs;
|
|
146
|
+
const userCreationPromise = data_router_1.DataRouter.createUser({
|
|
147
|
+
id: userId,
|
|
148
|
+
email,
|
|
149
|
+
role,
|
|
150
|
+
}, region, env, isTestUser ? undefined : request);
|
|
151
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
152
|
+
setTimeout(() => {
|
|
153
|
+
reject(new Error(`Test user creation timed out after ${TEST_USER_CREATION_TIMEOUT_MS}ms. ` +
|
|
154
|
+
`Database query timeout (${dbTimeoutMs}ms) should have triggered first at <${maxExpectedDbTime}ms. ` +
|
|
155
|
+
`This indicates the database timeout mechanism may not be working correctly, ` +
|
|
156
|
+
`or there's a connection acquisition issue outside the query timeout scope.`));
|
|
157
|
+
}, TEST_USER_CREATION_TIMEOUT_MS);
|
|
158
|
+
});
|
|
159
|
+
const createdUser = await Promise.race([
|
|
160
|
+
userCreationPromise,
|
|
161
|
+
timeoutPromise,
|
|
162
|
+
]);
|
|
163
|
+
const userCreationDuration = Date.now() - userCreationStartTime;
|
|
164
|
+
logger.debug("[UserCreation] User creation completed", {
|
|
165
|
+
duration: userCreationDuration,
|
|
166
|
+
userId: createdUser.id,
|
|
167
|
+
region,
|
|
168
|
+
isTestUser,
|
|
169
|
+
});
|
|
170
|
+
// Create a session for the test user so tests don't need to know SESSION_SECRET
|
|
171
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
172
|
+
const sessionSecret = secret_resolver_1.Secrets.getSessionSecret(env);
|
|
173
|
+
const testSession = {
|
|
174
|
+
userId: createdUser.id,
|
|
175
|
+
email: createdUser.email,
|
|
176
|
+
role: role,
|
|
177
|
+
expiresAt: Date.now() + 3600000, // 1 hour
|
|
178
|
+
dataRegion: createdUser.dataRegion || region,
|
|
179
|
+
sessionType: "user",
|
|
180
|
+
lastActivityAt: Date.now(),
|
|
181
|
+
profileContext: "primary",
|
|
182
|
+
};
|
|
183
|
+
let response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
184
|
+
success: true,
|
|
185
|
+
user: {
|
|
186
|
+
id: createdUser.id,
|
|
187
|
+
email: createdUser.email,
|
|
188
|
+
role: role,
|
|
189
|
+
region: createdUser.region,
|
|
190
|
+
dataRegion: createdUser.dataRegion,
|
|
191
|
+
},
|
|
192
|
+
}), { status: 201, headers: { "content-type": "application/json" } });
|
|
193
|
+
// Set session cookie on the response
|
|
194
|
+
response = await sessionManager.setSession(response, testSession, sessionSecret, undefined, env);
|
|
195
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
logger.error("[Admin Test] Error creating test user:", error);
|
|
199
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
200
|
+
error: error.message || "Failed to create test user",
|
|
201
|
+
}), { status: 500, headers: { "content-type": "application/json" } });
|
|
202
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
middleware: [(0, middleware_1.corsMiddleware)()], // No CSRF for test endpoints (unauthenticated in CI)
|
|
206
|
+
description: "Create test user (dev environment only)",
|
|
207
|
+
},
|
|
208
|
+
// Test-only endpoint: Delete test user (dev environment only)
|
|
209
|
+
{
|
|
210
|
+
path: "/api/admin/test/users/:userId",
|
|
211
|
+
method: "DELETE",
|
|
212
|
+
handler: async (request, env, { pathname }) => {
|
|
213
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
214
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
215
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
216
|
+
// SECURITY: Only allow in dev/test environments
|
|
217
|
+
// Note: env.ENVIRONMENT falls back to NODE_ENV (which is "production" in Docker),
|
|
218
|
+
// so prefer env.STAGE which is explicitly set by CDK to the deployment stage.
|
|
219
|
+
const environment = (env.STAGE ||
|
|
220
|
+
env.DEPLOY_ENV ||
|
|
221
|
+
"dev").toLowerCase();
|
|
222
|
+
if (environment === "prod" || environment === "production") {
|
|
223
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
224
|
+
error: "Forbidden: Test endpoints not available in production",
|
|
225
|
+
}), { status: 403, headers: { "content-type": "application/json" } });
|
|
226
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
227
|
+
}
|
|
228
|
+
// SECURITY: In test mode (CI), allow unauthenticated access for test user deletion
|
|
229
|
+
const isCI = env.CI === "true" || env.GITHUB_ACTIONS === "true";
|
|
230
|
+
// Optionally check for SUPER_ADMIN in local dev (but allow unauthenticated in CI)
|
|
231
|
+
if (!isCI) {
|
|
232
|
+
const sessionSecret = secret_resolver_1.Secrets.getSessionSecret(env);
|
|
233
|
+
const session = await sessionManager.getSession(request, sessionSecret, env);
|
|
234
|
+
if (session) {
|
|
235
|
+
const db = (0, db_1.createPrisma)(env);
|
|
236
|
+
const user = await db.user.findUnique({
|
|
237
|
+
where: { id: session.userId },
|
|
238
|
+
select: { role: true },
|
|
239
|
+
});
|
|
240
|
+
if (!user || user.role !== "SUPER_ADMIN") {
|
|
241
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
242
|
+
error: "Forbidden: Super-admin access required",
|
|
243
|
+
}), { status: 403, headers: { "content-type": "application/json" } });
|
|
244
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// If no session in local dev, still allow (for test convenience)
|
|
248
|
+
}
|
|
249
|
+
// Extract userId from pathname (outside try block for error handler access)
|
|
250
|
+
const userIdMatch = pathname.match(/\/api\/admin\/test\/users\/([^/]+)/);
|
|
251
|
+
if (!userIdMatch) {
|
|
252
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Invalid user ID" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
253
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
254
|
+
}
|
|
255
|
+
const userId = userIdMatch[1];
|
|
256
|
+
try {
|
|
257
|
+
// Delete user via DataRouter (uses API's database connection)
|
|
258
|
+
const region = (0, region_detection_1.detectRegionSync)(request, env);
|
|
259
|
+
const dbManager = database_connection_manager_1.sharedDatabaseConnectionManager;
|
|
260
|
+
await (0, db_query_helper_1.withQueryTimeoutAndRetry)(dbManager, region, env, async (db) => {
|
|
261
|
+
const { deleteUserData } = await Promise.resolve().then(() => __importStar(require("../services/user-data-deletion")));
|
|
262
|
+
await deleteUserData(db, userId);
|
|
263
|
+
}, {
|
|
264
|
+
...db_query_helper_1.QueryTimeoutPresets.STANDARD,
|
|
265
|
+
timeoutMs: 5000, // 5 seconds for cleanup (more time for multiple deletes)
|
|
266
|
+
retryTimeoutMs: 2000, // 2 seconds for retry
|
|
267
|
+
maxRetries: 1, // Allow 1 retry for cleanup operations
|
|
268
|
+
});
|
|
269
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
270
|
+
success: true,
|
|
271
|
+
message: "Test user deleted successfully",
|
|
272
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
273
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
// Ignore "Record to delete does not exist" errors
|
|
277
|
+
if (error.message?.includes("Record to delete does not exist")) {
|
|
278
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
279
|
+
success: true,
|
|
280
|
+
message: "User already deleted or does not exist",
|
|
281
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
282
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
283
|
+
}
|
|
284
|
+
// Ignore foreign key constraint violations - user may have already been deleted
|
|
285
|
+
// or related records may have been cleaned up by cascade deletes
|
|
286
|
+
if (error.message?.includes("Foreign key constraint") ||
|
|
287
|
+
error.message?.includes("foreign key constraint violated")) {
|
|
288
|
+
// Try to verify if user still exists
|
|
289
|
+
try {
|
|
290
|
+
const verifyRegion = (0, region_detection_1.detectRegionSync)(request, env);
|
|
291
|
+
const verifyDbManager = database_connection_manager_1.sharedDatabaseConnectionManager;
|
|
292
|
+
const userExists = await (0, db_query_helper_1.withQueryTimeoutAndRetry)(verifyDbManager, verifyRegion, env, async (db) => {
|
|
293
|
+
const user = await db.user.findUnique({
|
|
294
|
+
where: { id: userId },
|
|
295
|
+
select: { id: true },
|
|
296
|
+
});
|
|
297
|
+
return !!user;
|
|
298
|
+
}, {
|
|
299
|
+
...db_query_helper_1.QueryTimeoutPresets.STANDARD,
|
|
300
|
+
defaultValue: false, // Assume deleted if query fails
|
|
301
|
+
});
|
|
302
|
+
if (!userExists) {
|
|
303
|
+
// User is already deleted, return success
|
|
304
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
305
|
+
success: true,
|
|
306
|
+
message: "User already deleted (foreign key constraint handled)",
|
|
307
|
+
}), {
|
|
308
|
+
status: 200,
|
|
309
|
+
headers: { "content-type": "application/json" },
|
|
310
|
+
});
|
|
311
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch (verifyError) {
|
|
315
|
+
// If verification fails, log and continue with error response
|
|
316
|
+
logger.warn("[Admin Test] Error verifying user deletion:", verifyError);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
logger.error("[Admin Test] Error deleting test user:", error);
|
|
320
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
321
|
+
error: error.message || "Failed to delete test user",
|
|
322
|
+
}), { status: 500, headers: { "content-type": "application/json" } });
|
|
323
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
middleware: [(0, middleware_1.corsMiddleware)()], // No CSRF for test endpoints (unauthenticated in CI)
|
|
327
|
+
description: "Delete test user (dev environment only)",
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
path: "/api/admin/super-admin/*",
|
|
331
|
+
method: "*",
|
|
332
|
+
handler: async (request, env, { pathname }) => {
|
|
333
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
334
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
335
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
336
|
+
// Get session secret with error handling
|
|
337
|
+
let sessionSecret;
|
|
338
|
+
try {
|
|
339
|
+
logger.debug("[Admin] Getting session secret...");
|
|
340
|
+
sessionSecret = secret_resolver_1.Secrets.getSessionSecret(env);
|
|
341
|
+
logger.debug(`[Admin] Session secret retrieved, type: ${typeof sessionSecret}, length: ${sessionSecret?.length ?? "N/A"}`);
|
|
342
|
+
if (!sessionSecret || typeof sessionSecret !== "string") {
|
|
343
|
+
logger.error(`[Admin] Invalid session secret from Secrets.getSessionSecret: ${typeof sessionSecret}, ${sessionSecret ? "present but invalid" : "missing"}`);
|
|
344
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Server configuration error" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
345
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
346
|
+
}
|
|
347
|
+
logger.debug("[Admin] Session secret is valid, length:", sessionSecret.length);
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
logger.error("[Admin] Error getting session secret:", error);
|
|
351
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Server configuration error" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
352
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
353
|
+
}
|
|
354
|
+
logger.debug("[Admin] Calling getSession with secret length:", sessionSecret.length);
|
|
355
|
+
const session = await sessionManager.getSession(request, sessionSecret, env);
|
|
356
|
+
logger.debug("[Admin] getSession returned:", session ? "session found" : "null (unauthorized)");
|
|
357
|
+
if (!session) {
|
|
358
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
359
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
360
|
+
}
|
|
361
|
+
const db = (0, db_1.createPrisma)(env);
|
|
362
|
+
const user = await db.user.findUnique({
|
|
363
|
+
where: { id: session.userId },
|
|
364
|
+
select: { role: true, email: true },
|
|
365
|
+
});
|
|
366
|
+
if (!user) {
|
|
367
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: User not found" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
368
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
369
|
+
}
|
|
370
|
+
const isSuperAdmin = user.role === "SUPER_ADMIN";
|
|
371
|
+
if (pathname === "/api/admin/super-admin/check" &&
|
|
372
|
+
request.method === "GET") {
|
|
373
|
+
logger.debug("[SuperAdmin] Check request", {
|
|
374
|
+
userEmail: user.email,
|
|
375
|
+
userRole: user.role,
|
|
376
|
+
isSuperAdmin,
|
|
377
|
+
});
|
|
378
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({ isSuperAdmin }), { status: 200, headers: { "content-type": "application/json" } });
|
|
379
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
380
|
+
}
|
|
381
|
+
if (!isSuperAdmin) {
|
|
382
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Super-admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
383
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
384
|
+
}
|
|
385
|
+
const toggleService = new feature_toggle_service_1.FeatureToggleService(db);
|
|
386
|
+
// Get all feature toggles
|
|
387
|
+
if (pathname === "/api/admin/super-admin/feature-toggles" &&
|
|
388
|
+
request.method === "GET") {
|
|
389
|
+
try {
|
|
390
|
+
// Use standard timeout presets (consistent with other endpoints)
|
|
391
|
+
// DatabaseConnectionManager handles connection health and stale connection cleanup
|
|
392
|
+
const dbManager = database_connection_manager_1.sharedDatabaseConnectionManager;
|
|
393
|
+
const region = (0, region_detection_1.detectRegionSync)(request, env);
|
|
394
|
+
// Use STANDARD preset (3s initial + 2s retry = 5s total)
|
|
395
|
+
// This is consistent with other user-facing endpoints and well below Worker limits
|
|
396
|
+
// Use defaultValue to return empty array on timeout/error (graceful degradation)
|
|
397
|
+
let toggles = [];
|
|
398
|
+
try {
|
|
399
|
+
toggles = await (0, db_query_helper_1.withQueryTimeoutAndRetry)(dbManager, region, env, async (client) => {
|
|
400
|
+
const service = new feature_toggle_service_1.FeatureToggleService(client);
|
|
401
|
+
return await service.getAllToggles();
|
|
402
|
+
}, {
|
|
403
|
+
...db_query_helper_1.QueryTimeoutPresets.STANDARD, // 1s initial, 0.5s retry (optimized)
|
|
404
|
+
defaultValue: [], // Return empty array on timeout/error (graceful degradation)
|
|
405
|
+
maxRetries: 1, // Only 1 retry to keep total time under 2s
|
|
406
|
+
context: {
|
|
407
|
+
operation: "getAllFeatureToggles",
|
|
408
|
+
userEmail: user.email,
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
// Ensure toggles is always an array (defensive check)
|
|
412
|
+
if (!Array.isArray(toggles)) {
|
|
413
|
+
logger.warn("[SuperAdmin] getAllToggles returned non-array, using empty array", { togglesType: typeof toggles });
|
|
414
|
+
toggles = [];
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
// Defensive: If defaultValue wasn't returned (shouldn't happen, but be safe)
|
|
419
|
+
// Log the error and use empty array as fallback
|
|
420
|
+
// This should never happen if executeWithRetry is working correctly,
|
|
421
|
+
// but we handle it defensively to ensure we always return a valid response
|
|
422
|
+
logger.warn("[SuperAdmin] Error in getAllToggles, using empty array fallback", {
|
|
423
|
+
error: error?.message || String(error),
|
|
424
|
+
errorCode: error?.code,
|
|
425
|
+
errorName: error?.name,
|
|
426
|
+
hasDefaultValue: true,
|
|
427
|
+
// This indicates executeWithRetry didn't return defaultValue as expected
|
|
428
|
+
// This is a defensive fallback to ensure graceful degradation
|
|
429
|
+
});
|
|
430
|
+
toggles = []; // Fallback to empty array
|
|
431
|
+
}
|
|
432
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
433
|
+
toggles: toggles.map((toggle) => ({
|
|
434
|
+
key: toggle.key,
|
|
435
|
+
enabled: toggle.enabled,
|
|
436
|
+
lastChanged: toggle.lastChanged?.toISOString(),
|
|
437
|
+
changedBy: toggle.changedBy,
|
|
438
|
+
description: toggle.description,
|
|
439
|
+
})),
|
|
440
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
441
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
logger.error("[SuperAdmin] Error getting all feature toggles:", error);
|
|
445
|
+
logger.error("[SuperAdmin] Error stack:", error instanceof Error ? error.stack : "No stack trace");
|
|
446
|
+
// Extract error details once
|
|
447
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
448
|
+
const errorString = String(error).toLowerCase();
|
|
449
|
+
logger.error("[SuperAdmin] Error type and message:", {
|
|
450
|
+
type: typeof error,
|
|
451
|
+
isError: error instanceof Error,
|
|
452
|
+
message: errorMessage,
|
|
453
|
+
string: errorString,
|
|
454
|
+
errorCode: error?.code,
|
|
455
|
+
errorName: error?.name,
|
|
456
|
+
});
|
|
457
|
+
// Check if it's a timeout error (including connection timeouts)
|
|
458
|
+
// Also check for memory errors which can occur with stale connections
|
|
459
|
+
// Also check for prepared statement errors (PgBouncer transaction mode limitation)
|
|
460
|
+
// Be very permissive - if defaultValue was set, we should return it for ANY error
|
|
461
|
+
// Since we configured defaultValue: [], treat ANY error as a timeout/connection issue
|
|
462
|
+
// This provides graceful degradation - if the database is having issues, return empty array
|
|
463
|
+
const isTimeout = errorMessage.includes("timeout") ||
|
|
464
|
+
errorMessage.includes("exceeded") ||
|
|
465
|
+
errorMessage.includes("Database query timeout") ||
|
|
466
|
+
errorMessage.includes("timeout exceeded when trying to connect") ||
|
|
467
|
+
errorMessage.includes("Database query failed after") ||
|
|
468
|
+
errorMessage.includes("memory access out of bounds") || // PrismaPg adapter error from stale connections
|
|
469
|
+
errorMessage.includes("ECONNREFUSED") ||
|
|
470
|
+
errorMessage.includes("ETIMEDOUT") ||
|
|
471
|
+
errorMessage.includes("ENOTFOUND") ||
|
|
472
|
+
errorMessage.includes("ECONNRESET") ||
|
|
473
|
+
errorMessage.includes("ENETUNREACH") ||
|
|
474
|
+
errorString.includes("timeout") ||
|
|
475
|
+
errorString.includes("exceeded") ||
|
|
476
|
+
errorString.includes("database query failed") ||
|
|
477
|
+
errorString.includes("memory access") ||
|
|
478
|
+
errorString.includes("connection");
|
|
479
|
+
// Check for prepared statement errors (PgBouncer transaction mode doesn't support prepared statements)
|
|
480
|
+
const isPreparedStatementError = errorMessage.includes("prepared statement") ||
|
|
481
|
+
errorMessage.includes("does not exist") ||
|
|
482
|
+
errorMessage.includes("already exists") ||
|
|
483
|
+
errorString.includes("prepared statement") ||
|
|
484
|
+
error?.code === "26000" || // PostgreSQL error code for invalid prepared statement
|
|
485
|
+
error?.code === "42P05"; // PostgreSQL error code for duplicate prepared statement
|
|
486
|
+
// If it's a timeout/connection error OR any database-related error OR prepared statement error,
|
|
487
|
+
// return empty array (graceful degradation)
|
|
488
|
+
// This matches the defaultValue: [] behavior we configured in withQueryTimeoutAndRetry
|
|
489
|
+
// The executeWithRetry should have returned defaultValue, but if it still throws,
|
|
490
|
+
// we handle it here as a fallback
|
|
491
|
+
// Be very permissive - ANY error from database operations should return empty array
|
|
492
|
+
// Since we configured defaultValue: [], any error means the database query failed
|
|
493
|
+
// Check error message, error string, and error code
|
|
494
|
+
const isDatabaseError = isTimeout ||
|
|
495
|
+
isPreparedStatementError ||
|
|
496
|
+
errorMessage.includes("Database") ||
|
|
497
|
+
errorMessage.includes("Prisma") ||
|
|
498
|
+
errorMessage.includes("query") ||
|
|
499
|
+
errorMessage.includes("connection") ||
|
|
500
|
+
errorMessage.includes("timeout") ||
|
|
501
|
+
errorMessage.includes("exceeded") ||
|
|
502
|
+
errorMessage.includes("failed after") || // "Database query failed after X retries"
|
|
503
|
+
errorString.includes("database") ||
|
|
504
|
+
errorString.includes("prisma") ||
|
|
505
|
+
errorString.includes("query") ||
|
|
506
|
+
errorString.includes("connection") ||
|
|
507
|
+
errorString.includes("timeout") ||
|
|
508
|
+
errorString.includes("failed after") ||
|
|
509
|
+
error?.code?.startsWith("P") || // Prisma error codes (P1001, P2021, etc.)
|
|
510
|
+
error?.code?.startsWith("08") || // PostgreSQL connection error codes (08P01, etc.)
|
|
511
|
+
error?.code?.startsWith("42") || // PostgreSQL syntax/state error codes (42P05, etc.)
|
|
512
|
+
true; // Catch ALL errors - if defaultValue was set, any error should return it
|
|
513
|
+
// Since we configured defaultValue: [] in withQueryTimeoutAndRetry,
|
|
514
|
+
// ANY error from database operations should return empty array
|
|
515
|
+
// This provides graceful degradation - if database is having issues, return empty array
|
|
516
|
+
// The isDatabaseError check includes `true` at the end to catch ALL errors
|
|
517
|
+
logger.warn("[SuperAdmin] Error detected in feature toggle query, returning empty array (graceful degradation)", {
|
|
518
|
+
errorMessage,
|
|
519
|
+
isTimeout,
|
|
520
|
+
isPreparedStatementError,
|
|
521
|
+
isDatabaseError,
|
|
522
|
+
errorCode: error?.code,
|
|
523
|
+
errorName: error?.name,
|
|
524
|
+
});
|
|
525
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
526
|
+
toggles: [],
|
|
527
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
528
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
// Create a new feature toggle
|
|
532
|
+
if (pathname === "/api/admin/super-admin/feature-toggles" &&
|
|
533
|
+
request.method === "POST") {
|
|
534
|
+
try {
|
|
535
|
+
// Rate limit admin API
|
|
536
|
+
const rateLimitResult = await (0, feature_toggle_rate_limit_1.rateLimitAdminFeatureToggleAPI)(request, env, user.email);
|
|
537
|
+
if (!rateLimitResult || !rateLimitResult.allowed) {
|
|
538
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
539
|
+
error: {
|
|
540
|
+
code: "RATE_LIMIT_EXCEEDED",
|
|
541
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
542
|
+
retryAfter: rateLimitResult
|
|
543
|
+
? Math.ceil((rateLimitResult.resetAt - Date.now()) / 1000)
|
|
544
|
+
: 60,
|
|
545
|
+
},
|
|
546
|
+
}), {
|
|
547
|
+
status: 429,
|
|
548
|
+
headers: {
|
|
549
|
+
"content-type": "application/json",
|
|
550
|
+
...(rateLimitResult?.headers || {}),
|
|
551
|
+
},
|
|
552
|
+
});
|
|
553
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
554
|
+
}
|
|
555
|
+
// Validate request body
|
|
556
|
+
const CreateToggleSchema = zod_1.z.object({
|
|
557
|
+
key: feature_toggle_schemas_1.FeatureToggleKeySchema,
|
|
558
|
+
enabled: zod_1.z.boolean().default(false),
|
|
559
|
+
description: zod_1.z.string().max(1000).optional(),
|
|
560
|
+
});
|
|
561
|
+
const { key, enabled, description } = (0, validate_request_1.validateBody)(CreateToggleSchema, await request.json());
|
|
562
|
+
// Check if toggle already exists
|
|
563
|
+
const existing = await toggleService.getToggle(key);
|
|
564
|
+
if (existing) {
|
|
565
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Feature toggle already exists" }), { status: 409, headers: { "content-type": "application/json" } });
|
|
566
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
567
|
+
}
|
|
568
|
+
// Create the toggle
|
|
569
|
+
const toggle = await toggleService.setToggle(key, enabled, user.email, description);
|
|
570
|
+
const responseHeaders = {
|
|
571
|
+
"content-type": "application/json",
|
|
572
|
+
...rateLimitResult.headers,
|
|
573
|
+
};
|
|
574
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
575
|
+
success: true,
|
|
576
|
+
toggle: {
|
|
577
|
+
key: toggle.key,
|
|
578
|
+
enabled: toggle.enabled,
|
|
579
|
+
lastChanged: toggle.lastChanged.toISOString(),
|
|
580
|
+
changedBy: toggle.changedBy,
|
|
581
|
+
description: description,
|
|
582
|
+
},
|
|
583
|
+
}), { status: 201, headers: responseHeaders });
|
|
584
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
if (error instanceof validate_request_1.ValidationError) {
|
|
588
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: error.message }), { status: 400, headers: { "content-type": "application/json" } });
|
|
589
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
590
|
+
}
|
|
591
|
+
logger.error("[SuperAdmin] Error creating feature toggle:", error);
|
|
592
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to create feature toggle" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
593
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (pathname === "/api/admin/super-admin/settings" &&
|
|
597
|
+
request.method === "GET") {
|
|
598
|
+
try {
|
|
599
|
+
const globalPublicPosting = await toggleService.getToggle("global_public_posting_enabled");
|
|
600
|
+
const signupToggle = await toggleService.getToggle("user_signup_mode");
|
|
601
|
+
let signupMode = "open";
|
|
602
|
+
if (signupToggle?.description) {
|
|
603
|
+
const modeMatch = signupToggle.description.match(/user_signup_mode:(open|invitation_only|disabled)/);
|
|
604
|
+
if (modeMatch) {
|
|
605
|
+
signupMode = modeMatch[1];
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
else if (signupToggle?.enabled === false) {
|
|
609
|
+
signupMode = "disabled";
|
|
610
|
+
}
|
|
611
|
+
const superAdminCount = await db.user.count({
|
|
612
|
+
where: { role: "SUPER_ADMIN" },
|
|
613
|
+
});
|
|
614
|
+
const settings = {
|
|
615
|
+
featureToggles: {
|
|
616
|
+
global_public_posting_enabled: {
|
|
617
|
+
enabled: globalPublicPosting?.enabled ?? false,
|
|
618
|
+
lastChanged: globalPublicPosting?.lastChanged?.toISOString(),
|
|
619
|
+
changedBy: globalPublicPosting?.changedBy,
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
signupSettings: {
|
|
623
|
+
mode: signupMode,
|
|
624
|
+
lastChanged: signupToggle?.lastChanged?.toISOString(),
|
|
625
|
+
changedBy: signupToggle?.changedBy,
|
|
626
|
+
},
|
|
627
|
+
systemInfo: {
|
|
628
|
+
environment: env.ENVIRONMENT || "unknown",
|
|
629
|
+
version: (0, version_1.getAppVersion)(env),
|
|
630
|
+
superAdminCount,
|
|
631
|
+
},
|
|
632
|
+
};
|
|
633
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify(settings), { status: 200, headers: { "content-type": "application/json" } });
|
|
634
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
logger.error("[SuperAdmin] Error getting settings:", error);
|
|
638
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to get settings" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
639
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
const toggleUpdateMatch = pathname.match(/^\/api\/admin\/super-admin\/feature-toggles\/(.+)$/);
|
|
643
|
+
if (toggleUpdateMatch && request.method === "PUT") {
|
|
644
|
+
try {
|
|
645
|
+
logger.debug(`[Admin] PUT request for feature toggle, pathname: ${pathname}`);
|
|
646
|
+
logger.debug(`[Admin] toggleUpdateMatch: ${JSON.stringify(toggleUpdateMatch)}`);
|
|
647
|
+
logger.debug(`[Admin] user.email: ${user.email}, type: ${typeof user.email}`);
|
|
648
|
+
// Rate limit admin API (1000 requests/minute per user)
|
|
649
|
+
// Ensure user.email is defined and is a string for rate limiting
|
|
650
|
+
if (!user.email || typeof user.email !== "string") {
|
|
651
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "User email not found or invalid" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
652
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
653
|
+
}
|
|
654
|
+
const rateLimitResult = await (0, feature_toggle_rate_limit_1.rateLimitAdminFeatureToggleAPI)(request, env, user.email);
|
|
655
|
+
if (!rateLimitResult || !rateLimitResult.allowed) {
|
|
656
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
657
|
+
error: {
|
|
658
|
+
code: "RATE_LIMIT_EXCEEDED",
|
|
659
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
660
|
+
retryAfter: rateLimitResult
|
|
661
|
+
? Math.ceil((rateLimitResult.resetAt - Date.now()) / 1000)
|
|
662
|
+
: 60,
|
|
663
|
+
},
|
|
664
|
+
}), {
|
|
665
|
+
status: 429,
|
|
666
|
+
headers: {
|
|
667
|
+
"content-type": "application/json",
|
|
668
|
+
...(rateLimitResult?.headers || {}),
|
|
669
|
+
},
|
|
670
|
+
});
|
|
671
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
672
|
+
}
|
|
673
|
+
// Validate path parameter (toggle key)
|
|
674
|
+
const pathParam = toggleUpdateMatch?.[1];
|
|
675
|
+
if (!pathParam || typeof pathParam !== "string") {
|
|
676
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
677
|
+
error: "Invalid path parameter: toggle key is required",
|
|
678
|
+
}), { status: 400, headers: { "content-type": "application/json" } });
|
|
679
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
680
|
+
}
|
|
681
|
+
let toggleKey;
|
|
682
|
+
try {
|
|
683
|
+
toggleKey = (0, validate_request_1.validatePathParam)(feature_toggle_schemas_1.FeatureToggleKeySchema, pathParam);
|
|
684
|
+
}
|
|
685
|
+
catch (error) {
|
|
686
|
+
if (error instanceof validate_request_1.ValidationError) {
|
|
687
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify(error.toResponse()), {
|
|
688
|
+
status: 400,
|
|
689
|
+
headers: { "content-type": "application/json" },
|
|
690
|
+
});
|
|
691
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
692
|
+
}
|
|
693
|
+
throw error;
|
|
694
|
+
}
|
|
695
|
+
// Validate request body
|
|
696
|
+
let body;
|
|
697
|
+
try {
|
|
698
|
+
body = await request.json();
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Invalid JSON in request body" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
702
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
703
|
+
}
|
|
704
|
+
// Ensure body is an object
|
|
705
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
706
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Request body must be an object" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
707
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
708
|
+
}
|
|
709
|
+
const UpdateToggleEnabledSchema = zod_1.z.object({
|
|
710
|
+
enabled: zod_1.z.boolean({
|
|
711
|
+
required_error: "enabled is required",
|
|
712
|
+
invalid_type_error: "enabled must be a boolean",
|
|
713
|
+
}),
|
|
714
|
+
});
|
|
715
|
+
let enabled;
|
|
716
|
+
try {
|
|
717
|
+
const validated = (0, validate_request_1.validateBody)(UpdateToggleEnabledSchema, body);
|
|
718
|
+
enabled = validated.enabled;
|
|
719
|
+
}
|
|
720
|
+
catch (error) {
|
|
721
|
+
if (error instanceof validate_request_1.ValidationError) {
|
|
722
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify(error.toResponse()), {
|
|
723
|
+
status: 400,
|
|
724
|
+
headers: { "content-type": "application/json" },
|
|
725
|
+
});
|
|
726
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
727
|
+
}
|
|
728
|
+
// Log unexpected errors for debugging
|
|
729
|
+
logger.error("[Admin] Unexpected error in body validation:", error);
|
|
730
|
+
throw error;
|
|
731
|
+
}
|
|
732
|
+
// Use improved database connection manager with aggressive timeout handling
|
|
733
|
+
const dbManager = database_connection_manager_1.sharedDatabaseConnectionManager;
|
|
734
|
+
const region = (0, region_detection_1.detectRegionSync)(request, env);
|
|
735
|
+
// Top-level timeout wrapper to ensure we never hang for more than 3 seconds
|
|
736
|
+
// This is well below Cloudflare's 30-second limit and ensures we always return a response
|
|
737
|
+
// Aggressive timeout to fail fast if database is slow
|
|
738
|
+
const MAX_TOTAL_TIMEOUT_MS = 3000; // 3 seconds total - fail fast
|
|
739
|
+
let timeoutId = null;
|
|
740
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
741
|
+
timeoutId = setTimeout(() => {
|
|
742
|
+
reject(new Error("Request timeout: Database operation exceeded maximum time limit"));
|
|
743
|
+
}, MAX_TOTAL_TIMEOUT_MS);
|
|
744
|
+
});
|
|
745
|
+
let toggle;
|
|
746
|
+
try {
|
|
747
|
+
// Wrap the entire operation in a timeout-safe wrapper
|
|
748
|
+
const dbOperation = (async () => {
|
|
749
|
+
try {
|
|
750
|
+
return await dbManager.executeWithRetry(region, env, async (client) => {
|
|
751
|
+
// Create a temporary service instance with the client from timeout helper
|
|
752
|
+
const service = new feature_toggle_service_1.FeatureToggleService(client);
|
|
753
|
+
// Ensure user.email is still defined (double-check before DB operation)
|
|
754
|
+
if (!user.email || typeof user.email !== "string") {
|
|
755
|
+
throw new Error("User email is required for toggle update");
|
|
756
|
+
}
|
|
757
|
+
return await service.setToggle(toggleKey, enabled, user.email, toggleKey === "global_public_posting_enabled"
|
|
758
|
+
? "Globally enable public posting for all users"
|
|
759
|
+
: undefined);
|
|
760
|
+
}, {
|
|
761
|
+
timeoutMs: 1000, // 1 second initial timeout - fail fast
|
|
762
|
+
retryTimeoutMs: 500, // 0.5 seconds retry timeout - very fast retry
|
|
763
|
+
maxRetries: 1, // Only 1 retry to keep total time under 2s
|
|
764
|
+
context: {
|
|
765
|
+
operation: "updateFeatureToggle",
|
|
766
|
+
userEmail: user.email,
|
|
767
|
+
toggleKey: toggleKey,
|
|
768
|
+
},
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
catch (error) {
|
|
772
|
+
// Re-throw with more context
|
|
773
|
+
throw new Error(`Database operation failed: ${error.message || String(error)}`);
|
|
774
|
+
}
|
|
775
|
+
})();
|
|
776
|
+
// Race the database operation against the top-level timeout
|
|
777
|
+
// This ensures we ALWAYS return a response within 6 seconds
|
|
778
|
+
toggle = await Promise.race([dbOperation, timeoutPromise]);
|
|
779
|
+
// Clear timeout if operation succeeded
|
|
780
|
+
if (timeoutId) {
|
|
781
|
+
clearTimeout(timeoutId);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
catch (dbError) {
|
|
785
|
+
// Clear timeout on error
|
|
786
|
+
if (timeoutId) {
|
|
787
|
+
clearTimeout(timeoutId);
|
|
788
|
+
}
|
|
789
|
+
logger.error("[SuperAdmin] Database error updating feature toggle:", {
|
|
790
|
+
error: dbError.message,
|
|
791
|
+
stack: dbError.stack,
|
|
792
|
+
toggleKey,
|
|
793
|
+
userEmail: user.email,
|
|
794
|
+
isTimeout: dbError.message?.includes("timeout") ||
|
|
795
|
+
dbError.message?.includes("exceeded"),
|
|
796
|
+
});
|
|
797
|
+
// Return a user-friendly error response instead of letting it bubble up
|
|
798
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
799
|
+
error: "Database operation timed out. Please try again in a moment.",
|
|
800
|
+
details: "The database connection is experiencing issues. This usually resolves quickly.",
|
|
801
|
+
}), { status: 503, headers: { "content-type": "application/json" } });
|
|
802
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
803
|
+
}
|
|
804
|
+
// Add rate limit headers to successful response
|
|
805
|
+
const responseHeaders = {
|
|
806
|
+
"content-type": "application/json",
|
|
807
|
+
...rateLimitResult.headers,
|
|
808
|
+
};
|
|
809
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
810
|
+
success: true,
|
|
811
|
+
toggle: {
|
|
812
|
+
key: toggle.key,
|
|
813
|
+
enabled: toggle.enabled,
|
|
814
|
+
lastChanged: toggle.lastChanged.toISOString(),
|
|
815
|
+
changedBy: toggle.changedBy,
|
|
816
|
+
},
|
|
817
|
+
}), { status: 200, headers: responseHeaders });
|
|
818
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
819
|
+
}
|
|
820
|
+
catch (error) {
|
|
821
|
+
// Handle validation errors
|
|
822
|
+
if (error instanceof validate_request_1.ValidationError) {
|
|
823
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify(error.toResponse()), {
|
|
824
|
+
status: error.getStatusCode(),
|
|
825
|
+
headers: { "content-type": "application/json" },
|
|
826
|
+
});
|
|
827
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
828
|
+
}
|
|
829
|
+
logger.error("[SuperAdmin] Error updating feature toggle:", error);
|
|
830
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to update feature toggle" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
831
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (pathname === "/api/admin/super-admin/signup-settings" &&
|
|
835
|
+
request.method === "PUT") {
|
|
836
|
+
try {
|
|
837
|
+
const body = (await request.json());
|
|
838
|
+
const { mode } = body;
|
|
839
|
+
if (!mode ||
|
|
840
|
+
!["open", "invitation_only", "disabled"].includes(mode)) {
|
|
841
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
842
|
+
error: 'Invalid request: mode must be "open", "invitation_only", or "disabled"',
|
|
843
|
+
}), { status: 400, headers: { "content-type": "application/json" } });
|
|
844
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
845
|
+
}
|
|
846
|
+
const enabled = mode !== "disabled";
|
|
847
|
+
const description = `user_signup_mode:${mode}`;
|
|
848
|
+
const toggle = await toggleService.setToggle("user_signup_mode", enabled, user.email, description);
|
|
849
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
850
|
+
success: true,
|
|
851
|
+
signupSettings: {
|
|
852
|
+
mode: mode,
|
|
853
|
+
lastChanged: toggle.lastChanged.toISOString(),
|
|
854
|
+
changedBy: toggle.changedBy,
|
|
855
|
+
},
|
|
856
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
857
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
858
|
+
}
|
|
859
|
+
catch (error) {
|
|
860
|
+
logger.error("[SuperAdmin] Error updating sign-up settings:", error);
|
|
861
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to update sign-up settings" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
862
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Not found" }), { status: 404, headers: { "content-type": "application/json" } });
|
|
866
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
867
|
+
},
|
|
868
|
+
middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
|
|
869
|
+
description: "Super-admin routes",
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
path: /^\/api\/feature-toggles\/(.+)$/,
|
|
873
|
+
method: "GET",
|
|
874
|
+
handler: async (request, env, { pathname }) => {
|
|
875
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
876
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
877
|
+
const toggleKeyMatch = pathname.match(/^\/api\/feature-toggles\/(.+)$/);
|
|
878
|
+
if (!toggleKeyMatch) {
|
|
879
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({ enabled: false }), { status: 200, headers: { "content-type": "application/json" } });
|
|
880
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
881
|
+
}
|
|
882
|
+
try {
|
|
883
|
+
// Rate limit public API (100 requests/minute per IP)
|
|
884
|
+
const rateLimitResult = await (0, feature_toggle_rate_limit_1.rateLimitFeatureToggleAPI)(request, env);
|
|
885
|
+
if (!rateLimitResult || !rateLimitResult.allowed) {
|
|
886
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
887
|
+
error: {
|
|
888
|
+
code: "RATE_LIMIT_EXCEEDED",
|
|
889
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
890
|
+
retryAfter: rateLimitResult
|
|
891
|
+
? Math.ceil((rateLimitResult.resetAt - Date.now()) / 1000)
|
|
892
|
+
: 60,
|
|
893
|
+
},
|
|
894
|
+
}), {
|
|
895
|
+
status: 429,
|
|
896
|
+
headers: {
|
|
897
|
+
"content-type": "application/json",
|
|
898
|
+
...(rateLimitResult?.headers || {}),
|
|
899
|
+
},
|
|
900
|
+
});
|
|
901
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
902
|
+
}
|
|
903
|
+
// Validate path parameter (toggle key)
|
|
904
|
+
const toggleKey = (0, validate_request_1.validatePathParam)(feature_toggle_schemas_1.FeatureToggleKeySchema, toggleKeyMatch[1]);
|
|
905
|
+
// Validate query parameters
|
|
906
|
+
const url = new URL(request.url);
|
|
907
|
+
const queryParams = {};
|
|
908
|
+
url.searchParams.forEach((value, key) => {
|
|
909
|
+
queryParams[key] = value;
|
|
910
|
+
});
|
|
911
|
+
const validatedQuery = (0, validate_request_1.validateQuery)(feature_toggle_schemas_1.PublicAPIQuerySchema, queryParams);
|
|
912
|
+
const db = (0, db_1.createPrisma)(env);
|
|
913
|
+
const toggleService = new feature_toggle_service_1.FeatureToggleService(db);
|
|
914
|
+
const toggle = await toggleService.getToggle(toggleKey);
|
|
915
|
+
if (!toggle) {
|
|
916
|
+
// Add rate limit headers even for not found responses
|
|
917
|
+
const responseHeaders = {
|
|
918
|
+
"content-type": "application/json",
|
|
919
|
+
...rateLimitResult.headers,
|
|
920
|
+
};
|
|
921
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({ key: toggleKey, enabled: false }), { status: 200, headers: responseHeaders });
|
|
922
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
923
|
+
}
|
|
924
|
+
// Add rate limit headers to successful response
|
|
925
|
+
const responseHeaders = {
|
|
926
|
+
"content-type": "application/json",
|
|
927
|
+
...rateLimitResult.headers,
|
|
928
|
+
};
|
|
929
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
930
|
+
enabled: toggle.enabled,
|
|
931
|
+
key: toggle.key,
|
|
932
|
+
lastChanged: toggle.lastChanged?.toISOString(),
|
|
933
|
+
changedBy: toggle.changedBy,
|
|
934
|
+
}), { status: 200, headers: responseHeaders });
|
|
935
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
936
|
+
}
|
|
937
|
+
catch (error) {
|
|
938
|
+
logger.error(`[Admin] GET handler error: ${error instanceof Error ? error.message : String(error)}`, {
|
|
939
|
+
errorType: error?.constructor?.name,
|
|
940
|
+
stack: error instanceof Error ? error.stack : "No stack",
|
|
941
|
+
});
|
|
942
|
+
// Handle validation errors
|
|
943
|
+
if (error instanceof validate_request_1.ValidationError) {
|
|
944
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify(error.toResponse()), {
|
|
945
|
+
status: error.getStatusCode(),
|
|
946
|
+
headers: { "content-type": "application/json" },
|
|
947
|
+
});
|
|
948
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
949
|
+
}
|
|
950
|
+
// For other errors, return 500
|
|
951
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
952
|
+
error: "Internal server error",
|
|
953
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
954
|
+
}), { status: 500, headers: { "content-type": "application/json" } });
|
|
955
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
middleware: [(0, middleware_1.corsMiddleware)()],
|
|
959
|
+
description: "Get feature toggle status",
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
path: "/api/roles/metadata",
|
|
963
|
+
method: "GET",
|
|
964
|
+
handler: async (request, env) => {
|
|
965
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
966
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
967
|
+
try {
|
|
968
|
+
const db = (0, db_1.createPrisma)(env);
|
|
969
|
+
const roleMetadata = await db.roleMetadata.findMany({
|
|
970
|
+
where: { isActive: true },
|
|
971
|
+
orderBy: { role: "asc" },
|
|
972
|
+
});
|
|
973
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({ roles: roleMetadata }), { status: 200, headers: { "content-type": "application/json" } });
|
|
974
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
975
|
+
}
|
|
976
|
+
catch (error) {
|
|
977
|
+
logger.error("Error fetching role metadata:", error);
|
|
978
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to fetch role metadata" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
979
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
980
|
+
}
|
|
981
|
+
},
|
|
982
|
+
middleware: [(0, middleware_1.corsMiddleware)()],
|
|
983
|
+
description: "Get role metadata",
|
|
984
|
+
},
|
|
985
|
+
// Domain Management Endpoints
|
|
986
|
+
{
|
|
987
|
+
path: "/api/admin/domains",
|
|
988
|
+
method: "GET",
|
|
989
|
+
handler: async (request, env, { url, requestContext }) => {
|
|
990
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
991
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
992
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
993
|
+
// Check authentication and authorization
|
|
994
|
+
const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
|
|
995
|
+
if (!session) {
|
|
996
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
997
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
998
|
+
}
|
|
999
|
+
// Check if user is admin
|
|
1000
|
+
const region = requestContext?.region || env.DEFAULT_REGION || "EU";
|
|
1001
|
+
const db = data_router_1.DataRouter.getDatabaseForRegion(region, env);
|
|
1002
|
+
const user = await db.user.findUnique({
|
|
1003
|
+
where: { id: session.userId },
|
|
1004
|
+
select: { role: true },
|
|
1005
|
+
});
|
|
1006
|
+
if (!user || (user.role !== "SUPER_ADMIN" && user.role !== "INTERNAL")) {
|
|
1007
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
1008
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1009
|
+
}
|
|
1010
|
+
try {
|
|
1011
|
+
// Parse query parameters
|
|
1012
|
+
const queryParams = new URL(url).searchParams;
|
|
1013
|
+
const limit = Math.min(parseInt(queryParams.get("limit") || "50", 10), 100);
|
|
1014
|
+
const cursor = queryParams.get("cursor") || undefined;
|
|
1015
|
+
const status = queryParams.get("status") || undefined;
|
|
1016
|
+
const domainFilter = queryParams.get("domain") || undefined;
|
|
1017
|
+
const sortBy = queryParams.get("sortBy") || "createdAt";
|
|
1018
|
+
const sortOrder = queryParams.get("sortOrder") || "desc";
|
|
1019
|
+
// Build query
|
|
1020
|
+
const where = {};
|
|
1021
|
+
if (cursor) {
|
|
1022
|
+
where.id = { gt: cursor };
|
|
1023
|
+
}
|
|
1024
|
+
if (status) {
|
|
1025
|
+
where.status = status;
|
|
1026
|
+
}
|
|
1027
|
+
if (domainFilter) {
|
|
1028
|
+
where.domain = { contains: domainFilter, mode: "insensitive" };
|
|
1029
|
+
}
|
|
1030
|
+
// Build orderBy
|
|
1031
|
+
const orderBy = {};
|
|
1032
|
+
if (sortBy === "createdAt" ||
|
|
1033
|
+
sortBy === "domain" ||
|
|
1034
|
+
sortBy === "reputation" ||
|
|
1035
|
+
sortBy === "status") {
|
|
1036
|
+
orderBy[sortBy] = sortOrder === "asc" ? "asc" : "desc";
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
orderBy.createdAt = "desc"; // Default
|
|
1040
|
+
}
|
|
1041
|
+
// Get domains with pagination
|
|
1042
|
+
const domains = await db.domainReputation.findMany({
|
|
1043
|
+
where,
|
|
1044
|
+
take: limit + 1,
|
|
1045
|
+
orderBy,
|
|
1046
|
+
});
|
|
1047
|
+
const hasMore = domains.length > limit;
|
|
1048
|
+
const result = hasMore ? domains.slice(0, limit) : domains;
|
|
1049
|
+
const nextCursor = hasMore ? result[result.length - 1].id : undefined;
|
|
1050
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1051
|
+
domains: result.map((d) => ({
|
|
1052
|
+
id: d.id,
|
|
1053
|
+
domain: d.domain,
|
|
1054
|
+
reputation: d.reputation,
|
|
1055
|
+
status: d.status,
|
|
1056
|
+
lastChecked: d.lastChecked.toISOString(),
|
|
1057
|
+
createdAt: d.createdAt.toISOString(),
|
|
1058
|
+
updatedAt: d.updatedAt.toISOString(),
|
|
1059
|
+
})),
|
|
1060
|
+
hasMore,
|
|
1061
|
+
nextCursor,
|
|
1062
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1063
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
1064
|
+
}
|
|
1065
|
+
catch (error) {
|
|
1066
|
+
logger.error("[Admin] Error fetching domains:", error);
|
|
1067
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to fetch domains" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
1068
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1069
|
+
}
|
|
1070
|
+
},
|
|
1071
|
+
middleware: [(0, middleware_1.corsMiddleware)()],
|
|
1072
|
+
description: "List domains with reputation",
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
path: /^\/api\/admin\/domains\/([^/]+)\/block$/,
|
|
1076
|
+
method: "POST",
|
|
1077
|
+
handler: async (request, env, { pathname, requestContext }) => {
|
|
1078
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
1079
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
1080
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
1081
|
+
// Check authentication and authorization
|
|
1082
|
+
const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
|
|
1083
|
+
if (!session) {
|
|
1084
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
1085
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1086
|
+
}
|
|
1087
|
+
// Check if user is admin
|
|
1088
|
+
const region = requestContext?.region || env.DEFAULT_REGION || "EU";
|
|
1089
|
+
const db = data_router_1.DataRouter.getDatabaseForRegion(region, env);
|
|
1090
|
+
const user = await db.user.findUnique({
|
|
1091
|
+
where: { id: session.userId },
|
|
1092
|
+
select: { role: true },
|
|
1093
|
+
});
|
|
1094
|
+
if (!user || (user.role !== "SUPER_ADMIN" && user.role !== "INTERNAL")) {
|
|
1095
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
1096
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1097
|
+
}
|
|
1098
|
+
try {
|
|
1099
|
+
// Extract domain from path
|
|
1100
|
+
const match = pathname.match(/^\/api\/admin\/domains\/([^/]+)\/block$/);
|
|
1101
|
+
if (!match) {
|
|
1102
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Invalid URL format" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
1103
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1104
|
+
}
|
|
1105
|
+
const domain = decodeURIComponent(match[1]);
|
|
1106
|
+
// Block domain
|
|
1107
|
+
const reputationService = new domain_reputation_service_1.DomainReputationService(env);
|
|
1108
|
+
await reputationService.blockDomain(domain, region, env);
|
|
1109
|
+
logger.info(`[Admin] Domain blocked: ${domain} by user ${session.userId}`);
|
|
1110
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1111
|
+
success: true,
|
|
1112
|
+
message: `Domain ${domain} has been blocked`,
|
|
1113
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1114
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
1115
|
+
}
|
|
1116
|
+
catch (error) {
|
|
1117
|
+
logger.error("[Admin] Error blocking domain:", error);
|
|
1118
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to block domain" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
1119
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
|
|
1123
|
+
description: "Block a domain",
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
path: /^\/api\/admin\/domains\/([^/]+)\/unblock$/,
|
|
1127
|
+
method: "POST",
|
|
1128
|
+
handler: async (request, env, { pathname, requestContext }) => {
|
|
1129
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
1130
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
1131
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
1132
|
+
// Check authentication and authorization
|
|
1133
|
+
const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
|
|
1134
|
+
if (!session) {
|
|
1135
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
1136
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1137
|
+
}
|
|
1138
|
+
// Check if user is admin
|
|
1139
|
+
const region = requestContext?.region || env.DEFAULT_REGION || "EU";
|
|
1140
|
+
const db = data_router_1.DataRouter.getDatabaseForRegion(region, env);
|
|
1141
|
+
const user = await db.user.findUnique({
|
|
1142
|
+
where: { id: session.userId },
|
|
1143
|
+
select: { role: true },
|
|
1144
|
+
});
|
|
1145
|
+
if (!user || (user.role !== "SUPER_ADMIN" && user.role !== "INTERNAL")) {
|
|
1146
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
1147
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1148
|
+
}
|
|
1149
|
+
try {
|
|
1150
|
+
// Extract domain from path
|
|
1151
|
+
const match = pathname.match(/^\/api\/admin\/domains\/([^/]+)\/unblock$/);
|
|
1152
|
+
if (!match) {
|
|
1153
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Invalid URL format" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
1154
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1155
|
+
}
|
|
1156
|
+
const domain = decodeURIComponent(match[1]);
|
|
1157
|
+
// Unblock domain
|
|
1158
|
+
const reputationService = new domain_reputation_service_1.DomainReputationService(env);
|
|
1159
|
+
await reputationService.unblockDomain(domain, region, env);
|
|
1160
|
+
logger.info(`[Admin] Domain unblocked: ${domain} by user ${session.userId}`);
|
|
1161
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1162
|
+
success: true,
|
|
1163
|
+
message: `Domain ${domain} has been unblocked`,
|
|
1164
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1165
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
1166
|
+
}
|
|
1167
|
+
catch (error) {
|
|
1168
|
+
logger.error("[Admin] Error unblocking domain:", error);
|
|
1169
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to unblock domain" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
1170
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1171
|
+
}
|
|
1172
|
+
},
|
|
1173
|
+
middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
|
|
1174
|
+
description: "Unblock a domain",
|
|
1175
|
+
},
|
|
1176
|
+
{
|
|
1177
|
+
path: "/api/admin/reports",
|
|
1178
|
+
method: "GET",
|
|
1179
|
+
handler: async (request, env, { url, requestContext }) => {
|
|
1180
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
1181
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
1182
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
1183
|
+
// Check authentication and authorization
|
|
1184
|
+
const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
|
|
1185
|
+
if (!session) {
|
|
1186
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
1187
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1188
|
+
}
|
|
1189
|
+
// Check if user is admin
|
|
1190
|
+
const region = requestContext?.region || env.DEFAULT_REGION || "EU";
|
|
1191
|
+
const db = data_router_1.DataRouter.getDatabaseForRegion(region, env);
|
|
1192
|
+
const user = await db.user.findUnique({
|
|
1193
|
+
where: { id: session.userId },
|
|
1194
|
+
select: { role: true },
|
|
1195
|
+
});
|
|
1196
|
+
if (!user || (user.role !== "SUPER_ADMIN" && user.role !== "INTERNAL")) {
|
|
1197
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
1198
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1199
|
+
}
|
|
1200
|
+
try {
|
|
1201
|
+
// Parse query parameters
|
|
1202
|
+
const queryParams = new URL(url).searchParams;
|
|
1203
|
+
const limit = Math.min(parseInt(queryParams.get("limit") || "50", 10), 100);
|
|
1204
|
+
const cursor = queryParams.get("cursor") || undefined;
|
|
1205
|
+
const status = queryParams.get("status") || undefined;
|
|
1206
|
+
const domain = queryParams.get("domain") || undefined;
|
|
1207
|
+
const sortBy = queryParams.get("sortBy") || "createdAt";
|
|
1208
|
+
const sortOrder = queryParams.get("sortOrder") || "desc";
|
|
1209
|
+
// Build query
|
|
1210
|
+
const where = {};
|
|
1211
|
+
if (cursor) {
|
|
1212
|
+
where.id = { gt: cursor };
|
|
1213
|
+
}
|
|
1214
|
+
if (status) {
|
|
1215
|
+
where.status = status;
|
|
1216
|
+
}
|
|
1217
|
+
if (domain) {
|
|
1218
|
+
where.domain = { contains: domain, mode: "insensitive" };
|
|
1219
|
+
}
|
|
1220
|
+
// Build orderBy
|
|
1221
|
+
const orderBy = {};
|
|
1222
|
+
if (sortBy === "createdAt" ||
|
|
1223
|
+
sortBy === "domain" ||
|
|
1224
|
+
sortBy === "status") {
|
|
1225
|
+
orderBy[sortBy] = sortOrder === "asc" ? "asc" : "desc";
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
orderBy.createdAt = "desc"; // Default
|
|
1229
|
+
}
|
|
1230
|
+
// Get reports with pagination
|
|
1231
|
+
const reports = await db.linkReport.findMany({
|
|
1232
|
+
where,
|
|
1233
|
+
take: limit + 1,
|
|
1234
|
+
orderBy,
|
|
1235
|
+
include: {
|
|
1236
|
+
user: {
|
|
1237
|
+
select: {
|
|
1238
|
+
id: true,
|
|
1239
|
+
email: true,
|
|
1240
|
+
},
|
|
1241
|
+
},
|
|
1242
|
+
},
|
|
1243
|
+
});
|
|
1244
|
+
const hasMore = reports.length > limit;
|
|
1245
|
+
const result = hasMore ? reports.slice(0, limit) : reports;
|
|
1246
|
+
const nextCursor = hasMore ? result[result.length - 1].id : undefined;
|
|
1247
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1248
|
+
reports: result.map((r) => ({
|
|
1249
|
+
id: r.id,
|
|
1250
|
+
userId: r.userId,
|
|
1251
|
+
userEmail: r.user.email,
|
|
1252
|
+
linkUrl: r.linkUrl,
|
|
1253
|
+
domain: r.domain,
|
|
1254
|
+
reason: r.reason,
|
|
1255
|
+
status: r.status,
|
|
1256
|
+
createdAt: r.createdAt.toISOString(),
|
|
1257
|
+
})),
|
|
1258
|
+
hasMore,
|
|
1259
|
+
nextCursor,
|
|
1260
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1261
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
1262
|
+
}
|
|
1263
|
+
catch (error) {
|
|
1264
|
+
logger.error("[Admin] Error fetching reports:", error);
|
|
1265
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to fetch reports" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
1266
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
middleware: [(0, middleware_1.corsMiddleware)()],
|
|
1270
|
+
description: "List link reports",
|
|
1271
|
+
},
|
|
1272
|
+
{
|
|
1273
|
+
path: /^\/api\/admin\/reports\/([^/]+)\/review$/,
|
|
1274
|
+
method: "POST",
|
|
1275
|
+
handler: async (request, env, { pathname, requestContext }) => {
|
|
1276
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
1277
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
1278
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
1279
|
+
// Check authentication and authorization
|
|
1280
|
+
const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
|
|
1281
|
+
if (!session) {
|
|
1282
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
1283
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1284
|
+
}
|
|
1285
|
+
// Check if user is admin
|
|
1286
|
+
const region = requestContext?.region || env.DEFAULT_REGION || "EU";
|
|
1287
|
+
const db = data_router_1.DataRouter.getDatabaseForRegion(region, env);
|
|
1288
|
+
const user = await db.user.findUnique({
|
|
1289
|
+
where: { id: session.userId },
|
|
1290
|
+
select: { role: true },
|
|
1291
|
+
});
|
|
1292
|
+
if (!user || (user.role !== "SUPER_ADMIN" && user.role !== "INTERNAL")) {
|
|
1293
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
1294
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1295
|
+
}
|
|
1296
|
+
try {
|
|
1297
|
+
// Extract reportId from path
|
|
1298
|
+
const match = pathname.match(/^\/api\/admin\/reports\/([^/]+)\/review$/);
|
|
1299
|
+
if (!match) {
|
|
1300
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Invalid URL format" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
1301
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1302
|
+
}
|
|
1303
|
+
const reportId = match[1];
|
|
1304
|
+
// Parse request body
|
|
1305
|
+
const body = (await request.json().catch(() => ({})));
|
|
1306
|
+
if (!body.action ||
|
|
1307
|
+
!["approve", "reject", "dismiss"].includes(body.action)) {
|
|
1308
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1309
|
+
error: "Invalid action. Must be approve, reject, or dismiss",
|
|
1310
|
+
}), { status: 400, headers: { "content-type": "application/json" } });
|
|
1311
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1312
|
+
}
|
|
1313
|
+
// Get report
|
|
1314
|
+
const report = await db.linkReport.findUnique({
|
|
1315
|
+
where: { id: reportId },
|
|
1316
|
+
});
|
|
1317
|
+
if (!report) {
|
|
1318
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Report not found" }), { status: 404, headers: { "content-type": "application/json" } });
|
|
1319
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1320
|
+
}
|
|
1321
|
+
// Update report status
|
|
1322
|
+
let newStatus;
|
|
1323
|
+
if (body.action === "approve") {
|
|
1324
|
+
newStatus = "approved";
|
|
1325
|
+
// If approved, update domain reputation (negative signal)
|
|
1326
|
+
const reputationService = new domain_reputation_service_1.DomainReputationService(env);
|
|
1327
|
+
await reputationService.updateReputation(report.domain, "user_report", region, env);
|
|
1328
|
+
}
|
|
1329
|
+
else if (body.action === "reject") {
|
|
1330
|
+
newStatus = "rejected";
|
|
1331
|
+
}
|
|
1332
|
+
else {
|
|
1333
|
+
newStatus = "dismissed";
|
|
1334
|
+
}
|
|
1335
|
+
const updatedReport = await db.linkReport.update({
|
|
1336
|
+
where: { id: reportId },
|
|
1337
|
+
data: {
|
|
1338
|
+
status: newStatus,
|
|
1339
|
+
},
|
|
1340
|
+
});
|
|
1341
|
+
logger.info(`[Admin] Report ${reportId} reviewed: ${body.action} by user ${session.userId}`);
|
|
1342
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1343
|
+
success: true,
|
|
1344
|
+
report: {
|
|
1345
|
+
id: updatedReport.id,
|
|
1346
|
+
status: updatedReport.status,
|
|
1347
|
+
},
|
|
1348
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1349
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
1350
|
+
}
|
|
1351
|
+
catch (error) {
|
|
1352
|
+
logger.error("[Admin] Error reviewing report:", error);
|
|
1353
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to review report" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
1354
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1355
|
+
}
|
|
1356
|
+
},
|
|
1357
|
+
middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
|
|
1358
|
+
description: "Review a link report",
|
|
1359
|
+
},
|
|
1360
|
+
{
|
|
1361
|
+
path: "/api/admin/domains/bulk",
|
|
1362
|
+
method: "POST",
|
|
1363
|
+
handler: async (request, env, { requestContext }) => {
|
|
1364
|
+
const sessionManager = new session_manager_1.SessionManager();
|
|
1365
|
+
const securityHeaders = new security_headers_1.SecurityHeaders(env);
|
|
1366
|
+
const logger = logger_1.Logger.getInstance(env);
|
|
1367
|
+
// Check authentication and authorization
|
|
1368
|
+
const session = await sessionManager.getSession(request, secret_resolver_1.Secrets.getSessionSecret(env), env);
|
|
1369
|
+
if (!session) {
|
|
1370
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { "content-type": "application/json" } });
|
|
1371
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1372
|
+
}
|
|
1373
|
+
// Check if user is admin
|
|
1374
|
+
const region = requestContext?.region || env.DEFAULT_REGION || "EU";
|
|
1375
|
+
const db = data_router_1.DataRouter.getDatabaseForRegion(region, env);
|
|
1376
|
+
const user = await db.user.findUnique({
|
|
1377
|
+
where: { id: session.userId },
|
|
1378
|
+
select: { role: true },
|
|
1379
|
+
});
|
|
1380
|
+
if (!user || (user.role !== "SUPER_ADMIN" && user.role !== "INTERNAL")) {
|
|
1381
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Forbidden: Admin access required" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
1382
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1383
|
+
}
|
|
1384
|
+
try {
|
|
1385
|
+
// Parse request body
|
|
1386
|
+
const body = (await request.json());
|
|
1387
|
+
if (!body.action ||
|
|
1388
|
+
!["block", "unblock", "allowlist"].includes(body.action)) {
|
|
1389
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1390
|
+
error: "Invalid action. Must be block, unblock, or allowlist",
|
|
1391
|
+
}), { status: 400, headers: { "content-type": "application/json" } });
|
|
1392
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1393
|
+
}
|
|
1394
|
+
if (!Array.isArray(body.domains) || body.domains.length === 0) {
|
|
1395
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "domains must be a non-empty array" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
1396
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1397
|
+
}
|
|
1398
|
+
// Limit bulk operations to prevent abuse
|
|
1399
|
+
if (body.domains.length > 100) {
|
|
1400
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Maximum 100 domains per bulk operation" }), { status: 400, headers: { "content-type": "application/json" } });
|
|
1401
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1402
|
+
}
|
|
1403
|
+
const reputationService = new domain_reputation_service_1.DomainReputationService(env);
|
|
1404
|
+
const results = [];
|
|
1405
|
+
// Process each domain
|
|
1406
|
+
for (const domain of body.domains) {
|
|
1407
|
+
try {
|
|
1408
|
+
if (body.action === "block") {
|
|
1409
|
+
await reputationService.blockDomain(domain, region, env);
|
|
1410
|
+
}
|
|
1411
|
+
else if (body.action === "unblock") {
|
|
1412
|
+
await reputationService.unblockDomain(domain, region, env);
|
|
1413
|
+
}
|
|
1414
|
+
else {
|
|
1415
|
+
await reputationService.addToAllowlist(domain, region, env);
|
|
1416
|
+
}
|
|
1417
|
+
results.push({ domain, success: true });
|
|
1418
|
+
}
|
|
1419
|
+
catch (error) {
|
|
1420
|
+
logger.warn(`[Admin] Failed to ${body.action} domain ${domain}:`, error);
|
|
1421
|
+
results.push({
|
|
1422
|
+
domain,
|
|
1423
|
+
success: false,
|
|
1424
|
+
error: error.message || "Unknown error",
|
|
1425
|
+
});
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
const successCount = results.filter((r) => r.success).length;
|
|
1429
|
+
logger.info(`[Admin] Bulk ${body.action} operation: ${successCount}/${body.domains.length} successful`);
|
|
1430
|
+
const response = securityHeaders.createSecureResponse(JSON.stringify({
|
|
1431
|
+
success: true,
|
|
1432
|
+
action: body.action,
|
|
1433
|
+
total: body.domains.length,
|
|
1434
|
+
successful: successCount,
|
|
1435
|
+
failed: body.domains.length - successCount,
|
|
1436
|
+
results,
|
|
1437
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1438
|
+
return (0, worker_1.addCorsHeaders)(response, request, env);
|
|
1439
|
+
}
|
|
1440
|
+
catch (error) {
|
|
1441
|
+
logger.error("[Admin] Error performing bulk operation:", error);
|
|
1442
|
+
const errorResponse = securityHeaders.createSecureResponse(JSON.stringify({ error: "Failed to perform bulk operation" }), { status: 500, headers: { "content-type": "application/json" } });
|
|
1443
|
+
return (0, worker_1.addCorsHeaders)(errorResponse, request, env);
|
|
1444
|
+
}
|
|
1445
|
+
},
|
|
1446
|
+
middleware: [(0, middleware_1.corsMiddleware)(), (0, middleware_1.csrfMiddleware)()],
|
|
1447
|
+
description: "Bulk domain operations (block/unblock/allowlist)",
|
|
1448
|
+
},
|
|
1449
|
+
];
|
|
1450
|
+
//# sourceMappingURL=admin.js.map
|