@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,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage log-privacy test — a usage line names the counter it moved, never the document.
|
|
3
|
+
*
|
|
4
|
+
* `Usage` holds the WHOLE user document (`self.user`) so it can read and write the
|
|
5
|
+
* counters on it, and its lines used to hand that document to the logger. The document
|
|
6
|
+
* carries `api.privateKey`, consent, the request IP and attribution, and a backend line
|
|
7
|
+
* lands in Cloud Logging for the whole retention window — the live logs had the private
|
|
8
|
+
* key in them ([#632](https://github.com/Omega-JS-Stack/omega/issues/632)).
|
|
9
|
+
*
|
|
10
|
+
* The promise survives the `consume` rewrite
|
|
11
|
+
* ([#647](https://github.com/Omega-JS-Stack/omega/issues/647)): the two lines that
|
|
12
|
+
* exist now — the resolve line and the count line — name the account and the counter
|
|
13
|
+
* and nothing else.
|
|
14
|
+
*
|
|
15
|
+
* Plain-node unit test (no emulator, no network): the counter authenticates through the
|
|
16
|
+
* ctx it is handed, so the document under test is the one this file supplies and the
|
|
17
|
+
* assertions read the captured log output.
|
|
18
|
+
*/
|
|
19
|
+
const assert = require('node:assert');
|
|
20
|
+
|
|
21
|
+
const Usage = require('../../dist/manager/helpers/usage.js');
|
|
22
|
+
const defineCases = require('../../dist/vendor/devkit/test/define-cases.js');
|
|
23
|
+
|
|
24
|
+
// The leak fixture: a user document shaped the way ctx.authenticate() resolves one.
|
|
25
|
+
const LEAKED_KEY = 'sk_test_fake_leak';
|
|
26
|
+
const UID = 'user-632';
|
|
27
|
+
const USER_DOC = {
|
|
28
|
+
auth: { uid: UID, email: 'user@test.dev' },
|
|
29
|
+
api: { clientId: 'client-632', privateKey: LEAKED_KEY },
|
|
30
|
+
consent: { marketing: { status: 'granted', ip: '203.0.113.7' } },
|
|
31
|
+
attribution: { source: 'newsletter' },
|
|
32
|
+
subscription: { product: { id: 'basic' }, status: 'active' },
|
|
33
|
+
usage: { requests: { total: 10, monthly: 4, daily: 2 } },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** One counter lifecycle: attach, consume — and every line it wrote. */
|
|
37
|
+
async function captureUsage() {
|
|
38
|
+
const captured = [];
|
|
39
|
+
const record = (...args) => captured.push(args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' '));
|
|
40
|
+
|
|
41
|
+
const Manager = {
|
|
42
|
+
config: {
|
|
43
|
+
features: { requests: { name: 'API Requests', usage: { pace: false } } },
|
|
44
|
+
payment: { products: [{ id: 'basic', features: { requests: 100 } }] },
|
|
45
|
+
},
|
|
46
|
+
storage: () => ({ get: () => ({ value: () => ({}) }), set: () => ({ write: () => {} }) }),
|
|
47
|
+
libraries: {},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const ctx = {
|
|
51
|
+
log: record,
|
|
52
|
+
warn: record,
|
|
53
|
+
error: record,
|
|
54
|
+
isDevelopment: () => true,
|
|
55
|
+
report: (e, opts) => {
|
|
56
|
+
const error = e instanceof Error ? e : new Error(e);
|
|
57
|
+
error.code = (opts || {}).code || 500;
|
|
58
|
+
return error;
|
|
59
|
+
},
|
|
60
|
+
authenticate: async () => JSON.parse(JSON.stringify(USER_DOC)),
|
|
61
|
+
request: { data: {}, geolocation: { ip: '203.0.113.7' } },
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const usage = new Usage(Manager);
|
|
65
|
+
|
|
66
|
+
usage.attach(ctx, { log: true });
|
|
67
|
+
|
|
68
|
+
// The write is the one thing that would need Firestore — the LINES are the subject
|
|
69
|
+
usage.write = async () => {};
|
|
70
|
+
|
|
71
|
+
await usage.consume('requests', 1);
|
|
72
|
+
|
|
73
|
+
return { captured, usage };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let run;
|
|
77
|
+
const usageRun = () => (run = run || captureUsage());
|
|
78
|
+
|
|
79
|
+
module.exports = defineCases({
|
|
80
|
+
description: 'Usage log privacy (counters named, the user document never serialized)',
|
|
81
|
+
type: 'group',
|
|
82
|
+
tests: [
|
|
83
|
+
{
|
|
84
|
+
name: 'resolve() line names the user and its usage, not the document',
|
|
85
|
+
|
|
86
|
+
async run() {
|
|
87
|
+
const { captured } = await usageRun();
|
|
88
|
+
const line = captured.find((l) => l.includes('Usage.resolve(): Resolved'));
|
|
89
|
+
|
|
90
|
+
assert.ok(line, `no Usage.resolve() line was logged: ${JSON.stringify(captured)}`);
|
|
91
|
+
assert.ok(line.includes(UID), `line does not name the user: ${line}`);
|
|
92
|
+
assert.ok(line.includes('"monthly":4'), `line lost the usage it is about: ${line}`);
|
|
93
|
+
assert.ok(!line.includes('privateKey'), `user document serialized into the log line: ${line}`);
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
{
|
|
98
|
+
name: 'count() line names the feature and its new value',
|
|
99
|
+
|
|
100
|
+
async run() {
|
|
101
|
+
const { captured } = await usageRun();
|
|
102
|
+
const line = captured.find((l) => l.includes('Counted 1 requests'));
|
|
103
|
+
|
|
104
|
+
assert.ok(line, `no count line was logged: ${JSON.stringify(captured)}`);
|
|
105
|
+
assert.ok(line.includes('"monthly":5'), `line lost the counted value: ${line}`);
|
|
106
|
+
assert.ok(!line.includes('privateKey'), `user document serialized into the log line: ${line}`);
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
name: 'no line of the whole lifecycle carries the private key',
|
|
112
|
+
|
|
113
|
+
async run() {
|
|
114
|
+
const { captured } = await usageRun();
|
|
115
|
+
const leaking = captured.filter((l) => l.includes(LEAKED_KEY) || l.includes('privateKey'));
|
|
116
|
+
|
|
117
|
+
assert.deepEqual(leaking, [], `private key reached the log: ${JSON.stringify(leaking)}`);
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
});
|
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test: a missing user doc heals at sign-in
|
|
3
|
+
* ([#405](https://github.com/Omega-JS-Stack/omega/issues/405)).
|
|
4
|
+
*
|
|
5
|
+
* A user doc is born at signup. Nothing recreated it when it went missing, so an
|
|
6
|
+
* auth user whose `users/{uid}` disappeared stayed unauthenticated on every
|
|
7
|
+
* request forever. The heal sits in authenticate()'s token lane — the one seam
|
|
8
|
+
* every signed-in surface passes through — and recreates the doc auth:on-create
|
|
9
|
+
* would have written, behind the auth record and nothing else.
|
|
10
|
+
*
|
|
11
|
+
* Real everything: real Firebase Auth users in the emulator, real ID tokens
|
|
12
|
+
* (custom token → the emulator's own identitytoolkit endpoint, exactly how a
|
|
13
|
+
* browser gets one), the real RouteContext, the real on-create and before-signin
|
|
14
|
+
* handlers, and the real HTTP surface for the wiring. Broken states are BUILT
|
|
15
|
+
* here — an established account whose doc is deleted — because that is the state
|
|
16
|
+
* the wild produces, and the accounts are IMPORTED so their creationTime is a
|
|
17
|
+
* real one the signup window can be tested on both sides of.
|
|
18
|
+
*
|
|
19
|
+
* Run: npx omega test framework:helpers/user-doc-heal
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const onCreate = require('../../dist/manager/events/auth/on-create.js');
|
|
23
|
+
const beforeSignIn = require('../../dist/manager/events/auth/before-signin.js');
|
|
24
|
+
const { buildUserDoc, healUserDoc, HEAL_TAG } = require('../../dist/manager/libraries/user-doc.js');
|
|
25
|
+
const defineCases = require('../../dist/vendor/devkit/test/define-cases.js');
|
|
26
|
+
|
|
27
|
+
// The 1st-gen EventContext shape for a user creation — what the trigger hands the
|
|
28
|
+
// handler, forwarded straight to its debug line and the consumer hook.
|
|
29
|
+
const EVENT_CONTEXT = {
|
|
30
|
+
eventType: 'providers/firebase.auth/eventTypes/user.create',
|
|
31
|
+
resource: { service: 'firebaseauth.googleapis.com' },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// The AuthEventContext a blocking sign-in handler receives — it writes the caller's
|
|
35
|
+
// ip/agent/locale onto the doc as activity.
|
|
36
|
+
const SIGNIN_CONTEXT = {
|
|
37
|
+
ipAddress: '203.0.113.10',
|
|
38
|
+
userAgent: 'omega-heal-suite',
|
|
39
|
+
locale: 'en-US',
|
|
40
|
+
eventType: 'providers/cloud.auth/eventTypes/user.beforeSignIn',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A REAL ID token for a uid, the way a browser sign-in gets one: a custom token
|
|
45
|
+
* from the admin SDK, exchanged for an ID token at the auth emulator's own
|
|
46
|
+
* identitytoolkit endpoint. The token authenticate() verifies is the one Firebase
|
|
47
|
+
* Auth issued, not a hand-built JWT.
|
|
48
|
+
*/
|
|
49
|
+
async function mintIdToken(Manager, uid) {
|
|
50
|
+
const authHost = process.env.FIREBASE_AUTH_EMULATOR_HOST;
|
|
51
|
+
|
|
52
|
+
if (!authHost) {
|
|
53
|
+
throw new Error('FIREBASE_AUTH_EMULATOR_HOST is unset — this suite needs the auth emulator');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const customToken = await Manager.libraries.admin.auth().createCustomToken(uid);
|
|
57
|
+
const response = await fetch(`http://${authHost}/identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=fake-api-key`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { 'Content-Type': 'application/json' },
|
|
60
|
+
body: JSON.stringify({ token: customToken, returnSecureToken: true }),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const body = await response.json();
|
|
64
|
+
|
|
65
|
+
if (!body.idToken) {
|
|
66
|
+
throw new Error(`the auth emulator refused the custom token: ${JSON.stringify(body)}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return body.idToken;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// A context carrying the token the way a request does — the Authorization header
|
|
73
|
+
// authenticate() reads.
|
|
74
|
+
function contextFor(Manager, idToken) {
|
|
75
|
+
return Manager.RouteContext({
|
|
76
|
+
req: { headers: { authorization: `Bearer ${idToken}` } },
|
|
77
|
+
}, { functionName: 'omega_api' });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Every leaf path in a doc, sorted: the SHAPE, free of the values that differ
|
|
81
|
+
// between two builds of the same record (api keys, uuids, timestamps).
|
|
82
|
+
function shapeOf(value, prefix) {
|
|
83
|
+
prefix = prefix || '';
|
|
84
|
+
|
|
85
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
86
|
+
return [prefix];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return Object.keys(value)
|
|
90
|
+
.flatMap((key) => shapeOf(value[key], prefix ? `${prefix}.${key}` : key))
|
|
91
|
+
.sort();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The broken state this whole issue is about: a real account, established long
|
|
96
|
+
* ago, with no user doc.
|
|
97
|
+
*
|
|
98
|
+
* Imported rather than created, for the two things the heal reads off the record:
|
|
99
|
+
* a creationTime OUTSIDE the signup window (a brand-new account is on-create's,
|
|
100
|
+
* not the heal's) and real federated providerData (an anonymous account gets no
|
|
101
|
+
* doc anywhere). Auth's import path fires no user-creation trigger either, so
|
|
102
|
+
* nothing races the heal into writing a doc of its own.
|
|
103
|
+
*/
|
|
104
|
+
async function agedAuthUser(Manager, uid, options) {
|
|
105
|
+
options = options || {};
|
|
106
|
+
|
|
107
|
+
const admin = Manager.libraries.admin;
|
|
108
|
+
const email = `${uid}@example.com`;
|
|
109
|
+
const ageMs = typeof options.ageMs === 'number' ? options.ageMs : 30 * 24 * 60 * 60 * 1000;
|
|
110
|
+
const created = new Date(Date.now() - ageMs);
|
|
111
|
+
|
|
112
|
+
await admin.auth().deleteUser(uid).catch(() => {});
|
|
113
|
+
|
|
114
|
+
const result = await admin.auth().importUsers([{
|
|
115
|
+
uid: uid,
|
|
116
|
+
email: email,
|
|
117
|
+
displayName: 'Aged Persona',
|
|
118
|
+
metadata: { creationTime: created.toUTCString(), lastSignInTime: created.toUTCString() },
|
|
119
|
+
providerData: options.anonymous ? [] : [{
|
|
120
|
+
uid: email,
|
|
121
|
+
email: email,
|
|
122
|
+
displayName: 'Aged Persona',
|
|
123
|
+
providerId: 'google.com',
|
|
124
|
+
}],
|
|
125
|
+
}]);
|
|
126
|
+
|
|
127
|
+
if (result.failureCount) {
|
|
128
|
+
throw new Error(`importUsers refused ${uid}: ${JSON.stringify(result.errors)}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await admin.firestore().doc(`users/${uid}`).delete();
|
|
132
|
+
|
|
133
|
+
return admin.auth().getUser(uid);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// An account created RIGHT NOW, with its doc still to come: the signup window the
|
|
137
|
+
// heal stands down inside. Imported so the trigger stays out of the test's way —
|
|
138
|
+
// this suite drives the on-create handler itself.
|
|
139
|
+
async function freshAuthUser(Manager, uid) {
|
|
140
|
+
return agedAuthUser(Manager, uid, { ageMs: 0 });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// The real auth:on-create handler, run on a real Auth record — how this suite
|
|
144
|
+
// gets the doc a signup writes without waiting on trigger timing.
|
|
145
|
+
async function runOnCreate(Manager, authUser) {
|
|
146
|
+
return onCreate({
|
|
147
|
+
Manager: Manager,
|
|
148
|
+
ctx: Manager.RouteContext({}, { functionName: 'omega_authOnCreate' }),
|
|
149
|
+
user: authUser,
|
|
150
|
+
context: EVENT_CONTEXT,
|
|
151
|
+
libraries: { admin: Manager.libraries.admin },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Leave nothing behind: the auth user goes (its on-delete takes the doc), then
|
|
156
|
+
// the doc itself in case the account never had a trigger to fire.
|
|
157
|
+
async function cleanup(Manager, uid) {
|
|
158
|
+
const admin = Manager.libraries.admin;
|
|
159
|
+
|
|
160
|
+
await admin.auth().deleteUser(uid).catch(() => {});
|
|
161
|
+
await admin.firestore().doc(`users/${uid}`).delete().catch(() => {});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = defineCases({
|
|
165
|
+
description: 'a missing user doc heals at sign-in (idempotent, order-proof)',
|
|
166
|
+
type: 'group',
|
|
167
|
+
timeout: 60000,
|
|
168
|
+
|
|
169
|
+
tests: [
|
|
170
|
+
{
|
|
171
|
+
name: 'a-signed-in-user-with-a-doc-is-never-rewritten',
|
|
172
|
+
run: async ({ assert, Manager, accounts, firestore }) => {
|
|
173
|
+
const uid = accounts.basic.uid;
|
|
174
|
+
const idToken = await mintIdToken(Manager, uid);
|
|
175
|
+
|
|
176
|
+
// Snapshot AFTER the sign-in that minted the token — the pin is on the
|
|
177
|
+
// authentication, not on what a sign-in itself is entitled to update.
|
|
178
|
+
const before = await firestore.get(`users/${uid}`);
|
|
179
|
+
|
|
180
|
+
assert.ok(before?.auth?.uid, `precondition: users/${uid} should already exist`);
|
|
181
|
+
|
|
182
|
+
const ctx = contextFor(Manager, idToken);
|
|
183
|
+
const user = await ctx.authenticate();
|
|
184
|
+
|
|
185
|
+
assert.equal(user.authenticated, true, 'a persona with a doc authenticates');
|
|
186
|
+
assert.equal(user.auth.uid, uid, 'the authenticated uid is the token subject');
|
|
187
|
+
|
|
188
|
+
const after = await firestore.get(`users/${uid}`);
|
|
189
|
+
|
|
190
|
+
assert.deepEqual(after, before, 'authenticating a user who HAS a doc must write nothing');
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
{
|
|
195
|
+
name: 'a-missing-doc-is-recreated-at-signin',
|
|
196
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
197
|
+
const uid = '_test-heal-missing-doc';
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const authUser = await agedAuthUser(Manager, uid);
|
|
201
|
+
const idToken = await mintIdToken(Manager, uid);
|
|
202
|
+
|
|
203
|
+
assert.equal(await firestore.get(`users/${uid}`), null, 'precondition: the doc is missing');
|
|
204
|
+
|
|
205
|
+
const ctx = contextFor(Manager, idToken);
|
|
206
|
+
const user = await ctx.authenticate();
|
|
207
|
+
|
|
208
|
+
assert.equal(user.authenticated, true, 'the healed caller authenticates on the same request');
|
|
209
|
+
|
|
210
|
+
const healed = await firestore.get(`users/${uid}`);
|
|
211
|
+
|
|
212
|
+
assert.ok(healed, 'the doc exists again');
|
|
213
|
+
assert.equal(healed.auth.uid, uid, 'the doc carries its uid');
|
|
214
|
+
assert.equal(healed.auth.email, authUser.email, 'the doc carries the Auth email');
|
|
215
|
+
assert.ok(healed.api?.privateKey, 'the doc carries a generated api key, like a signup doc');
|
|
216
|
+
assert.equal(healed.metadata.tag, HEAL_TAG, 'the doc says out loud that it was healed');
|
|
217
|
+
|
|
218
|
+
// An account this old signed up long ago: re-running the signup flow at
|
|
219
|
+
// it (welcome emails, affiliate credit, marketing sync) is not a heal
|
|
220
|
+
assert.equal(healed.flags.signupProcessed, true, 'a healed account is not sent back through signup');
|
|
221
|
+
|
|
222
|
+
// The shape is auth:on-create's, not a second hand-rolled one
|
|
223
|
+
const born = buildUserDoc({ Manager: Manager, user: authUser, tag: 'auth:on-create' });
|
|
224
|
+
|
|
225
|
+
assert.deepEqual(shapeOf(healed), shapeOf(born), 'the healed doc has the shape a signup writes');
|
|
226
|
+
assert.deepEqual(healed.metadata.created, born.metadata.created, 'metadata.created comes from the Auth record');
|
|
227
|
+
} finally {
|
|
228
|
+
await cleanup(Manager, uid);
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
{
|
|
234
|
+
name: 'the-doc-a-signin-leaves-behind-is-healed-not-trusted',
|
|
235
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
236
|
+
const uid = '_test-heal-signin-residue';
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
const authUser = await agedAuthUser(Manager, uid);
|
|
240
|
+
const idToken = await mintIdToken(Manager, uid);
|
|
241
|
+
|
|
242
|
+
// The REAL blocking handler every sign-in runs through: it merge-writes
|
|
243
|
+
// activity onto users/{uid}, so a doc-less account reaches authenticate()
|
|
244
|
+
// carrying a doc that is not an account.
|
|
245
|
+
await beforeSignIn({
|
|
246
|
+
Manager: Manager,
|
|
247
|
+
ctx: Manager.RouteContext({}, { functionName: 'omega_authBeforeSignIn' }),
|
|
248
|
+
user: authUser,
|
|
249
|
+
context: SIGNIN_CONTEXT,
|
|
250
|
+
libraries: { admin: Manager.libraries.admin },
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const residue = await firestore.get(`users/${uid}`);
|
|
254
|
+
|
|
255
|
+
assert.ok(residue, 'precondition: the sign-in left a doc');
|
|
256
|
+
assert.equal(residue.auth, undefined, 'precondition: that doc is not an account');
|
|
257
|
+
|
|
258
|
+
const user = await contextFor(Manager, idToken).authenticate();
|
|
259
|
+
|
|
260
|
+
assert.equal(user.authenticated, true, 'a caller whose doc is nothing but sign-in residue is healed and authenticated');
|
|
261
|
+
|
|
262
|
+
const healed = await firestore.get(`users/${uid}`);
|
|
263
|
+
|
|
264
|
+
assert.equal(healed.auth.uid, uid, 'the residue is healed into a real account doc');
|
|
265
|
+
assert.equal(healed.activity.geolocation.ip, SIGNIN_CONTEXT.ipAddress, 'the heal keeps what the sign-in already wrote');
|
|
266
|
+
assert.ok(healed.api?.privateKey, 'the account gets the api keys it never had');
|
|
267
|
+
} finally {
|
|
268
|
+
await cleanup(Manager, uid);
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
{
|
|
274
|
+
name: 'on-create-then-heal-converges-without-clobbering',
|
|
275
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
276
|
+
const uid = '_test-heal-race-create-first';
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
await runOnCreate(Manager, await agedAuthUser(Manager, uid));
|
|
280
|
+
|
|
281
|
+
// Age the doc the way the live database ages one: a leaf the schema
|
|
282
|
+
// gained after this account signed up. Reshaping those is the manual
|
|
283
|
+
// users migration's job alone — a heal that finds a real doc must leave
|
|
284
|
+
// it exactly as it is, drift included.
|
|
285
|
+
const admin = Manager.libraries.admin;
|
|
286
|
+
|
|
287
|
+
await admin.firestore().doc(`users/${uid}`)
|
|
288
|
+
.update({ 'subscription.trial.claimed': admin.firestore.FieldValue.delete() });
|
|
289
|
+
|
|
290
|
+
const born = await firestore.get(`users/${uid}`);
|
|
291
|
+
|
|
292
|
+
assert.equal(born.metadata.tag, 'auth:on-create', 'precondition: on-create wrote the doc');
|
|
293
|
+
assert.equal(born.subscription.trial.claimed, undefined, 'precondition: the doc is missing a schema leaf');
|
|
294
|
+
|
|
295
|
+
const ctx = Manager.RouteContext({}, { functionName: 'omega_api' });
|
|
296
|
+
const returned = await healUserDoc({
|
|
297
|
+
Manager: Manager,
|
|
298
|
+
ctx: ctx,
|
|
299
|
+
admin: Manager.libraries.admin,
|
|
300
|
+
uid: uid,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const after = await firestore.get(`users/${uid}`);
|
|
304
|
+
|
|
305
|
+
assert.deepEqual(after, born, 'a heal arriving second must leave on-create\'s doc exactly as it is');
|
|
306
|
+
assert.equal(returned.api.privateKey, born.api.privateKey, 'the heal reports the doc that survived');
|
|
307
|
+
assert.equal(after.metadata.tag, 'auth:on-create', 'the tag still names the seam that created it');
|
|
308
|
+
} finally {
|
|
309
|
+
await cleanup(Manager, uid);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
{
|
|
315
|
+
name: 'heal-then-on-create-converges-without-duplicating',
|
|
316
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
317
|
+
const uid = '_test-heal-race-heal-first';
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
// An established account whose doc went missing, healed first
|
|
321
|
+
const authUser = await agedAuthUser(Manager, uid);
|
|
322
|
+
const ctx = Manager.RouteContext({}, { functionName: 'omega_api' });
|
|
323
|
+
|
|
324
|
+
await healUserDoc({
|
|
325
|
+
Manager: Manager,
|
|
326
|
+
ctx: ctx,
|
|
327
|
+
admin: Manager.libraries.admin,
|
|
328
|
+
uid: uid,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
const healed = await firestore.get(`users/${uid}`);
|
|
332
|
+
|
|
333
|
+
assert.equal(healed.metadata.tag, HEAL_TAG, 'precondition: the heal wrote the doc');
|
|
334
|
+
|
|
335
|
+
// The trigger arrives afterward with the REAL Auth record it fires on
|
|
336
|
+
await runOnCreate(Manager, authUser);
|
|
337
|
+
|
|
338
|
+
const after = await firestore.get(`users/${uid}`);
|
|
339
|
+
|
|
340
|
+
assert.deepEqual(after, healed, 'on-create arriving second must skip the doc the heal wrote');
|
|
341
|
+
assert.equal(after.api.privateKey, healed.api.privateKey, 'no second set of api keys was minted');
|
|
342
|
+
} finally {
|
|
343
|
+
await cleanup(Manager, uid);
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
{
|
|
349
|
+
name: 'a-healed-account-can-make-an-authenticated-request-immediately',
|
|
350
|
+
run: async ({ assert, Manager, http, firestore }) => {
|
|
351
|
+
const uid = '_test-heal-authenticated-request';
|
|
352
|
+
|
|
353
|
+
try {
|
|
354
|
+
await agedAuthUser(Manager, uid);
|
|
355
|
+
const idToken = await mintIdToken(Manager, uid);
|
|
356
|
+
|
|
357
|
+
assert.equal(await firestore.get(`users/${uid}`), null, 'precondition: the doc is missing');
|
|
358
|
+
|
|
359
|
+
http.setAuth('bearer', { token: idToken });
|
|
360
|
+
|
|
361
|
+
// The route is a normal authenticated read — the heal happens inside the
|
|
362
|
+
// request that would previously have answered 401
|
|
363
|
+
const first = await http.get('backend-manager/user/subscription', {});
|
|
364
|
+
|
|
365
|
+
assert.isSuccess(first, 'the request that healed the account also succeeds');
|
|
366
|
+
assert.hasProperty(first, 'data.subscription', 'the account answers with its subscription');
|
|
367
|
+
assert.ok(await firestore.get(`users/${uid}`), 'the doc exists after the request');
|
|
368
|
+
|
|
369
|
+
const second = await http.get('backend-manager/user/subscription', {});
|
|
370
|
+
|
|
371
|
+
assert.isSuccess(second, 'the next request succeeds too, healing nothing');
|
|
372
|
+
assert.equal((await firestore.get(`users/${uid}`)).metadata.tag, HEAL_TAG, 'the second request wrote no new doc');
|
|
373
|
+
} finally {
|
|
374
|
+
await cleanup(Manager, uid);
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
|
|
379
|
+
{
|
|
380
|
+
name: 'a-token-whose-account-is-gone-is-never-healed',
|
|
381
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
382
|
+
const uid = '_test-heal-deleted-account';
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
await agedAuthUser(Manager, uid);
|
|
386
|
+
const idToken = await mintIdToken(Manager, uid);
|
|
387
|
+
|
|
388
|
+
// The account goes away while its token is still inside its hour
|
|
389
|
+
await Manager.libraries.admin.auth().deleteUser(uid);
|
|
390
|
+
|
|
391
|
+
const ctx = contextFor(Manager, idToken);
|
|
392
|
+
const user = await ctx.authenticate();
|
|
393
|
+
|
|
394
|
+
assert.equal(user.authenticated, false, 'a deleted account does not authenticate');
|
|
395
|
+
assert.equal(await firestore.get(`users/${uid}`), null, 'the heal must never mint a doc with no auth user behind it');
|
|
396
|
+
} finally {
|
|
397
|
+
await cleanup(Manager, uid);
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
|
|
402
|
+
{
|
|
403
|
+
name: 'the-heal-refuses-a-uid-with-no-auth-user',
|
|
404
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
405
|
+
// The seam above cannot reach the heal for a deleted account — the
|
|
406
|
+
// emulator's verifyIdToken refuses the token first. The guard itself is
|
|
407
|
+
// what keeps the auth-less doc #399 refuses from being minted here, so it
|
|
408
|
+
// is pinned directly: no auth user, no doc, ever.
|
|
409
|
+
const uid = '_test-heal-no-auth-user';
|
|
410
|
+
|
|
411
|
+
try {
|
|
412
|
+
await Manager.libraries.admin.firestore().doc(`users/${uid}`).delete();
|
|
413
|
+
|
|
414
|
+
const ctx = Manager.RouteContext({}, { functionName: 'omega_api' });
|
|
415
|
+
const healed = await healUserDoc({
|
|
416
|
+
Manager: Manager,
|
|
417
|
+
ctx: ctx,
|
|
418
|
+
admin: Manager.libraries.admin,
|
|
419
|
+
uid: uid,
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
assert.equal(healed, null, 'the heal reports nothing to heal');
|
|
423
|
+
assert.equal(await firestore.get(`users/${uid}`), null, 'no doc is written for a uid this project never authenticated');
|
|
424
|
+
} finally {
|
|
425
|
+
await cleanup(Manager, uid);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
{
|
|
431
|
+
name: 'a-signup-still-in-flight-is-left-to-on-create',
|
|
432
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
433
|
+
// The interleaving that made this window necessary: a brand-new account
|
|
434
|
+
// makes an authenticated request BEFORE auth:on-create has run. A heal
|
|
435
|
+
// there would write the doc, and on-create's own "already exists" check
|
|
436
|
+
// would then skip the account for good — no consumer hook, ever, and an
|
|
437
|
+
// ordinary signup logged as out of sync.
|
|
438
|
+
const uid = '_test-heal-signup-in-flight';
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
const authUser = await freshAuthUser(Manager, uid);
|
|
442
|
+
const age = Date.now() - new Date(authUser.metadata?.creationTime || 0).getTime();
|
|
443
|
+
|
|
444
|
+
assert.ok(age < 120000, `precondition: the record should be brand new, Auth says ${authUser.metadata?.creationTime} (${Math.round(age / 1000)}s old)`);
|
|
445
|
+
|
|
446
|
+
const ctx = Manager.RouteContext({}, { functionName: 'omega_api' });
|
|
447
|
+
|
|
448
|
+
const healed = await healUserDoc({
|
|
449
|
+
Manager: Manager,
|
|
450
|
+
ctx: ctx,
|
|
451
|
+
admin: Manager.libraries.admin,
|
|
452
|
+
uid: uid,
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
assert.equal(healed, null, 'the heal stands down inside the signup window');
|
|
456
|
+
assert.equal(await firestore.get(`users/${uid}`), null, 'the doc is still on-create\'s to write');
|
|
457
|
+
|
|
458
|
+
// on-create arrives and does its FULL job, early return untaken
|
|
459
|
+
await runOnCreate(Manager, authUser);
|
|
460
|
+
|
|
461
|
+
const born = await firestore.get(`users/${uid}`);
|
|
462
|
+
|
|
463
|
+
assert.equal(born.metadata.tag, 'auth:on-create', 'the signup doc is on-create\'s, tag and all');
|
|
464
|
+
assert.equal(born.flags.signupProcessed, false, 'a real new signup still has its signup flow ahead of it');
|
|
465
|
+
} finally {
|
|
466
|
+
await cleanup(Manager, uid);
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
|
|
471
|
+
{
|
|
472
|
+
name: 'a-signup-window-caller-with-residue-still-authenticates',
|
|
473
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
474
|
+
// The stand-down must not cost a caller the answer they used to get. A
|
|
475
|
+
// signup still in flight has a doc holding nothing but before-signin's
|
|
476
|
+
// activity, and that doc authenticated its caller before the heal existed
|
|
477
|
+
// — /user/signup itself arrives this way, and its 30s poll for the doc is
|
|
478
|
+
// behind that authentication.
|
|
479
|
+
const uid = '_test-heal-window-residue';
|
|
480
|
+
|
|
481
|
+
try {
|
|
482
|
+
const authUser = await freshAuthUser(Manager, uid);
|
|
483
|
+
const idToken = await mintIdToken(Manager, uid);
|
|
484
|
+
|
|
485
|
+
await beforeSignIn({
|
|
486
|
+
Manager: Manager,
|
|
487
|
+
ctx: Manager.RouteContext({}, { functionName: 'omega_authBeforeSignIn' }),
|
|
488
|
+
user: authUser,
|
|
489
|
+
context: SIGNIN_CONTEXT,
|
|
490
|
+
libraries: { admin: Manager.libraries.admin },
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
const residue = await firestore.get(`users/${uid}`);
|
|
494
|
+
|
|
495
|
+
assert.ok(residue, 'precondition: the sign-in left a doc');
|
|
496
|
+
assert.equal(residue.auth, undefined, 'precondition: that doc is not an account yet');
|
|
497
|
+
|
|
498
|
+
const user = await contextFor(Manager, idToken).authenticate();
|
|
499
|
+
|
|
500
|
+
assert.equal(user.authenticated, true, 'a signup in flight authenticates on its residue, exactly as it did before the heal existed');
|
|
501
|
+
|
|
502
|
+
const after = await firestore.get(`users/${uid}`);
|
|
503
|
+
|
|
504
|
+
assert.equal(after.auth, undefined, 'the heal still wrote nothing inside the window');
|
|
505
|
+
assert.equal(after.metadata.tag, undefined, 'nothing tagged this doc a heal');
|
|
506
|
+
} finally {
|
|
507
|
+
await cleanup(Manager, uid);
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
|
|
512
|
+
{
|
|
513
|
+
name: 'an-anonymous-account-is-never-given-a-doc',
|
|
514
|
+
run: async ({ assert, Manager, firestore }) => {
|
|
515
|
+
// Anonymous accounts get no user doc anywhere in the framework — the heal
|
|
516
|
+
// reads the record the same way auth:on-create does.
|
|
517
|
+
const uid = '_test-heal-anonymous';
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
const authUser = await agedAuthUser(Manager, uid, { anonymous: true });
|
|
521
|
+
|
|
522
|
+
assert.deepEqual(authUser.providerData, [], 'precondition: the record has no provider behind it');
|
|
523
|
+
|
|
524
|
+
const ctx = Manager.RouteContext({}, { functionName: 'omega_api' });
|
|
525
|
+
const healed = await healUserDoc({
|
|
526
|
+
Manager: Manager,
|
|
527
|
+
ctx: ctx,
|
|
528
|
+
admin: Manager.libraries.admin,
|
|
529
|
+
uid: uid,
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
assert.equal(healed, null, 'the heal refuses an anonymous account');
|
|
533
|
+
assert.equal(await firestore.get(`users/${uid}`), null, 'no doc is written for one');
|
|
534
|
+
} finally {
|
|
535
|
+
await cleanup(Manager, uid);
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
],
|
|
540
|
+
});
|