@omega.js/backend 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +98 -0
- package/README.md +1053 -0
- package/bin/omega +2 -0
- package/bin/omega-backend +2 -0
- package/bin/omg +2 -0
- package/cli.js +3 -0
- package/dist/cli/command-table.js +268 -0
- package/dist/cli/commands/auth.js +259 -0
- package/dist/cli/commands/base-command.js +451 -0
- package/dist/cli/commands/build.js +27 -0
- package/dist/cli/commands/clean.js +13 -0
- package/dist/cli/commands/clear.js +11 -0
- package/dist/cli/commands/cwd.js +9 -0
- package/dist/cli/commands/deploy.js +205 -0
- package/dist/cli/commands/emulator-orphans.js +440 -0
- package/dist/cli/commands/emulator.js +1829 -0
- package/dist/cli/commands/firebase-init.js +101 -0
- package/dist/cli/commands/firestore.js +261 -0
- package/dist/cli/commands/indexes.js +51 -0
- package/dist/cli/commands/install.js +151 -0
- package/dist/cli/commands/logs.js +358 -0
- package/dist/cli/commands/mcp.js +41 -0
- package/dist/cli/commands/migrate-markers.js +176 -0
- package/dist/cli/commands/migrate-rules.js +90 -0
- package/dist/cli/commands/migrate.js +59 -0
- package/dist/cli/commands/serve.js +208 -0
- package/dist/cli/commands/setup-tests/base-test.js +174 -0
- package/dist/cli/commands/setup-tests/emulator-config.js +109 -0
- package/dist/cli/commands/setup-tests/env-runtime-config-deprecated.js +47 -0
- package/dist/cli/commands/setup-tests/firebase-admin.js +49 -0
- package/dist/cli/commands/setup-tests/firebase-auth.js +26 -0
- package/dist/cli/commands/setup-tests/firebase-cli.js +26 -0
- package/dist/cli/commands/setup-tests/firebase-functions.js +49 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-file.js +72 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-in-json.js +20 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-required.js +108 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-synced.js +236 -0
- package/dist/cli/commands/setup-tests/firestore-rules-file.js +115 -0
- package/dist/cli/commands/setup-tests/firestore-rules-in-json.js +49 -0
- package/dist/cli/commands/setup-tests/functions-package.js +44 -0
- package/dist/cli/commands/setup-tests/gcloud-cli.js +26 -0
- package/dist/cli/commands/setup-tests/gitignore.js +122 -0
- package/dist/cli/commands/setup-tests/helpers/merge-line-files.js +28 -0
- package/dist/cli/commands/setup-tests/helpers/required-indexes.js +109 -0
- package/dist/cli/commands/setup-tests/helpers/seed-campaigns.js +246 -0
- package/dist/cli/commands/setup-tests/helpers.js +72 -0
- package/dist/cli/commands/setup-tests/hosting-folder.js +23 -0
- package/dist/cli/commands/setup-tests/hosting-rewrites.js +52 -0
- package/dist/cli/commands/setup-tests/index.js +111 -0
- package/dist/cli/commands/setup-tests/is-firebase-project.js +21 -0
- package/dist/cli/commands/setup-tests/java-installed.js +27 -0
- package/dist/cli/commands/setup-tests/legacy-tests-cleanup.js +43 -0
- package/dist/cli/commands/setup-tests/marketing-campaigns-seeded.js +230 -0
- package/dist/cli/commands/setup-tests/node-version.js +60 -0
- package/dist/cli/commands/setup-tests/npm-project-scripts.js +42 -0
- package/dist/cli/commands/setup-tests/nvmrc-version.js +36 -0
- package/dist/cli/commands/setup-tests/omega-backend.js +42 -0
- package/dist/cli/commands/setup-tests/omega-config.js +84 -0
- package/dist/cli/commands/setup-tests/project-directories.js +34 -0
- package/dist/cli/commands/setup-tests/project-id-consistency.js +201 -0
- package/dist/cli/commands/setup-tests/public-html-files.js +22 -0
- package/dist/cli/commands/setup-tests/realtime-rules-file.js +69 -0
- package/dist/cli/commands/setup-tests/realtime-rules-in-json.js +20 -0
- package/dist/cli/commands/setup-tests/remoteconfig-template-file.js +32 -0
- package/dist/cli/commands/setup-tests/remoteconfig-template-in-json.js +31 -0
- package/dist/cli/commands/setup-tests/service-account.js +86 -0
- package/dist/cli/commands/setup-tests/storage-lifecycle-policy.js +81 -0
- package/dist/cli/commands/setup-tests/storage-rules-file.js +32 -0
- package/dist/cli/commands/setup-tests/storage-rules-in-json.js +20 -0
- package/dist/cli/commands/stripe.js +14 -0
- package/dist/cli/commands/test-lanes/stripe-live.js +440 -0
- package/dist/cli/commands/test.js +976 -0
- package/dist/cli/commands/update.js +27 -0
- package/dist/cli/commands/version.js +10 -0
- package/dist/cli/commands/watch.js +196 -0
- package/dist/cli/flags.js +13 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/run.js +33 -0
- package/dist/cli/utils/attach-log-file.js +4 -0
- package/dist/cli/utils/compile-rules.js +1155 -0
- package/dist/cli/utils/ensure-target.js +314 -0
- package/dist/cli/utils/project-type.js +140 -0
- package/dist/cli/utils/public-files.js +49 -0
- package/dist/cli/utils/safe-install.js +4 -0
- package/dist/cli/utils/spawn-shell.js +94 -0
- package/dist/cli/utils/stage-functions.js +338 -0
- package/dist/cli/utils/stage-local-packages.js +210 -0
- package/dist/cli/utils/target-checks.js +161 -0
- package/dist/cli/utils/target.js +24 -0
- package/dist/cli/utils/ui.js +292 -0
- package/dist/defaults/AGENTS.md +125 -0
- package/dist/defaults/CHANGELOG.md +15 -0
- package/dist/defaults/CLAUDE.md +1 -0
- package/dist/defaults/_.gitignore +65 -0
- package/dist/defaults/docs/README.md +17 -0
- package/dist/defaults/test/README.md +65 -0
- package/dist/defaults/test/_init.js +14 -0
- package/dist/defaults/test/helpers/connect-trap.js +72 -0
- package/dist/defaults/test/unit/registration.test.js +143 -0
- package/dist/defaults/test/unit/rules-posture.test.js +101 -0
- package/dist/defaults/test/unit/socket-free.test.js +43 -0
- package/dist/manager/events/auth/before-create.js +89 -0
- package/dist/manager/events/auth/before-signin.js +76 -0
- package/dist/manager/events/auth/on-create.js +112 -0
- package/dist/manager/events/auth/on-delete.js +141 -0
- package/dist/manager/events/auth/utils.js +93 -0
- package/dist/manager/events/cron/daily/blog-auto-publisher.js +287 -0
- package/dist/manager/events/cron/daily/data-requests.js +57 -0
- package/dist/manager/events/cron/daily/expire-paypal-cancellations.js +191 -0
- package/dist/manager/events/cron/daily/marketing-prune.js +486 -0
- package/dist/manager/events/cron/daily/reset-usage.js +188 -0
- package/dist/manager/events/cron/daily/trial-lapse-sweep.js +355 -0
- package/dist/manager/events/cron/daily.js +3 -0
- package/dist/manager/events/cron/frequent/abandoned-carts.js +204 -0
- package/dist/manager/events/cron/frequent/email-queue.js +71 -0
- package/dist/manager/events/cron/frequent/marketing-campaigns.js +463 -0
- package/dist/manager/events/cron/frequent/retry-failed-webhooks.js +70 -0
- package/dist/manager/events/cron/frequent.js +3 -0
- package/dist/manager/events/cron/runner.js +64 -0
- package/dist/manager/events/firestore/notifications/on-write.js +123 -0
- package/dist/manager/events/firestore/payments-disputes/on-write.js +256 -0
- package/dist/manager/events/firestore/payments-disputes/providers/stripe.js +218 -0
- package/dist/manager/events/firestore/payments-disputes/providers/test.js +231 -0
- package/dist/manager/events/firestore/payments-webhooks/analytics.js +687 -0
- package/dist/manager/events/firestore/payments-webhooks/on-write.js +1224 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/index.js +395 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-completed.js +58 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-failed.js +28 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-refunded.js +30 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/send-email.js +74 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/cancellation-removed.js +14 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/cancellation-requested.js +28 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/checkout-declined.js +18 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/new-subscription.js +67 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-failed.js +25 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-recovered.js +26 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-refunded.js +34 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/plan-changed.js +42 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/subscription-cancelled.js +33 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/subscription-winback.js +17 -0
- package/dist/manager/functions/_legacy/actions/create-post-handler.js +188 -0
- package/dist/manager/functions/_legacy/actions/generate-uuid.js +63 -0
- package/dist/manager/functions/_legacy/actions/sign-up-handler.js +205 -0
- package/dist/manager/functions/_legacy/admin/create-post.js +207 -0
- package/dist/manager/functions/_legacy/admin/firestore-write.js +72 -0
- package/dist/manager/functions/_legacy/admin/get-stats.js +218 -0
- package/dist/manager/functions/_legacy/admin/query.js +198 -0
- package/dist/manager/functions/_legacy/admin/send-notification.js +206 -0
- package/dist/manager/functions/_legacy/template.js +33 -0
- package/dist/manager/functions/_legacy/test/authenticate.js +40 -0
- package/dist/manager/functions/_legacy/test/webhook.js +37 -0
- package/dist/manager/functions/wrappers/mailchimp/addToList.js +25 -0
- package/dist/manager/helpers/analytics.js +498 -0
- package/dist/manager/helpers/api-manager.js +313 -0
- package/dist/manager/helpers/backend-router.js +37 -0
- package/dist/manager/helpers/context/authenticate.js +215 -0
- package/dist/manager/helpers/context/client-info.js +91 -0
- package/dist/manager/helpers/context/index.js +228 -0
- package/dist/manager/helpers/context/logging.js +150 -0
- package/dist/manager/helpers/context/parse.js +160 -0
- package/dist/manager/helpers/context/respond.js +247 -0
- package/dist/manager/helpers/event-middleware.js +109 -0
- package/dist/manager/helpers/metadata.js +32 -0
- package/dist/manager/helpers/middleware.js +541 -0
- package/dist/manager/helpers/redact-secret.js +25 -0
- package/dist/manager/helpers/resolved-config.js +34 -0
- package/dist/manager/helpers/roles.js +69 -0
- package/dist/manager/helpers/safe-compare.js +31 -0
- package/dist/manager/helpers/schema-engine.js +314 -0
- package/dist/manager/helpers/schema-zod.js +203 -0
- package/dist/manager/helpers/settings.js +215 -0
- package/dist/manager/helpers/usage.js +541 -0
- package/dist/manager/helpers/user.js +57 -0
- package/dist/manager/helpers/utilities.js +565 -0
- package/dist/manager/index.js +1404 -0
- package/dist/manager/libraries/abandoned-cart-config.js +12 -0
- package/dist/manager/libraries/ai/index.js +321 -0
- package/dist/manager/libraries/ai/prompt.js +85 -0
- package/dist/manager/libraries/ai/providers/anthropic-format.js +297 -0
- package/dist/manager/libraries/ai/providers/anthropic.js +169 -0
- package/dist/manager/libraries/ai/providers/claude-code.js +183 -0
- package/dist/manager/libraries/ai/providers/openai.js +1272 -0
- package/dist/manager/libraries/ai/providers/test.js +257 -0
- package/dist/manager/libraries/ai/tokens.js +54 -0
- package/dist/manager/libraries/analytics/conversions.js +478 -0
- package/dist/manager/libraries/analytics/match-data.js +573 -0
- package/dist/manager/libraries/analytics/signup.js +120 -0
- package/dist/manager/libraries/auth-user.js +46 -0
- package/dist/manager/libraries/content/feed-parser.js +198 -0
- package/dist/manager/libraries/content/ghostii.js +191 -0
- package/dist/manager/libraries/content/source-resolver.js +629 -0
- package/dist/manager/libraries/email/constants.js +532 -0
- package/dist/manager/libraries/email/data/blocked-local-parts.json +55 -0
- package/dist/manager/libraries/email/data/blocked-local-patterns.js +14 -0
- package/dist/manager/libraries/email/data/corporate-domains.json +23 -0
- package/dist/manager/libraries/email/data/custom-disposable-domains.json +58 -0
- package/dist/manager/libraries/email/data/disposable-domains.json +8184 -0
- package/dist/manager/libraries/email/data/typo-domains.js +83 -0
- package/dist/manager/libraries/email/disposable-domains.js +92 -0
- package/dist/manager/libraries/email/generators/lib/filter.js +179 -0
- package/dist/manager/libraries/email/generators/lib/image-host.js +344 -0
- package/dist/manager/libraries/email/generators/lib/image-illustrator.js +154 -0
- package/dist/manager/libraries/email/generators/lib/markdown-renderer.js +294 -0
- package/dist/manager/libraries/email/generators/lib/mjml-template.js +120 -0
- package/dist/manager/libraries/email/generators/lib/structure.js +299 -0
- package/dist/manager/libraries/email/generators/lib/svg-illustrator.js +197 -0
- package/dist/manager/libraries/email/generators/lib/templates/base.js +229 -0
- package/dist/manager/libraries/email/generators/lib/templates/card.js +33 -0
- package/dist/manager/libraries/email/generators/lib/templates/classic-schema.js +59 -0
- package/dist/manager/libraries/email/generators/lib/templates/clean.js +82 -0
- package/dist/manager/libraries/email/generators/lib/templates/editorial/helpers.js +100 -0
- package/dist/manager/libraries/email/generators/lib/templates/editorial/index.js +318 -0
- package/dist/manager/libraries/email/generators/lib/templates/feedback.js +101 -0
- package/dist/manager/libraries/email/generators/lib/templates/field-report/helpers.js +138 -0
- package/dist/manager/libraries/email/generators/lib/templates/field-report/index.js +494 -0
- package/dist/manager/libraries/email/generators/lib/templates/index.js +47 -0
- package/dist/manager/libraries/email/generators/lib/templates/newsletter-shared.js +610 -0
- package/dist/manager/libraries/email/generators/lib/templates/order.js +461 -0
- package/dist/manager/libraries/email/generators/lib/templates/plain.js +83 -0
- package/dist/manager/libraries/email/generators/lib/templates/shared-campaign.js +64 -0
- package/dist/manager/libraries/email/generators/newsletter.js +899 -0
- package/dist/manager/libraries/email/index.js +146 -0
- package/dist/manager/libraries/email/marketing/index.js +754 -0
- package/dist/manager/libraries/email/prepare.js +365 -0
- package/dist/manager/libraries/email/providers/beehiiv.js +589 -0
- package/dist/manager/libraries/email/providers/sendgrid.js +845 -0
- package/dist/manager/libraries/email/transactional/index.js +510 -0
- package/dist/manager/libraries/email/utm.js +86 -0
- package/dist/manager/libraries/email/validation-provider-neverbounce.js +70 -0
- package/dist/manager/libraries/email/validation-provider-zerobounce.js +42 -0
- package/dist/manager/libraries/email/validation.js +255 -0
- package/dist/manager/libraries/env.js +198 -0
- package/dist/manager/libraries/infer-contact.js +101 -0
- package/dist/manager/libraries/load-provider.js +65 -0
- package/dist/manager/libraries/notification.js +256 -0
- package/dist/manager/libraries/openai.js +13 -0
- package/dist/manager/libraries/payment/discount-codes.js +204 -0
- package/dist/manager/libraries/payment/fetch-failure.js +56 -0
- package/dist/manager/libraries/payment/license.js +44 -0
- package/dist/manager/libraries/payment/order-id.js +57 -0
- package/dist/manager/libraries/payment/provider-errors.js +71 -0
- package/dist/manager/libraries/payment/providers/chargebee.js +817 -0
- package/dist/manager/libraries/payment/providers/coinbase.js +330 -0
- package/dist/manager/libraries/payment/providers/paypal.js +987 -0
- package/dist/manager/libraries/payment/providers/stripe.js +755 -0
- package/dist/manager/libraries/payment/providers/test.js +250 -0
- package/dist/manager/libraries/payment/refund-linkage.js +78 -0
- package/dist/manager/libraries/payment/refund-policy.js +113 -0
- package/dist/manager/libraries/payment/winback.js +55 -0
- package/dist/manager/libraries/prompts/infer-contact.md +78 -0
- package/dist/manager/libraries/rate-limits.js +17 -0
- package/dist/manager/libraries/recaptcha.js +58 -0
- package/dist/manager/libraries/user-doc.js +234 -0
- package/dist/manager/routes/admin/backup/post.js +106 -0
- package/dist/manager/routes/admin/cron/post.js +37 -0
- package/dist/manager/routes/admin/database/get.js +35 -0
- package/dist/manager/routes/admin/database/post.js +34 -0
- package/dist/manager/routes/admin/email/post.js +74 -0
- package/dist/manager/routes/admin/firestore/get.js +35 -0
- package/dist/manager/routes/admin/firestore/post.js +56 -0
- package/dist/manager/routes/admin/firestore/query/post.js +128 -0
- package/dist/manager/routes/admin/hook/post.js +104 -0
- package/dist/manager/routes/admin/infer-contact/post.js +35 -0
- package/dist/manager/routes/admin/notification/post.js +37 -0
- package/dist/manager/routes/admin/payment/post.js +56 -0
- package/dist/manager/routes/admin/post/deduplicate-image-alts.js +52 -0
- package/dist/manager/routes/admin/post/dispatch-deploy.js +36 -0
- package/dist/manager/routes/admin/post/post.js +487 -0
- package/dist/manager/routes/admin/post/put.js +146 -0
- package/dist/manager/routes/admin/post/templates/post.html +14 -0
- package/dist/manager/routes/admin/repo/content/post.js +106 -0
- package/dist/manager/routes/admin/stats/get.js +222 -0
- package/dist/manager/routes/admin/users/disable/post.js +50 -0
- package/dist/manager/routes/admin/users/list/get.js +110 -0
- package/dist/manager/routes/admin/users/sync/post.js +119 -0
- package/dist/manager/routes/brand/get.js +26 -0
- package/dist/manager/routes/content/post/get.js +110 -0
- package/dist/manager/routes/general/email/post.js +89 -0
- package/dist/manager/routes/general/email/templates/general/download-app-link.js +42 -0
- package/dist/manager/routes/general/uuid/post.js +31 -0
- package/dist/manager/routes/handler/post/post.js +142 -0
- package/dist/manager/routes/health/get.js +43 -0
- package/dist/manager/routes/index.js +11 -0
- package/dist/manager/routes/marketing/campaign/delete.js +45 -0
- package/dist/manager/routes/marketing/campaign/get.js +69 -0
- package/dist/manager/routes/marketing/campaign/post.js +124 -0
- package/dist/manager/routes/marketing/campaign/put.js +86 -0
- package/dist/manager/routes/marketing/campaign/utils.js +59 -0
- package/dist/manager/routes/marketing/contact/delete.js +100 -0
- package/dist/manager/routes/marketing/contact/post.js +149 -0
- package/dist/manager/routes/marketing/contact/put.js +37 -0
- package/dist/manager/routes/marketing/email-preferences/post.js +275 -0
- package/dist/manager/routes/marketing/webhook/forward/post.js +170 -0
- package/dist/manager/routes/marketing/webhook/post.js +123 -0
- package/dist/manager/routes/marketing/webhook/providers/beehiiv.js +197 -0
- package/dist/manager/routes/marketing/webhook/providers/sendgrid.js +194 -0
- package/dist/manager/routes/payments/cancel/_is-trialing.js +40 -0
- package/dist/manager/routes/payments/cancel/post.js +149 -0
- package/dist/manager/routes/payments/cancel/providers/chargebee.js +41 -0
- package/dist/manager/routes/payments/cancel/providers/paypal.js +56 -0
- package/dist/manager/routes/payments/cancel/providers/stripe.js +33 -0
- package/dist/manager/routes/payments/cancel/providers/test.js +118 -0
- package/dist/manager/routes/payments/discount/get.js +25 -0
- package/dist/manager/routes/payments/dispute-alert/post.js +117 -0
- package/dist/manager/routes/payments/dispute-alert/providers/chargeblast.js +55 -0
- package/dist/manager/routes/payments/intent/post.js +341 -0
- package/dist/manager/routes/payments/intent/providers/chargebee.js +197 -0
- package/dist/manager/routes/payments/intent/providers/coinbase.js +94 -0
- package/dist/manager/routes/payments/intent/providers/paypal.js +244 -0
- package/dist/manager/routes/payments/intent/providers/stripe.js +141 -0
- package/dist/manager/routes/payments/intent/providers/test.js +341 -0
- package/dist/manager/routes/payments/plan/post.js +147 -0
- package/dist/manager/routes/payments/plan/providers/chargebee.js +62 -0
- package/dist/manager/routes/payments/plan/providers/paypal.js +62 -0
- package/dist/manager/routes/payments/plan/providers/stripe.js +59 -0
- package/dist/manager/routes/payments/plan/providers/test.js +113 -0
- package/dist/manager/routes/payments/portal/post.js +113 -0
- package/dist/manager/routes/payments/portal/providers/chargebee.js +62 -0
- package/dist/manager/routes/payments/portal/providers/paypal.js +25 -0
- package/dist/manager/routes/payments/portal/providers/stripe.js +62 -0
- package/dist/manager/routes/payments/portal/providers/test.js +18 -0
- package/dist/manager/routes/payments/refund/post.js +207 -0
- package/dist/manager/routes/payments/refund/providers/chargebee.js +147 -0
- package/dist/manager/routes/payments/refund/providers/coinbase.js +40 -0
- package/dist/manager/routes/payments/refund/providers/paypal.js +239 -0
- package/dist/manager/routes/payments/refund/providers/stripe.js +160 -0
- package/dist/manager/routes/payments/refund/providers/test.js +204 -0
- package/dist/manager/routes/payments/trial-eligibility/get.js +29 -0
- package/dist/manager/routes/payments/uncancel/post.js +106 -0
- package/dist/manager/routes/payments/uncancel/providers/chargebee.js +30 -0
- package/dist/manager/routes/payments/uncancel/providers/paypal.js +25 -0
- package/dist/manager/routes/payments/uncancel/providers/stripe.js +27 -0
- package/dist/manager/routes/payments/uncancel/providers/test.js +114 -0
- package/dist/manager/routes/payments/webhook/post.js +157 -0
- package/dist/manager/routes/payments/webhook/providers/chargebee.js +218 -0
- package/dist/manager/routes/payments/webhook/providers/coinbase.js +91 -0
- package/dist/manager/routes/payments/webhook/providers/paypal.js +214 -0
- package/dist/manager/routes/payments/webhook/providers/stripe.js +182 -0
- package/dist/manager/routes/payments/webhook/providers/test.js +18 -0
- package/dist/manager/routes/payments/winback/post.js +276 -0
- package/dist/manager/routes/payments/winback/providers/chargebee.js +24 -0
- package/dist/manager/routes/payments/winback/providers/paypal.js +22 -0
- package/dist/manager/routes/payments/winback/providers/stripe.js +41 -0
- package/dist/manager/routes/payments/winback/providers/test.js +42 -0
- package/dist/manager/routes/restart/index.js +37 -0
- package/dist/manager/routes/special/electron-client/post.js +59 -0
- package/dist/manager/routes/test/authenticate/get.js +11 -0
- package/dist/manager/routes/test/health/get.js +8 -0
- package/dist/manager/routes/test/index.js +16 -0
- package/dist/manager/routes/test/lab/post.js +17 -0
- package/dist/manager/routes/test/redirect/get.js +27 -0
- package/dist/manager/routes/test/reset-account/post.js +79 -0
- package/dist/manager/routes/test/roster/get.js +40 -0
- package/dist/manager/routes/test/schema/post.js +20 -0
- package/dist/manager/routes/test/usage/post.js +44 -0
- package/dist/manager/routes/test/webhook/post.js +21 -0
- package/dist/manager/routes/user/api-keys/post.js +51 -0
- package/dist/manager/routes/user/connections/_context.js +194 -0
- package/dist/manager/routes/user/connections/_grant.js +247 -0
- package/dist/manager/routes/user/connections/_lease.js +184 -0
- package/dist/manager/routes/user/connections/_providers.js +191 -0
- package/dist/manager/routes/user/connections/_state.js +117 -0
- package/dist/manager/routes/user/connections/delete.js +55 -0
- package/dist/manager/routes/user/connections/get.js +167 -0
- package/dist/manager/routes/user/connections/post.js +370 -0
- package/dist/manager/routes/user/connections/providers/discord.js +41 -0
- package/dist/manager/routes/user/connections/providers/google.js +55 -0
- package/dist/manager/routes/user/connections/providers/kick.js +68 -0
- package/dist/manager/routes/user/connections/providers/spotify.js +40 -0
- package/dist/manager/routes/user/connections/providers/twitch.js +52 -0
- package/dist/manager/routes/user/data-request/delete.js +84 -0
- package/dist/manager/routes/user/data-request/get.js +229 -0
- package/dist/manager/routes/user/data-request/post.js +136 -0
- package/dist/manager/routes/user/delete.js +149 -0
- package/dist/manager/routes/user/feedback/post.js +81 -0
- package/dist/manager/routes/user/get.js +14 -0
- package/dist/manager/routes/user/orders/get.js +95 -0
- package/dist/manager/routes/user/sessions/delete.js +95 -0
- package/dist/manager/routes/user/sessions/get.js +40 -0
- package/dist/manager/routes/user/settings/validate/post.js +86 -0
- package/dist/manager/routes/user/signup/post.js +662 -0
- package/dist/manager/routes/user/subscription/get.js +77 -0
- package/dist/manager/routes/user/token/post.js +30 -0
- package/dist/manager/routes/verts/delete.js +43 -0
- package/dist/manager/routes/verts/get.js +49 -0
- package/dist/manager/routes/verts/post.js +61 -0
- package/dist/manager/routes/verts/put.js +75 -0
- package/dist/manager/routes/verts/redirect/get.js +36 -0
- package/dist/manager/routes/verts/serve/get.js +67 -0
- package/dist/manager/routes/verts/utils.js +436 -0
- package/dist/manager/schemas/admin/backup/post.js +8 -0
- package/dist/manager/schemas/admin/cron/post.js +8 -0
- package/dist/manager/schemas/admin/database/get.js +5 -0
- package/dist/manager/schemas/admin/database/post.js +6 -0
- package/dist/manager/schemas/admin/email/post.js +31 -0
- package/dist/manager/schemas/admin/firestore/get.js +5 -0
- package/dist/manager/schemas/admin/firestore/post.js +8 -0
- package/dist/manager/schemas/admin/firestore/query/post.js +5 -0
- package/dist/manager/schemas/admin/hook/post.js +8 -0
- package/dist/manager/schemas/admin/infer-contact/post.js +6 -0
- package/dist/manager/schemas/admin/notification/post.js +23 -0
- package/dist/manager/schemas/admin/payment/post.js +8 -0
- package/dist/manager/schemas/admin/post/post.js +23 -0
- package/dist/manager/schemas/admin/post/put.js +13 -0
- package/dist/manager/schemas/admin/repo/content/post.js +10 -0
- package/dist/manager/schemas/admin/stats/get.js +5 -0
- package/dist/manager/schemas/admin/users/disable/post.js +9 -0
- package/dist/manager/schemas/admin/users/list/get.js +10 -0
- package/dist/manager/schemas/admin/users/sync/post.js +7 -0
- package/dist/manager/schemas/brand/get.js +3 -0
- package/dist/manager/schemas/content/post/get.js +8 -0
- package/dist/manager/schemas/general/email/post.js +10 -0
- package/dist/manager/schemas/general/uuid/post.js +9 -0
- package/dist/manager/schemas/handler/post/post.js +13 -0
- package/dist/manager/schemas/health/get.js +3 -0
- package/dist/manager/schemas/marketing/campaign/delete.js +8 -0
- package/dist/manager/schemas/marketing/campaign/get.js +13 -0
- package/dist/manager/schemas/marketing/campaign/post.js +43 -0
- package/dist/manager/schemas/marketing/campaign/put.js +37 -0
- package/dist/manager/schemas/marketing/contact/delete.js +8 -0
- package/dist/manager/schemas/marketing/contact/post.js +14 -0
- package/dist/manager/schemas/marketing/contact/put.js +8 -0
- package/dist/manager/schemas/marketing/email-preferences/post.js +15 -0
- package/dist/manager/schemas/marketing/webhook/forward/post.js +8 -0
- package/dist/manager/schemas/marketing/webhook/post.js +7 -0
- package/dist/manager/schemas/payments/cancel/post.js +15 -0
- package/dist/manager/schemas/payments/discount/get.js +8 -0
- package/dist/manager/schemas/payments/dispute-alert/post.js +6 -0
- package/dist/manager/schemas/payments/intent/post.js +28 -0
- package/dist/manager/schemas/payments/plan/post.js +11 -0
- package/dist/manager/schemas/payments/portal/post.js +12 -0
- package/dist/manager/schemas/payments/refund/post.js +14 -0
- package/dist/manager/schemas/payments/trial-eligibility/get.js +7 -0
- package/dist/manager/schemas/payments/uncancel/post.js +9 -0
- package/dist/manager/schemas/payments/webhook/post.js +6 -0
- package/dist/manager/schemas/payments/winback/post.js +12 -0
- package/dist/manager/schemas/restart/index.js +5 -0
- package/dist/manager/schemas/special/electron-client/post.js +11 -0
- package/dist/manager/schemas/test/authenticate/get.js +3 -0
- package/dist/manager/schemas/test/health/get.js +3 -0
- package/dist/manager/schemas/test/index.js +5 -0
- package/dist/manager/schemas/test/lab/post.js +3 -0
- package/dist/manager/schemas/test/redirect/get.js +7 -0
- package/dist/manager/schemas/test/reset-account/post.js +3 -0
- package/dist/manager/schemas/test/roster/get.js +3 -0
- package/dist/manager/schemas/test/schema/post.js +70 -0
- package/dist/manager/schemas/test/usage/post.js +8 -0
- package/dist/manager/schemas/test/webhook/post.js +7 -0
- package/dist/manager/schemas/user/api-keys/post.js +6 -0
- package/dist/manager/schemas/user/connections/delete.js +8 -0
- package/dist/manager/schemas/user/connections/get.js +21 -0
- package/dist/manager/schemas/user/connections/post.js +12 -0
- package/dist/manager/schemas/user/data-request/delete.js +3 -0
- package/dist/manager/schemas/user/data-request/get.js +5 -0
- package/dist/manager/schemas/user/data-request/post.js +6 -0
- package/dist/manager/schemas/user/delete.js +6 -0
- package/dist/manager/schemas/user/feedback/post.js +8 -0
- package/dist/manager/schemas/user/get.js +3 -0
- package/dist/manager/schemas/user/orders/get.js +6 -0
- package/dist/manager/schemas/user/sessions/delete.js +6 -0
- package/dist/manager/schemas/user/sessions/get.js +6 -0
- package/dist/manager/schemas/user/settings/validate/post.js +8 -0
- package/dist/manager/schemas/user/signup/post.js +27 -0
- package/dist/manager/schemas/user/subscription/get.js +5 -0
- package/dist/manager/schemas/user/token/post.js +5 -0
- package/dist/manager/schemas/verts/delete.js +8 -0
- package/dist/manager/schemas/verts/get.js +9 -0
- package/dist/manager/schemas/verts/post.js +23 -0
- package/dist/manager/schemas/verts/put.js +20 -0
- package/dist/manager/schemas/verts/redirect/get.js +10 -0
- package/dist/manager/schemas/verts/serve/get.js +14 -0
- package/dist/manager/server-manager.js +69 -0
- package/dist/mcp/client.js +98 -0
- package/dist/mcp/handler.js +521 -0
- package/dist/mcp/index.js +157 -0
- package/dist/mcp/tools.js +555 -0
- package/dist/mcp/utils.js +108 -0
- package/dist/omega-bin.js +6 -0
- package/dist/require.js +3 -0
- package/dist/test/fixtures/firebase-project/.firebaserc +5 -0
- package/dist/test/fixtures/firebase-project/config/omega.json5 +131 -0
- package/dist/test/fixtures/firebase-project/database.rules.json +6 -0
- package/dist/test/fixtures/firebase-project/firebase.json +49 -0
- package/dist/test/fixtures/firebase-project/firestore.indexes.json +4 -0
- package/dist/test/fixtures/firebase-project/package.json +14 -0
- package/dist/test/fixtures/firebase-project/src/index.js +11 -0
- package/dist/test/fixtures/firebase-project/storage.rules +8 -0
- package/dist/test/parse-audit.js +25 -0
- package/dist/test/run-tests.js +90 -0
- package/dist/test/runner.js +982 -0
- package/dist/test/seed.js +242 -0
- package/dist/test/test-accounts.js +2660 -0
- package/dist/test/utils/assertions.js +189 -0
- package/dist/test/utils/email-capture.js +252 -0
- package/dist/test/utils/extended-mode-warning.js +11 -0
- package/dist/test/utils/firestore-rules-client.js +277 -0
- package/dist/test/utils/http-client.js +228 -0
- package/dist/test/utils/test-mode-file.js +192 -0
- package/dist/utils/merge-line-files.js +6 -0
- package/dist/utils/scaffold-defaults.js +71 -0
- package/dist/utils/test-lanes.js +62 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/analytics/adapters/ga4.js +26 -0
- package/dist/vendor/analytics/adapters/meta.js +26 -0
- package/dist/vendor/analytics/adapters/resolve.js +130 -0
- package/dist/vendor/analytics/adapters/tiktok.js +27 -0
- package/dist/vendor/analytics/catalog.js +908 -0
- package/dist/vendor/analytics/identity.js +136 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/bare-requires.js +153 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/defaults-engine.js +372 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/deploy.js +286 -0
- package/dist/vendor/devkit/license.js +155 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/merge-line-files.js +296 -0
- package/dist/vendor/devkit/npm-registry.js +52 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/parse-audit.js +74 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/scaffold-guard.js +96 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/test/assert.js +120 -0
- package/dist/vendor/devkit/test/define-cases.js +104 -0
- package/dist/vendor/devkit/test/runner-core.js +554 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/dist/vendor/monitoring/core.js +180 -0
- package/dist/vendor/monitoring/env.js +49 -0
- package/dist/vendor/monitoring/logger.js +39 -0
- package/dist/vendor/monitoring/node.js +72 -0
- package/docs/admin-post-route.md +57 -0
- package/docs/ai-library.md +171 -0
- package/docs/architecture.md +62 -0
- package/docs/audit.md +70 -0
- package/docs/auth-hooks.md +74 -0
- package/docs/build-system.md +65 -0
- package/docs/cdp-debugging.md +29 -0
- package/docs/cli-firestore-auth.md +85 -0
- package/docs/cli-logs.md +67 -0
- package/docs/cli-output.md +146 -0
- package/docs/code-patterns.md +77 -0
- package/docs/common-mistakes.md +12 -0
- package/docs/common-operations.md +60 -0
- package/docs/connections.md +212 -0
- package/docs/consent.md +362 -0
- package/docs/directory-structure.md +150 -0
- package/docs/email-system.md +459 -0
- package/docs/environment-detection.md +93 -0
- package/docs/file-naming.md +10 -0
- package/docs/firestore.md +134 -0
- package/docs/ghostii.md +240 -0
- package/docs/index.md +299 -0
- package/docs/key-files.md +37 -0
- package/docs/logging.md +60 -0
- package/docs/marketing-campaigns.md +407 -0
- package/docs/marketing-fields.md +25 -0
- package/docs/mcp.md +222 -0
- package/docs/migration.md +129 -0
- package/docs/payment-system.md +856 -0
- package/docs/paypal-sandbox-qa.md +105 -0
- package/docs/response-headers.md +9 -0
- package/docs/routes.md +211 -0
- package/docs/sanitization.md +71 -0
- package/docs/schemas.md +163 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/stripe-webhook-forwarding.md +20 -0
- package/docs/test-boot-layer.md +67 -0
- package/docs/test-framework.md +583 -0
- package/docs/usage-rate-limiting.md +121 -0
- package/docs/verts.md +29 -0
- package/package.json +143 -0
- package/templates/config/omega.json5 +322 -0
- package/templates/database.rules.json +82 -0
- package/templates/firebase.json +67 -0
- package/templates/firestore.framework.rules +191 -0
- package/templates/firestore.indexes.json +4 -0
- package/templates/firestore.rules +59 -0
- package/templates/index.js +12 -0
- package/templates/public/404.html +26 -0
- package/templates/public/index.html +24 -0
- package/templates/remoteconfig.template.json +1 -0
- package/templates/storage-lifecycle-config-1-day.json +9 -0
- package/templates/storage-lifecycle-config-30-days.json +9 -0
- package/templates/storage.rules +11 -0
- package/test/_init/accounts-validation.js +58 -0
- package/test/ai/tools-live.test.js +171 -0
- package/test/analytics/conversion-delivery.test.js +1013 -0
- package/test/analytics/match-normalization.test.js +238 -0
- package/test/analytics/signup-conversion.test.js +135 -0
- package/test/boot/cli-dispatch.test.js +142 -0
- package/test/boot/defaults-scaffold.test.js +248 -0
- package/test/boot/deploy-staging.test.js +446 -0
- package/test/boot/disposable-domains.test.js +154 -0
- package/test/boot/emulator-boots.test.js +39 -0
- package/test/boot/emulator-port-preflight.test.js +126 -0
- package/test/boot/emulator-ready-timeout.test.js +46 -0
- package/test/boot/project-id-refresh.test.js +73 -0
- package/test/boot/suite-portability.test.js +278 -0
- package/test/boot/update-command.test.js +63 -0
- package/test/cli/cross-platform.test.js +168 -0
- package/test/cli/custom-project-type.test.js +426 -0
- package/test/cli/deploy-license-env.test.js +100 -0
- package/test/cli/emulator-adoption.test.js +254 -0
- package/test/cli/emulator-orphans.test.js +658 -0
- package/test/cli/emulator-ownership.test.js +177 -0
- package/test/cli/emulator-port-retry.test.js +395 -0
- package/test/cli/emulator-shutdown.test.js +788 -0
- package/test/cli/emulator-stale-reap.test.js +574 -0
- package/test/cli/ensure-target.test.js +325 -0
- package/test/cli/flags.test.js +64 -0
- package/test/cli/https-trust.test.js +38 -0
- package/test/cli/install-update-dispatch.test.js +47 -0
- package/test/cli/lane-environments.test.js +159 -0
- package/test/cli/marketing-campaigns-seeded.test.js +194 -0
- package/test/cli/migrate-bare-requires.test.js +128 -0
- package/test/cli/migrate-markers.test.js +530 -0
- package/test/cli/required-indexes.test.js +64 -0
- package/test/cli/rules-compile.test.js +622 -0
- package/test/cli/rules-migration-deferral.test.js +259 -0
- package/test/cli/rules-version.test.js +104 -0
- package/test/cli/setup-load-files.test.js +66 -0
- package/test/cli/setup-offline-mode.test.js +276 -0
- package/test/cli/setup-retired.test.js +64 -0
- package/test/cli/setup-shared-project-indexes.test.js +262 -0
- package/test/cli/setup-tests-requires.test.js +45 -0
- package/test/cli/stage-env-compose.test.js +316 -0
- package/test/cli/stripe-live-lane.test.js +303 -0
- package/test/cli/target.test.js +182 -0
- package/test/cli/templates.test.js +66 -0
- package/test/cli/test-runner-env.test.js +115 -0
- package/test/cli/test-stack-shutdown.test.js +275 -0
- package/test/cli/test-target-no-match.test.js +128 -0
- package/test/cli/verb-logs.test.js +118 -0
- package/test/cli/version-dispatch.test.js +39 -0
- package/test/content/blog-generate.test.js +164 -0
- package/test/email/campaign-config-fault.test.js +376 -0
- package/test/email/campaign-cron-pipeline.test.js +536 -0
- package/test/email/campaign-send.test.js +47 -0
- package/test/email/consent-lifecycle.test.js +258 -0
- package/test/email/content-html-policy.test.js +270 -0
- package/test/email/feedback-and-plain-send.test.js +54 -0
- package/test/email/fixtures/clean.json +30 -0
- package/test/email/fixtures/editorial.json +30 -0
- package/test/email/fixtures/field-report.json +53 -0
- package/test/email/identity.test.js +321 -0
- package/test/email/marketing/consent-gate.test.js +265 -0
- package/test/email/marketing/custom-fields-catalog.test.js +259 -0
- package/test/email/marketing/prune-per-provider.test.js +762 -0
- package/test/email/marketing/remove-log-privacy.test.js +225 -0
- package/test/email/marketing-lifecycle.test.js +139 -0
- package/test/email/newsletter-generate.test.js +853 -0
- package/test/email/newsletter-svg-tokens.test.js +51 -0
- package/test/email/newsletter-templates.test.js +492 -0
- package/test/email/order-one-time-cta.test.js +97 -0
- package/test/email/render-content.test.js +248 -0
- package/test/email/safe-url.test.js +0 -0
- package/test/email/sanitize-images.test.js +66 -0
- package/test/email/send-log-privacy.test.js +107 -0
- package/test/email/templates.test.js +288 -0
- package/test/email/testing-capture.test.js +260 -0
- package/test/email/transactional-send.test.js +36 -0
- package/test/email/transactional.test.js +562 -0
- package/test/email/unsubscribe-groups.test.js +155 -0
- package/test/email/unsubscribe-key.test.js +91 -0
- package/test/email/validation-cases.test.js +152 -0
- package/test/email/validation.test.js +746 -0
- package/test/events/auth-delete-conversion.test.js +138 -0
- package/test/events/auth-delete-race.test.js +211 -0
- package/test/events/auth-on-create-log.test.js +164 -0
- package/test/events/auth-signup-conversion.test.js +141 -0
- package/test/events/auth-signup-limit.test.js +142 -0
- package/test/events/auth-trigger-log-privacy.test.js +256 -0
- package/test/events/cron-job-doc-shape.test.js +101 -0
- package/test/events/cron-reset-usage.test.js +116 -0
- package/test/events/notification-conversion.test.js +182 -0
- package/test/events/payments/_webhook-harness.js +307 -0
- package/test/events/payments/abandoned-cart-activity.test.js +135 -0
- package/test/events/payments/analytics-payment-events.test.js +945 -0
- package/test/events/payments/dispute-email-status.test.js +55 -0
- package/test/events/payments/journey-payments-abandoned.test.js +126 -0
- package/test/events/payments/journey-payments-cancel-endpoint.test.js +102 -0
- package/test/events/payments/journey-payments-cancel-no-order.test.js +76 -0
- package/test/events/payments/journey-payments-cancel.test.js +184 -0
- package/test/events/payments/journey-payments-decline.test.js +225 -0
- package/test/events/payments/journey-payments-discount.test.js +91 -0
- package/test/events/payments/journey-payments-dispute.test.js +190 -0
- package/test/events/payments/journey-payments-failure.test.js +148 -0
- package/test/events/payments/journey-payments-legacy-product.test.js +151 -0
- package/test/events/payments/journey-payments-one-time-decline.test.js +127 -0
- package/test/events/payments/journey-payments-one-time-failure.test.js +113 -0
- package/test/events/payments/journey-payments-one-time-refund.test.js +186 -0
- package/test/events/payments/journey-payments-one-time.test.js +175 -0
- package/test/events/payments/journey-payments-plan-change.test.js +146 -0
- package/test/events/payments/journey-payments-plan-switch-trial.test.js +161 -0
- package/test/events/payments/journey-payments-plan-switch.test.js +182 -0
- package/test/events/payments/journey-payments-refund-no-order.test.js +76 -0
- package/test/events/payments/journey-payments-refund-webhook.test.js +225 -0
- package/test/events/payments/journey-payments-suspend.test.js +183 -0
- package/test/events/payments/journey-payments-trial-cancel.test.js +132 -0
- package/test/events/payments/journey-payments-trial.test.js +173 -0
- package/test/events/payments/journey-payments-uid-resolution.test.js +134 -0
- package/test/events/payments/journey-payments-uncancel.test.js +157 -0
- package/test/events/payments/journey-payments-upgrade.test.js +137 -0
- package/test/events/payments/journey-payments-winback-decline.test.js +171 -0
- package/test/events/payments/journey-payments-winback.test.js +195 -0
- package/test/events/payments/paypal-expiry-cron.test.js +166 -0
- package/test/events/payments/purchase-failed-handler.test.js +80 -0
- package/test/events/payments/purchase-refunded-handler.test.js +108 -0
- package/test/events/payments/test-processor-doc-shape.test.js +162 -0
- package/test/events/payments/transition-order-emails.test.js +185 -0
- package/test/events/payments/transition-promo-lines.test.js +192 -0
- package/test/events/payments/transitions-detect.test.js +767 -0
- package/test/events/payments/trial-lapse-sweep-staleness.test.js +173 -0
- package/test/events/payments/trial-lapse-sweep.test.js +359 -0
- package/test/events/payments/webhook-atomic-writes.test.js +69 -0
- package/test/events/payments/webhook-chargebee-unreachable.test.js +106 -0
- package/test/events/payments/webhook-discount-clear.test.js +189 -0
- package/test/events/payments/webhook-failure-intent.test.js +93 -0
- package/test/events/payments/webhook-hosted-page-uid-trust.test.js +212 -0
- package/test/events/payments/webhook-ordering.test.js +326 -0
- package/test/events/payments/webhook-provider-lookup-trust.test.js +206 -0
- package/test/events/payments/webhook-refund-amount-trust.test.js +223 -0
- package/test/events/payments/webhook-refund-envelope-shape.test.js +148 -0
- package/test/events/payments/webhook-refund-linkage-trust.test.js +404 -0
- package/test/events/payments/webhook-refund-transaction-fallback.test.js +184 -0
- package/test/events/payments/webhook-refund-without-order.test.js +170 -0
- package/test/events/payments/webhook-refusal-reporting.test.js +194 -0
- package/test/events/payments/webhook-refused-intent.test.js +142 -0
- package/test/events/payments/webhook-retry-sweep.test.js +252 -0
- package/test/events/payments/webhook-transition-claim.test.js +389 -0
- package/test/events/payments/webhook-uid-trust.test.js +203 -0
- package/test/events/payments/webhook-user-without-auth.test.js +161 -0
- package/test/fixtures/chargebee/invoice-one-time.json +27 -0
- package/test/fixtures/chargebee/subscription-active.json +44 -0
- package/test/fixtures/chargebee/subscription-cancelled.json +42 -0
- package/test/fixtures/chargebee/subscription-in-trial.json +41 -0
- package/test/fixtures/chargebee/subscription-legacy-plan.json +41 -0
- package/test/fixtures/chargebee/subscription-non-renewing.json +41 -0
- package/test/fixtures/chargebee/subscription-paused.json +42 -0
- package/test/fixtures/chargebee/webhook-payment-failed.json +51 -0
- package/test/fixtures/chargebee/webhook-subscription-created.json +47 -0
- package/test/fixtures/coinbase/charge-confirmed.json +50 -0
- package/test/fixtures/coinbase/charge-failed.json +34 -0
- package/test/fixtures/coinbase/charge-pending.json +34 -0
- package/test/fixtures/migrate/ported-route.js.txt +11 -0
- package/test/fixtures/paypal/capture-completed.json +51 -0
- package/test/fixtures/paypal/capture-refunded.json +43 -0
- package/test/fixtures/paypal/order-approved.json +62 -0
- package/test/fixtures/paypal/order-completed.json +110 -0
- package/test/fixtures/paypal/sale-refunded.json +38 -0
- package/test/fixtures/paypal/subscription-active.json +76 -0
- package/test/fixtures/paypal/subscription-cancelled.json +50 -0
- package/test/fixtures/paypal/subscription-suspended.json +65 -0
- package/test/fixtures/stripe/checkout-session-completed.json +130 -0
- package/test/fixtures/stripe/invoice-payment-failed.json +148 -0
- package/test/fixtures/stripe/invoice-subscription-payment-failed.json +28 -0
- package/test/fixtures/stripe/invoice-subscription-payment-succeeded.json +28 -0
- package/test/fixtures/stripe/subscription-active.json +161 -0
- package/test/fixtures/stripe/subscription-canceled.json +161 -0
- package/test/fixtures/stripe/subscription-trialing.json +161 -0
- package/test/helpers/_shared-config.js +15 -0
- package/test/helpers/ai-request-payload.test.js +619 -0
- package/test/helpers/ai-schema-resolve.test.js +125 -0
- package/test/helpers/ai-test-provider.test.js +227 -0
- package/test/helpers/ai-token-accounting.test.js +150 -0
- package/test/helpers/ai-tools-format.test.js +384 -0
- package/test/helpers/analytics-no-id-notice.test.js +146 -0
- package/test/helpers/analytics-user-data.test.js +194 -0
- package/test/helpers/api-manager.test.js +311 -0
- package/test/helpers/backend-router.test.js +136 -0
- package/test/helpers/content/blog-auto-publisher.test.js +482 -0
- package/test/helpers/content/feed-parser.test.js +529 -0
- package/test/helpers/content/ghostii-blocks.test.js +135 -0
- package/test/helpers/content/ghostii-feed-integration.test.js +405 -0
- package/test/helpers/content/ghostii-write-article.test.js +244 -0
- package/test/helpers/dev-only-routes.test.js +225 -0
- package/test/helpers/env-reader.test.js +362 -0
- package/test/helpers/environment.test.js +263 -0
- package/test/helpers/event-middleware.test.js +407 -0
- package/test/helpers/infer-contact.test.js +157 -0
- package/test/helpers/lane-url.test.js +90 -0
- package/test/helpers/merge-line-files.test.js +272 -0
- package/test/helpers/metadata.test.js +122 -0
- package/test/helpers/middleware-request-log.test.js +134 -0
- package/test/helpers/middleware-user-log.test.js +124 -0
- package/test/helpers/payment/chargebee/parse-webhook.test.js +490 -0
- package/test/helpers/payment/chargebee/refund-details.test.js +198 -0
- package/test/helpers/payment/chargebee/to-unified-one-time.test.js +148 -0
- package/test/helpers/payment/chargebee/to-unified-subscription.test.js +649 -0
- package/test/helpers/payment/coinbase/create-intent.test.js +247 -0
- package/test/helpers/payment/coinbase/parse-webhook.test.js +195 -0
- package/test/helpers/payment/coinbase/refund-unsupported.test.js +141 -0
- package/test/helpers/payment/coinbase/to-unified-one-time.test.js +201 -0
- package/test/helpers/payment/discount-codes.test.js +141 -0
- package/test/helpers/payment/extract-resource.test.js +113 -0
- package/test/helpers/payment/fetch-failure.test.js +215 -0
- package/test/helpers/payment/license-gate.test.js +108 -0
- package/test/helpers/payment/order-id.test.js +99 -0
- package/test/helpers/payment/paypal/create-intent.test.js +382 -0
- package/test/helpers/payment/paypal/fetch-capture.test.js +123 -0
- package/test/helpers/payment/paypal/fetch-sale.test.js +183 -0
- package/test/helpers/payment/paypal/parse-webhook.test.js +678 -0
- package/test/helpers/payment/paypal/refund-details.test.js +202 -0
- package/test/helpers/payment/paypal/resolve-plan-id.test.js +108 -0
- package/test/helpers/payment/paypal/switch-plan.test.js +92 -0
- package/test/helpers/payment/paypal/to-unified-one-time.test.js +383 -0
- package/test/helpers/payment/paypal/to-unified-subscription.test.js +884 -0
- package/test/helpers/payment/stripe/fetch-charge.test.js +147 -0
- package/test/helpers/payment/stripe/parse-webhook.test.js +448 -0
- package/test/helpers/payment/stripe/refund-details.test.js +147 -0
- package/test/helpers/payment/stripe/to-unified-one-time.test.js +307 -0
- package/test/helpers/payment/stripe/to-unified-subscription.test.js +709 -0
- package/test/helpers/persona-domain.test.js +87 -0
- package/test/helpers/recaptcha.test.js +166 -0
- package/test/helpers/resolved-config.test.js +106 -0
- package/test/helpers/response-log-redaction.test.js +262 -0
- package/test/helpers/roles.test.js +155 -0
- package/test/helpers/route-context-debug-gate.test.js +118 -0
- package/test/helpers/route-context-logging.test.js +214 -0
- package/test/helpers/route-context.test.js +129 -0
- package/test/helpers/safe-compare.test.js +114 -0
- package/test/helpers/sanitize.test.js +223 -0
- package/test/helpers/schema-engine.test.js +537 -0
- package/test/helpers/schema-zod.test.js +554 -0
- package/test/helpers/seed-accounts-load.test.js +163 -0
- package/test/helpers/seed-google-personas.test.js +114 -0
- package/test/helpers/seeded-personas.test.js +823 -0
- package/test/helpers/settings.test.js +292 -0
- package/test/helpers/setup-engines-pin.test.js +68 -0
- package/test/helpers/setup-manifest-sync.test.js +116 -0
- package/test/helpers/slugify.test.js +395 -0
- package/test/helpers/storage.test.js +195 -0
- package/test/helpers/test-banner-latch.test.js +139 -0
- package/test/helpers/usage-consume.test.js +460 -0
- package/test/helpers/usage-log-privacy.test.js +121 -0
- package/test/helpers/user-doc-heal.test.js +540 -0
- package/test/helpers/user.test.js +771 -0
- package/test/helpers/webhook-forward.test.js +419 -0
- package/test/helpers/wipe-auth-project.test.js +143 -0
- package/test/mcp/discovery.test.js +52 -0
- package/test/mcp/oauth.test.js +160 -0
- package/test/mcp/protocol.test.js +278 -0
- package/test/mcp/roles.test.js +203 -0
- package/test/mcp/utils.test.js +245 -0
- package/test/notification/identity.test.js +155 -0
- package/test/routes/admin/create-post.test.js +362 -0
- package/test/routes/admin/database.test.js +133 -0
- package/test/routes/admin/deduplicate-image-alts.test.js +191 -0
- package/test/routes/admin/email-content-html.test.js +58 -0
- package/test/routes/admin/email-request-log.test.js +86 -0
- package/test/routes/admin/email.test.js +116 -0
- package/test/routes/admin/firestore-query.test.js +206 -0
- package/test/routes/admin/firestore.test.js +129 -0
- package/test/routes/admin/infer-contact.test.js +220 -0
- package/test/routes/admin/notification.test.js +199 -0
- package/test/routes/admin/post-convert-image.test.js +159 -0
- package/test/routes/admin/post-deploy-flag.test.js +81 -0
- package/test/routes/admin/post-download-error.test.js +90 -0
- package/test/routes/admin/post-resize-image.test.js +185 -0
- package/test/routes/admin/post.test.js +369 -0
- package/test/routes/admin/repo-content.test.js +223 -0
- package/test/routes/admin/stats.test.js +114 -0
- package/test/routes/admin/users-disable.test.js +63 -0
- package/test/routes/admin/users-list.test.js +71 -0
- package/test/routes/content/post.test.js +60 -0
- package/test/routes/general/uuid.test.js +133 -0
- package/test/routes/health.test.js +110 -0
- package/test/routes/marketing/campaign.test.js +184 -0
- package/test/routes/marketing/contact.test.js +416 -0
- package/test/routes/marketing/email-preferences.test.js +293 -0
- package/test/routes/marketing/push-send.test.js +34 -0
- package/test/routes/marketing/webhook-forward.test.js +63 -0
- package/test/routes/marketing/webhook.test.js +641 -0
- package/test/routes/payments/_route-harness.js +145 -0
- package/test/routes/payments/cancel-provider-errors.test.js +227 -0
- package/test/routes/payments/cancel-skip-guards.test.js +126 -0
- package/test/routes/payments/cancel-trialing.test.js +428 -0
- package/test/routes/payments/cancel.test.js +165 -0
- package/test/routes/payments/dedup-race.test.js +186 -0
- package/test/routes/payments/discount.test.js +82 -0
- package/test/routes/payments/dispute-alert.test.js +324 -0
- package/test/routes/payments/intent-discount-amounts.test.js +550 -0
- package/test/routes/payments/intent-discount-coupons.test.js +293 -0
- package/test/routes/payments/intent-one-time-metadata.test.js +122 -0
- package/test/routes/payments/intent-purchaser-guard.test.js +139 -0
- package/test/routes/payments/intent-zero-total.test.js +260 -0
- package/test/routes/payments/intent.test.js +413 -0
- package/test/routes/payments/plan.test.js +367 -0
- package/test/routes/payments/portal-return-url.test.js +107 -0
- package/test/routes/payments/portal.test.js +94 -0
- package/test/routes/payments/refund-one-time.test.js +254 -0
- package/test/routes/payments/refund-paypal-proration.test.js +190 -0
- package/test/routes/payments/refund.test.js +181 -0
- package/test/routes/payments/trial-eligibility.test.js +73 -0
- package/test/routes/payments/uncancel.test.js +270 -0
- package/test/routes/payments/webhook-stripe-invoice.test.js +129 -0
- package/test/routes/payments/webhook-stripe-refund-one-time.test.js +130 -0
- package/test/routes/payments/webhook-test-provider.test.js +156 -0
- package/test/routes/payments/webhook.test.js +115 -0
- package/test/routes/payments/winback-stripe-coupon.test.js +126 -0
- package/test/routes/payments/winback.test.js +597 -0
- package/test/routes/test/authenticate.test.js +79 -0
- package/test/routes/test/redirect.test.js +66 -0
- package/test/routes/test/reset-account.test.js +126 -0
- package/test/routes/test/roster.test.js +101 -0
- package/test/routes/test/schema.test.js +556 -0
- package/test/routes/test/usage.test.js +374 -0
- package/test/routes/user/api-keys.test.js +158 -0
- package/test/routes/user/connections-grant.test.js +759 -0
- package/test/routes/user/connections-identity.test.js +260 -0
- package/test/routes/user/connections-log-privacy.test.js +206 -0
- package/test/routes/user/connections-refresh-lease.test.js +696 -0
- package/test/routes/user/connections-return.test.js +261 -0
- package/test/routes/user/connections-uid.test.js +516 -0
- package/test/routes/user/delete.test.js +138 -0
- package/test/routes/user/feedback.test.js +106 -0
- package/test/routes/user/orders.test.js +233 -0
- package/test/routes/user/sessions.test.js +231 -0
- package/test/routes/user/settings-validate.test.js +84 -0
- package/test/routes/user/signup-emails.test.js +113 -0
- package/test/routes/user/signup-location.test.js +84 -0
- package/test/routes/user/signup-log-privacy.test.js +112 -0
- package/test/routes/user/signup.test.js +579 -0
- package/test/routes/user/subscription.test.js +101 -0
- package/test/routes/user/token.test.js +111 -0
- package/test/routes/user/user.test.js +158 -0
- package/test/routes/verts/cache.test.js +78 -0
- package/test/routes/verts/click-destination.test.js +76 -0
- package/test/routes/verts/crud.test.js +194 -0
- package/test/routes/verts/redirect.test.js +147 -0
- package/test/routes/verts/selection.test.js +237 -0
- package/test/routes/verts/serve.test.js +185 -0
- package/test/routes/verts/unit-document.test.js +117 -0
- package/test/rules/_environment.js +66 -0
- package/test/rules/brand-merge.test.js +195 -0
- package/test/rules/field-helpers.test.js +309 -0
- package/test/rules/notifications.test.js +577 -0
- package/test/rules/payments-carts.test.js +406 -0
- package/test/rules/sessions.test.js +170 -0
- package/test/rules/user.test.js +517 -0
- package/test/rules/verts.test.js +101 -0
- package/test/security/fetch-log-secrets.test.js +124 -0
- package/test/security/primitives.test.js +105 -0
- package/test/security/repo-pinning.test.js +77 -0
- package/test/stripe-live/subscription-lifecycle.test.js +141 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The steps a connection is made of, and the ONE context every one of them is
|
|
3
|
+
* called with ([#793](https://github.com/Omega-JS-Stack/omega/issues/793)).
|
|
4
|
+
*
|
|
5
|
+
* A provider module declares data (`urls`, `scope`, `params`, `pkce`) and, for
|
|
6
|
+
* anything the data cannot say, a function. Every function — the provider's own
|
|
7
|
+
* or the default below — is called as a METHOD on the module (`this.urls.*`
|
|
8
|
+
* keeps working) and receives the same object:
|
|
9
|
+
*
|
|
10
|
+
* { provider, providerName, Manager, ctx, uid, clientId, clientSecret,
|
|
11
|
+
* redirectUri, scope, state, pkce, code, token, fetch }
|
|
12
|
+
*
|
|
13
|
+
* `pkce` is `{ verifier, challenge }` when the provider declares `pkce: 'S256'`
|
|
14
|
+
* and null otherwise; `code` is the authorization code (exchange); `token` is
|
|
15
|
+
* the exchange RESPONSE for `identity` and the STORED record for `refresh`,
|
|
16
|
+
* `revoke` and `status`. `fetch` is the lane's HTTP call, handed in so a step
|
|
17
|
+
* has ONE seam.
|
|
18
|
+
*
|
|
19
|
+
* One concern, one file: nothing here reads the environment or loads a module.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const fetch = require('wonderful-fetch');
|
|
23
|
+
const { arrayify } = require('node-powertools');
|
|
24
|
+
|
|
25
|
+
// How long the REFRESH step may spend at the provider
|
|
26
|
+
// ([#783](https://github.com/Omega-JS-Stack/omega/issues/783)). It is shorter
|
|
27
|
+
// than the exchange's 60s on purpose: a refresh runs while holding the lease in
|
|
28
|
+
// `_lease.js`, and a call that outlived the lease would let a second caller
|
|
29
|
+
// reclaim it and spend the same one-time refresh token. That file asserts the
|
|
30
|
+
// relationship at load, reading THIS constant, so the two can never drift.
|
|
31
|
+
const REFRESH_TIMEOUT_MS = 20000;
|
|
32
|
+
|
|
33
|
+
// What the default `revoke` answers for a provider that declares no
|
|
34
|
+
// `urls.revoke`: there is nothing to call, the record is still deleted, and the
|
|
35
|
+
// route says which of the two happened
|
|
36
|
+
const REVOKE_UNSUPPORTED = 'unsupported';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The one context object every step is called with — the ONE home of its shape.
|
|
40
|
+
* Keys the step at hand has no use for are present and undefined, so a provider
|
|
41
|
+
* author reads one table and never wonders which call site they are in.
|
|
42
|
+
*
|
|
43
|
+
* @param {object} parts - Whatever the route resolved
|
|
44
|
+
* @returns {object} The step context
|
|
45
|
+
*/
|
|
46
|
+
function buildGrantContext({
|
|
47
|
+
provider,
|
|
48
|
+
providerName,
|
|
49
|
+
Manager,
|
|
50
|
+
ctx,
|
|
51
|
+
uid,
|
|
52
|
+
clientId,
|
|
53
|
+
clientSecret,
|
|
54
|
+
redirectUri,
|
|
55
|
+
scope,
|
|
56
|
+
state,
|
|
57
|
+
pkce,
|
|
58
|
+
code,
|
|
59
|
+
token,
|
|
60
|
+
}) {
|
|
61
|
+
return {
|
|
62
|
+
provider,
|
|
63
|
+
providerName,
|
|
64
|
+
Manager,
|
|
65
|
+
ctx,
|
|
66
|
+
uid,
|
|
67
|
+
clientId,
|
|
68
|
+
clientSecret,
|
|
69
|
+
redirectUri,
|
|
70
|
+
scope,
|
|
71
|
+
state,
|
|
72
|
+
pkce: pkce || null,
|
|
73
|
+
code,
|
|
74
|
+
token,
|
|
75
|
+
fetch,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The authorization URL a redirect flow sends the user to.
|
|
81
|
+
*
|
|
82
|
+
* @param {object} context - The step context
|
|
83
|
+
* @returns {string} The authorization URL
|
|
84
|
+
*/
|
|
85
|
+
function defaultAuthorize(context) {
|
|
86
|
+
const { provider, clientId, redirectUri, scope, state, pkce } = context;
|
|
87
|
+
|
|
88
|
+
const url = new URL(provider.urls.authorize);
|
|
89
|
+
|
|
90
|
+
url.searchParams.set('state', state);
|
|
91
|
+
url.searchParams.set('client_id', clientId);
|
|
92
|
+
url.searchParams.set('redirect_uri', redirectUri);
|
|
93
|
+
url.searchParams.set('response_type', 'code');
|
|
94
|
+
url.searchParams.set('scope', arrayify(scope).join(' '));
|
|
95
|
+
|
|
96
|
+
// Provider-specific authorize params
|
|
97
|
+
for (const [key, value] of Object.entries(provider.params || {})) {
|
|
98
|
+
url.searchParams.set(key, value);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// PKCE: the challenge travels, the verifier never does
|
|
102
|
+
if (pkce) {
|
|
103
|
+
url.searchParams.set('code_challenge', pkce.challenge);
|
|
104
|
+
url.searchParams.set('code_challenge_method', 'S256');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return url.toString();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Exchange the authorization code for tokens.
|
|
112
|
+
*
|
|
113
|
+
* @param {object} context - The step context
|
|
114
|
+
* @returns {Promise<object>} The token response
|
|
115
|
+
*/
|
|
116
|
+
function defaultExchange(context) {
|
|
117
|
+
const { provider, clientId, clientSecret, redirectUri, code, pkce, fetch: call } = context;
|
|
118
|
+
|
|
119
|
+
const body = {
|
|
120
|
+
client_id: clientId,
|
|
121
|
+
// A PUBLIC client has no secret to send
|
|
122
|
+
// ([#785](https://github.com/Omega-JS-Stack/omega/issues/785)): Twitch (and
|
|
123
|
+
// any OAuth 2.1 provider) registers one, the brand holds an id alone, and an
|
|
124
|
+
// EMPTY `client_secret` is not the same request as no `client_secret` — the
|
|
125
|
+
// token endpoint reads the field as a wrong secret and refuses the grant.
|
|
126
|
+
// The key is omitted when the `CONNECTIONS_<PROVIDER>_CLIENT_SECRET` key is
|
|
127
|
+
// unset or empty; a confidential client's body is unchanged, field for field.
|
|
128
|
+
...(clientSecret ? { client_secret: clientSecret } : {}),
|
|
129
|
+
grant_type: 'authorization_code',
|
|
130
|
+
redirect_uri: redirectUri,
|
|
131
|
+
code: code,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
if (pkce) {
|
|
135
|
+
body.code_verifier = pkce.verifier;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return call(provider.urls.token, {
|
|
139
|
+
method: 'POST',
|
|
140
|
+
timeout: 60000,
|
|
141
|
+
response: 'json',
|
|
142
|
+
body: new URLSearchParams(body),
|
|
143
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Refresh an access token from the stored record.
|
|
149
|
+
*
|
|
150
|
+
* @param {object} context - The step context
|
|
151
|
+
* @returns {Promise<object>} The token response
|
|
152
|
+
*/
|
|
153
|
+
function defaultRefresh(context) {
|
|
154
|
+
const { provider, clientId, clientSecret, token, fetch: call } = context;
|
|
155
|
+
|
|
156
|
+
const body = {
|
|
157
|
+
client_id: clientId,
|
|
158
|
+
// Omitted for a public client, exactly as in the exchange above
|
|
159
|
+
// ([#785](https://github.com/Omega-JS-Stack/omega/issues/785))
|
|
160
|
+
...(clientSecret ? { client_secret: clientSecret } : {}),
|
|
161
|
+
grant_type: 'refresh_token',
|
|
162
|
+
refresh_token: token.refresh_token,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return call(provider.urls.token, {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
timeout: REFRESH_TIMEOUT_MS,
|
|
168
|
+
response: 'json',
|
|
169
|
+
body: new URLSearchParams(body),
|
|
170
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Revoke the access token at the provider — RFC 7009: a form POST carrying the
|
|
176
|
+
* token, plus the client credentials the provider knows this app by.
|
|
177
|
+
*
|
|
178
|
+
* A provider that declares no `urls.revoke` cannot revoke at all (Spotify), and
|
|
179
|
+
* says so rather than pretending: the answer is `'unsupported'`, and the delete
|
|
180
|
+
* removes the record either way. Every other outcome is silence (revoked) or a
|
|
181
|
+
* throw (the route reports it and still deletes).
|
|
182
|
+
*
|
|
183
|
+
* @param {object} context - The step context (`token` is the stored record)
|
|
184
|
+
* @returns {Promise<string|undefined>} `'unsupported'`, or nothing
|
|
185
|
+
*/
|
|
186
|
+
async function defaultRevoke(context) {
|
|
187
|
+
const { provider, clientId, clientSecret, token, fetch: call } = context;
|
|
188
|
+
|
|
189
|
+
if (!provider.urls?.revoke) {
|
|
190
|
+
return REVOKE_UNSUPPORTED;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await call(provider.urls.revoke, {
|
|
194
|
+
method: 'POST',
|
|
195
|
+
timeout: 60000,
|
|
196
|
+
body: new URLSearchParams({
|
|
197
|
+
token: token.access_token,
|
|
198
|
+
...(clientId ? { client_id: clientId } : {}),
|
|
199
|
+
...(clientSecret ? { client_secret: clientSecret } : {}),
|
|
200
|
+
}),
|
|
201
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// The steps the lane can run without the provider's help. `identity` is not
|
|
206
|
+
// here: nothing can guess whose account a token belongs to, which is why
|
|
207
|
+
// assertProviderShape requires it. Neither is `status`: without one, a stored
|
|
208
|
+
// refresh token IS the answer.
|
|
209
|
+
const GRANT_DEFAULTS = {
|
|
210
|
+
authorize: defaultAuthorize,
|
|
211
|
+
exchange: defaultExchange,
|
|
212
|
+
refresh: defaultRefresh,
|
|
213
|
+
revoke: defaultRevoke,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Run one step: the provider's own function when it declares one, else the
|
|
218
|
+
* default — always as a method on the module.
|
|
219
|
+
*
|
|
220
|
+
* @param {object} provider - The provider module
|
|
221
|
+
* @param {'authorize'|'exchange'|'identity'|'refresh'|'revoke'|'status'} step - The step to run
|
|
222
|
+
* @param {object} context - The step context
|
|
223
|
+
* @returns {*} Whatever the step answers (a URL string, a token response, an identity)
|
|
224
|
+
* @throws {Error} When the step has neither an override nor a default
|
|
225
|
+
*/
|
|
226
|
+
function runStep(provider, step, context) {
|
|
227
|
+
const fn = typeof provider[step] === 'function' ? provider[step] : GRANT_DEFAULTS[step];
|
|
228
|
+
|
|
229
|
+
if (typeof fn !== 'function') {
|
|
230
|
+
// A programmer error: the route asked for a step this provider cannot run
|
|
231
|
+
// and the lane has no default for. Loud here beats a TypeError at the seam.
|
|
232
|
+
throw new Error(`Connection provider ${provider.provider} declares no ${step}() and the lane has no default for it`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return fn.call(provider, context);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
REFRESH_TIMEOUT_MS,
|
|
240
|
+
REVOKE_UNSUPPORTED,
|
|
241
|
+
buildGrantContext,
|
|
242
|
+
defaultAuthorize,
|
|
243
|
+
defaultExchange,
|
|
244
|
+
defaultRefresh,
|
|
245
|
+
defaultRevoke,
|
|
246
|
+
runStep,
|
|
247
|
+
};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const { FieldValue } = require('firebase-admin/firestore');
|
|
3
|
+
const { REFRESH_TIMEOUT_MS } = require('./_grant.js');
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// The refresh lease ([#783](https://github.com/Omega-JS-Stack/omega/issues/783))
|
|
7
|
+
//
|
|
8
|
+
// A backend never runs as one process: Cloud Functions scales to as many
|
|
9
|
+
// instances as the traffic asks for, and two of them refreshing the SAME user's
|
|
10
|
+
// SAME provider at once spend a one-time refresh token twice (Twitch rotates
|
|
11
|
+
// its own on every use). The loser's exchange is refused and the token it stores
|
|
12
|
+
// is dead. A per-process lock cannot see the other instance; Firestore can, so
|
|
13
|
+
// the lease is a NOTE ON THE RECORD, taken in a transaction.
|
|
14
|
+
//
|
|
15
|
+
// It lives beside the route helpers rather than inside post.js so `delete` can
|
|
16
|
+
// take the same lease later — revoking under a running refresh is the same race.
|
|
17
|
+
// ============================================================================
|
|
18
|
+
|
|
19
|
+
// A lease older than this is STALE and anybody may take it: an instance that
|
|
20
|
+
// crashed mid-refresh (or was evicted) never runs its own clear, and a record
|
|
21
|
+
// that stayed leased forever would refuse every later refresh.
|
|
22
|
+
const LEASE_TTL_SECONDS = 30;
|
|
23
|
+
|
|
24
|
+
// How the loser waits for the winner's write: re-read every POLL, give up after WAIT.
|
|
25
|
+
const LEASE_POLL_MS = 500;
|
|
26
|
+
const LEASE_WAIT_MS = 10000;
|
|
27
|
+
|
|
28
|
+
// The lease has to OUTLIVE the call it protects. The winner holds it across the
|
|
29
|
+
// provider's refresh POST, and that call has its own timeout: if the timeout were
|
|
30
|
+
// the longer of the two, a slow provider would let the lease expire under a
|
|
31
|
+
// running refresh, a second caller would win it, and both would spend the same
|
|
32
|
+
// one-time refresh token — exactly the race the lease exists to stop. So the
|
|
33
|
+
// relationship is asserted here, at load, against the one home of the timeout:
|
|
34
|
+
// a programmer changing either number learns at boot, not from a dead token in
|
|
35
|
+
// production.
|
|
36
|
+
if (LEASE_TTL_SECONDS * 1000 <= REFRESH_TIMEOUT_MS) {
|
|
37
|
+
throw new Error(`Connections refresh lease: LEASE_TTL_SECONDS (${LEASE_TTL_SECONDS}s) must exceed the refresh step's REFRESH_TIMEOUT_MS (${REFRESH_TIMEOUT_MS}ms) — a lease that expires under a running refresh lets a second caller spend the same one-time refresh token`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ONE id per process, minted at module load: the lease says which instance holds
|
|
41
|
+
// it, so a stalled refresh is nameable in a log and in the 409 a loser answers.
|
|
42
|
+
const INSTANCE_ID = crypto.randomBytes(8).toString('hex');
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The stored connection record, whatever the document is missing.
|
|
46
|
+
*
|
|
47
|
+
* @param {object} snapshot - A Firestore document snapshot
|
|
48
|
+
* @param {string} provider - The provider key
|
|
49
|
+
* @returns {object} The record, or {}
|
|
50
|
+
*/
|
|
51
|
+
function connectionRecord(snapshot, provider) {
|
|
52
|
+
return (snapshot.data() || {}).connections?.[provider] || {};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Take the refresh lease on `users/<uid>.connections.<provider>`, in a
|
|
57
|
+
* transaction so two instances reading the same absent lease cannot both write
|
|
58
|
+
* one.
|
|
59
|
+
*
|
|
60
|
+
* The caller that WINS runs the provider refresh and is the one that clears the
|
|
61
|
+
* lease (in its own write, or through clearRefreshLease() when it fails). The
|
|
62
|
+
* caller that LOSES touches the provider not at all — it waits for the winner's
|
|
63
|
+
* token with awaitRefreshedToken().
|
|
64
|
+
*
|
|
65
|
+
* @param {object} options
|
|
66
|
+
* @param {object} options.admin - The firebase-admin library (the route's own handle)
|
|
67
|
+
* @param {string} options.uid - The user the connection belongs to
|
|
68
|
+
* @param {string} options.provider - The provider key
|
|
69
|
+
* @returns {Promise<{won: boolean, lease: object, updatedUNIX: number, token: object|undefined}>}
|
|
70
|
+
* Whether this caller holds the lease, the lease note (this caller's, or the
|
|
71
|
+
* holder's when it lost), the `updated.timestampUNIX` the record carried at
|
|
72
|
+
* entry — the value a loser watches for movement past — and the stored token
|
|
73
|
+
* AS THE TRANSACTION SAW IT, which is the one a winner refreshes with
|
|
74
|
+
*/
|
|
75
|
+
async function acquireRefreshLease({ admin, uid, provider }) {
|
|
76
|
+
const firestore = admin.firestore();
|
|
77
|
+
const docRef = firestore.doc(`users/${uid}`);
|
|
78
|
+
|
|
79
|
+
return firestore.runTransaction(async (transaction) => {
|
|
80
|
+
const snapshot = await transaction.get(docRef);
|
|
81
|
+
const record = connectionRecord(snapshot, provider);
|
|
82
|
+
|
|
83
|
+
const nowMs = Date.now();
|
|
84
|
+
const nowUNIX = Math.floor(nowMs / 1000);
|
|
85
|
+
const updatedUNIX = record.updated?.timestampUNIX || 0;
|
|
86
|
+
const held = record.refreshing;
|
|
87
|
+
|
|
88
|
+
if (held && nowUNIX - (held.timestampUNIX || 0) < LEASE_TTL_SECONDS) {
|
|
89
|
+
return { won: false, lease: held, updatedUNIX, token: record.token };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const lease = {
|
|
93
|
+
instance: INSTANCE_ID,
|
|
94
|
+
timestamp: new Date(nowMs).toISOString(),
|
|
95
|
+
timestampUNIX: nowUNIX,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
transaction.set(docRef, {
|
|
99
|
+
connections: { [provider]: { refreshing: lease } },
|
|
100
|
+
}, { merge: true });
|
|
101
|
+
|
|
102
|
+
return { won: true, lease, updatedUNIX, token: record.token };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Drop the lease without touching anything else — the FAILURE path of a winner
|
|
108
|
+
* (the success path removes it in the same write that stores the token, so the
|
|
109
|
+
* record is never one write away from consistent).
|
|
110
|
+
*
|
|
111
|
+
* @param {object} options
|
|
112
|
+
* @param {object} options.admin - The firebase-admin library
|
|
113
|
+
* @param {string} options.uid - The user the connection belongs to
|
|
114
|
+
* @param {string} options.provider - The provider key
|
|
115
|
+
* @returns {Promise<void>}
|
|
116
|
+
*/
|
|
117
|
+
async function clearRefreshLease({ admin, uid, provider }) {
|
|
118
|
+
await admin.firestore().doc(`users/${uid}`).set({
|
|
119
|
+
connections: { [provider]: { refreshing: FieldValue.delete() } },
|
|
120
|
+
}, { merge: true });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Wait for the caller that WON the lease to finish. A loser runs no grant step at
|
|
125
|
+
* all: the refresh token is one-time, and the winner is already spending it.
|
|
126
|
+
*
|
|
127
|
+
* The wait has THREE outcomes, and only one of them is a token:
|
|
128
|
+
*
|
|
129
|
+
* - `refreshed` — `updated.timestampUNIX` moved past what it was at entry. The
|
|
130
|
+
* winner wrote, and the record now holds a token this caller can answer with.
|
|
131
|
+
* - `abandoned` — the note is gone but the stamp never moved: the winner's
|
|
132
|
+
* provider call failed (or its lease expired) and the stored token is the
|
|
133
|
+
* PRE-refresh one. Answering it as a success would hand a caller a token that
|
|
134
|
+
* may be expired, and a rotating provider may already have invalidated it, so
|
|
135
|
+
* this is a conflict to report — never a token to return.
|
|
136
|
+
* - `timeout` — neither happened inside the window.
|
|
137
|
+
*
|
|
138
|
+
* `pollMs`/`timeoutMs` are the contract above, as parameters so the offline case
|
|
139
|
+
* can drive a timeout without waiting ten real seconds.
|
|
140
|
+
*
|
|
141
|
+
* @param {object} options
|
|
142
|
+
* @param {object} options.admin - The firebase-admin library
|
|
143
|
+
* @param {string} options.uid - The user the connection belongs to
|
|
144
|
+
* @param {string} options.provider - The provider key
|
|
145
|
+
* @param {number} options.since - The `updated.timestampUNIX` seen at entry
|
|
146
|
+
* @param {number} [options.pollMs] - Milliseconds between reads
|
|
147
|
+
* @param {number} [options.timeoutMs] - Milliseconds before giving up
|
|
148
|
+
* @returns {Promise<{outcome: 'refreshed'|'abandoned'|'timeout', token: object|null}>}
|
|
149
|
+
* The outcome, and the stored token on `refreshed` alone
|
|
150
|
+
*/
|
|
151
|
+
async function awaitRefreshedToken({ admin, uid, provider, since, pollMs = LEASE_POLL_MS, timeoutMs = LEASE_WAIT_MS }) {
|
|
152
|
+
const docRef = admin.firestore().doc(`users/${uid}`);
|
|
153
|
+
const startTime = Date.now();
|
|
154
|
+
|
|
155
|
+
while (true) {
|
|
156
|
+
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
157
|
+
|
|
158
|
+
const record = connectionRecord(await docRef.get(), provider);
|
|
159
|
+
|
|
160
|
+
// The winner writes the token, the stamp and the note's removal in ONE
|
|
161
|
+
// write, so a moved stamp is checked first: it is the only success
|
|
162
|
+
if ((record.updated?.timestampUNIX || 0) > since) {
|
|
163
|
+
return { outcome: 'refreshed', token: record.token || null };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!record.refreshing) {
|
|
167
|
+
return { outcome: 'abandoned', token: null };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
171
|
+
return { outcome: 'timeout', token: null };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports = {
|
|
177
|
+
INSTANCE_ID,
|
|
178
|
+
LEASE_TTL_SECONDS,
|
|
179
|
+
LEASE_POLL_MS,
|
|
180
|
+
LEASE_WAIT_MS,
|
|
181
|
+
acquireRefreshLease,
|
|
182
|
+
clearRefreshLease,
|
|
183
|
+
awaitRefreshedToken,
|
|
184
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider modules: where they are found, whether they can run a grant, and the
|
|
3
|
+
* credentials the brand registered them with
|
|
4
|
+
* ([#793](https://github.com/Omega-JS-Stack/omega/issues/793)).
|
|
5
|
+
*
|
|
6
|
+
* One concern, one file: nothing here knows what a grant step does, what the
|
|
7
|
+
* state cipher is, or which user the route is acting on.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const jetpack = require('fs-jetpack');
|
|
12
|
+
// Aliased: this file exports its OWN loadProvider (the connection lookup below)
|
|
13
|
+
const loadProviderModule = require('../../../libraries/load-provider.js');
|
|
14
|
+
const providerPath = loadProviderModule.providerPath;
|
|
15
|
+
const env = require('../../../libraries/env.js');
|
|
16
|
+
|
|
17
|
+
const PROVIDERS_DIR = path.join(__dirname, 'providers');
|
|
18
|
+
|
|
19
|
+
// A brand's own providers, staged with the rest of its src/
|
|
20
|
+
// ([#771](https://github.com/Omega-JS-Stack/omega/issues/771)): the same
|
|
21
|
+
// `${Manager.cwd}/<dir>/<name>.js` convention `src/routes/` and the event
|
|
22
|
+
// handlers already use, and it is searched FIRST — a brand may replace a
|
|
23
|
+
// packaged provider by shipping a file with its name.
|
|
24
|
+
const BRAND_PROVIDERS_DIR = 'connections';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The directories a provider name is looked up in, in order: the brand's own
|
|
28
|
+
* staged `connections/` dir, then the package's.
|
|
29
|
+
*
|
|
30
|
+
* @param {object|null} Manager - The BackendManager (its `cwd` is the staged consumer dir)
|
|
31
|
+
* @returns {string[]} Absolute directory paths, brand first
|
|
32
|
+
*/
|
|
33
|
+
function providerDirs(Manager) {
|
|
34
|
+
const dirs = [];
|
|
35
|
+
|
|
36
|
+
if (Manager && Manager.cwd) {
|
|
37
|
+
dirs.push(path.join(Manager.cwd, BRAND_PROVIDERS_DIR));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
dirs.push(PROVIDERS_DIR);
|
|
41
|
+
|
|
42
|
+
return dirs;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A provider module that cannot run its grant is a PROGRAMMER error, not a
|
|
47
|
+
* caller's typo: it throws here, naming the file and the field, instead of
|
|
48
|
+
* failing at the redirect or the token exchange with the provider's own
|
|
49
|
+
* opaque message ([#771](https://github.com/Omega-JS-Stack/omega/issues/771)).
|
|
50
|
+
*
|
|
51
|
+
* The three requirements are the three things the lane cannot invent
|
|
52
|
+
* ([#793](https://github.com/Omega-JS-Stack/omega/issues/793)): where the user
|
|
53
|
+
* is sent, how the code becomes a token, and who the token belongs to. Every
|
|
54
|
+
* other step has a default.
|
|
55
|
+
*
|
|
56
|
+
* The message names the FILE, never the path it was found at: the request that
|
|
57
|
+
* tripped it belongs to a signed-in user, and where a brand's code is deployed
|
|
58
|
+
* is not theirs to read. The file name is what a developer needs anyway.
|
|
59
|
+
*
|
|
60
|
+
* @param {*} provider - The required module
|
|
61
|
+
* @param {string} filePath - The file it came from
|
|
62
|
+
* @returns {object} The same module
|
|
63
|
+
* @throws {Error} When the module cannot answer an authorize, an exchange or an identity
|
|
64
|
+
*/
|
|
65
|
+
function assertProviderShape(provider, filePath) {
|
|
66
|
+
const file = path.basename(filePath);
|
|
67
|
+
|
|
68
|
+
if (!provider || typeof provider !== 'object') {
|
|
69
|
+
throw new Error(`Connection provider ${file} must export an object (the module shape: provider, name, urls, scope, identity)`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!provider.urls?.authorize && typeof provider.authorize !== 'function') {
|
|
73
|
+
throw new Error(`Connection provider ${file} declares no urls.authorize and no authorize() — one of the two has to say where the user is sent`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!provider.urls?.token && typeof provider.exchange !== 'function') {
|
|
77
|
+
throw new Error(`Connection provider ${file} declares no urls.token and no exchange() — one of the two has to say how the code becomes a token`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (typeof provider.identity !== 'function') {
|
|
81
|
+
throw new Error(`Connection provider ${file} declares no identity() — the lane cannot know whose account a token belongs to`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (provider.pkce && provider.pkce !== 'S256') {
|
|
85
|
+
throw new Error(`Connection provider ${file} declares pkce: '${provider.pkce}' — S256 is the only challenge method the lane mints`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return provider;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Resolve a provider module by name: the brand's own file wins, the package's
|
|
93
|
+
* answers otherwise, and a name nothing answers is null (the caller's 400).
|
|
94
|
+
*
|
|
95
|
+
* @param {string} providerName - The provider key ('google', 'twitch', …)
|
|
96
|
+
* @param {object|null} Manager - The BackendManager
|
|
97
|
+
* @returns {object|null} The provider module, or null when no file exists
|
|
98
|
+
* @throws {Error} When a file exists but exports a malformed shape
|
|
99
|
+
*/
|
|
100
|
+
function resolveProvider(providerName, Manager) {
|
|
101
|
+
for (const dir of providerDirs(Manager)) {
|
|
102
|
+
let file;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
file = providerPath(dir, providerName);
|
|
106
|
+
} catch (e) {
|
|
107
|
+
// An invalid name can never name a file: it is an unknown provider, and
|
|
108
|
+
// the confined loader is what decided that (never a second copy of the rule)
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (jetpack.exists(file) !== 'file') {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return assertProviderShape(loadProviderModule(dir, providerName), file);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The credential pair a provider was registered with — the ONE home of the env
|
|
124
|
+
* key convention ([#793](https://github.com/Omega-JS-Stack/omega/issues/793)):
|
|
125
|
+
* the provider name uppercased, dashes as underscores.
|
|
126
|
+
*
|
|
127
|
+
* A public client has no secret ([#785](https://github.com/Omega-JS-Stack/omega/issues/785)),
|
|
128
|
+
* and an unset key resolves to nothing rather than an empty string the grant
|
|
129
|
+
* would send.
|
|
130
|
+
*
|
|
131
|
+
* @param {string} providerName - The provider key
|
|
132
|
+
* @returns {{ clientId: string|undefined, clientSecret: string|undefined }}
|
|
133
|
+
*/
|
|
134
|
+
function providerCredentials(providerName) {
|
|
135
|
+
const providerEnvKey = providerName.toUpperCase().replace(/-/g, '_');
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
clientId: env.get(`CONNECTIONS_${providerEnvKey}_CLIENT_ID`),
|
|
139
|
+
clientSecret: env.get(`CONNECTIONS_${providerEnvKey}_CLIENT_SECRET`),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Load a provider and its credentials, or the 400 an unknown name answers.
|
|
145
|
+
*
|
|
146
|
+
* @param {string} providerName - The provider key
|
|
147
|
+
* @param {object|null} Manager - The BackendManager
|
|
148
|
+
* @returns {object} `{ connectionProvider, clientId, clientSecret }` or `{ error }`
|
|
149
|
+
*/
|
|
150
|
+
function loadProvider(providerName, Manager) {
|
|
151
|
+
const connectionProvider = resolveProvider(providerName, Manager);
|
|
152
|
+
|
|
153
|
+
if (!connectionProvider) {
|
|
154
|
+
return { error: { message: `Unknown connection provider: ${providerName}`, code: 400 } };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return { connectionProvider, ...providerCredentials(providerName) };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The ONE line a provider's identity step may log
|
|
162
|
+
* ([#641](https://github.com/Omega-JS-Stack/omega/issues/641)).
|
|
163
|
+
*
|
|
164
|
+
* Every provider used to hand `ctx.log` the token exchange RESPONSE, which
|
|
165
|
+
* carries the access token, the refresh token and (Google) the id token — so a
|
|
166
|
+
* brand's Cloud Logging held live third-party credentials for the whole
|
|
167
|
+
* retention window, readable by anyone with a log-viewer role. The decoded
|
|
168
|
+
* profile and the provider's identity response went the same way, and those are
|
|
169
|
+
* the user's PII.
|
|
170
|
+
*
|
|
171
|
+
* What a log needs is WHICH provider, WHOSE account, and whether the exchange
|
|
172
|
+
* came back with a token. Nothing on this line is a credential or a person, and
|
|
173
|
+
* one home for the format keeps the providers from drifting apart.
|
|
174
|
+
*
|
|
175
|
+
* @param {object} ctx - The route context (the log sink)
|
|
176
|
+
* @param {object} options
|
|
177
|
+
* @param {string} options.provider - The provider key ('google', 'discord', …)
|
|
178
|
+
* @param {string|null} [options.uid] - The account the identity is being linked to
|
|
179
|
+
* @param {object} [options.token] - The token exchange response — READ for whether
|
|
180
|
+
* it succeeded, never logged
|
|
181
|
+
*/
|
|
182
|
+
function logIdentityCheck(ctx, { provider, uid, token }) {
|
|
183
|
+
ctx.log(`identity(): provider=${provider}, uid=${uid || 'null'}, tokenExchange=${token?.access_token ? 'succeeded' : 'failed'}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module.exports = {
|
|
187
|
+
assertProviderShape,
|
|
188
|
+
resolveProvider,
|
|
189
|
+
loadProvider,
|
|
190
|
+
logIdentityCheck,
|
|
191
|
+
};
|