@runeditrun/rer 0.0.0-stage → 0.1.1
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 +21 -0
- package/README.md +157 -2
- package/bin/rer.mjs +3 -0
- package/cli/README.md +243 -0
- package/cli/adapter.mjs +10 -0
- package/cli/ai-local.mjs +65 -0
- package/cli/archive-path.mjs +52 -0
- package/cli/archive-vite.mjs +55 -0
- package/cli/archive.mjs +8 -0
- package/cli/auth-copy.mjs +80 -0
- package/cli/bounded.mjs +70 -0
- package/cli/cache-doctor.mjs +63 -0
- package/cli/container-transfer.mjs +35 -0
- package/cli/container.mjs +62 -0
- package/cli/contract.mjs +25 -0
- package/cli/dependencies.mjs +45 -0
- package/cli/dependency-approval.mjs +33 -0
- package/cli/dependency-doctor.mjs +34 -0
- package/cli/dependency-input.mjs +43 -0
- package/cli/deploy-config.mjs +118 -0
- package/cli/deploy.mjs +37 -0
- package/cli/dev-identity.mjs +80 -0
- package/cli/errors.mjs +14 -0
- package/cli/export.mjs +42 -0
- package/cli/font-cache.mjs +29 -0
- package/cli/hosted-output.mjs +110 -0
- package/cli/independent.mjs +29 -0
- package/cli/inspect.mjs +174 -0
- package/cli/jsonc.mjs +111 -0
- package/cli/lifecycle.mjs +148 -0
- package/cli/local.mjs +100 -0
- package/cli/main.mjs +57 -0
- package/cli/managed-server.mjs +143 -0
- package/cli/node-runtime-cache.mjs +68 -0
- package/cli/node-runtime-discovery.mjs +56 -0
- package/cli/node-runtime-download.mjs +59 -0
- package/cli/node-runtime.mjs +50 -0
- package/cli/output.mjs +22 -0
- package/cli/parse.mjs +77 -0
- package/cli/port.mjs +52 -0
- package/cli/portability-worker.mjs +56 -0
- package/cli/portability.mjs +66 -0
- package/cli/preview-cache.mjs +99 -0
- package/cli/project.mjs +48 -0
- package/cli/release.mjs +24 -0
- package/cli/runtime-front-door.mjs +46 -0
- package/cli/scheduled.mjs +81 -0
- package/cli/server-activity.mjs +12 -0
- package/cli/server-proxy.mjs +93 -0
- package/cli/server-registry.mjs +182 -0
- package/cli/server-resources.mjs +22 -0
- package/cli/settings.mjs +15 -0
- package/cli/setup-answers.mjs +29 -0
- package/cli/setup-input.mjs +113 -0
- package/cli/shared.mjs +7 -0
- package/cli/transfers.mjs +33 -0
- package/cli/version.mjs +36 -0
- package/composition/git-source.mjs +111 -0
- package/edition-authoring/files.mjs +81 -0
- package/edition-authoring/manifest.mjs +65 -0
- package/global/README.md +158 -0
- package/global/checkout.mjs +72 -0
- package/global/cli/command.mjs +13 -0
- package/global/cli/install.mjs +75 -0
- package/global/cli/layout.mjs +45 -0
- package/global/cli/status.mjs +54 -0
- package/global/cli/uninstall.mjs +36 -0
- package/global/delegate.mjs +13 -0
- package/global/launch/capacity.mjs +72 -0
- package/global/launch/dev.mjs +117 -0
- package/global/launch/facts.mjs +94 -0
- package/global/launch/failure.mjs +5 -0
- package/global/launch/local-defaults.mjs +4 -0
- package/global/launch/prepare.mjs +63 -0
- package/global/launch/render.mjs +44 -0
- package/global/launch/state.mjs +106 -0
- package/global/launch/steps.mjs +90 -0
- package/global/launch/stop.mjs +89 -0
- package/global/launch/worker.mjs +62 -0
- package/global/list.mjs +59 -0
- package/global/main.mjs +53 -0
- package/global/package-info.mjs +38 -0
- package/global/registry.mjs +24 -0
- package/global/rer.mjs +29 -0
- package/global/update/archive.mjs +89 -0
- package/global/update/command.mjs +90 -0
- package/global/update/latest.mjs +6 -0
- package/global/update/notice.mjs +58 -0
- package/global/update/registry.mjs +47 -0
- package/global/version.mjs +29 -0
- package/install.sh +144 -0
- package/modules/ai/LICENSE +21 -0
- package/modules/ai/README.md +90 -0
- package/modules/ai/client.mjs +71 -0
- package/modules/ai/config.mjs +39 -0
- package/modules/ai/dev/index.d.mts +6 -0
- package/modules/ai/dev/index.mjs +64 -0
- package/modules/ai/dev/outbox.mjs +33 -0
- package/modules/ai/errors.mjs +28 -0
- package/modules/ai/fake/index.d.mts +3 -0
- package/modules/ai/fake/index.mjs +82 -0
- package/modules/ai/index.d.mts +10 -0
- package/modules/ai/index.mjs +3 -0
- package/modules/ai/package.json +6 -0
- package/modules/container/README.md +156 -0
- package/modules/container/adapters/d1.mjs +34 -0
- package/modules/container/adapters/egress.mjs +40 -0
- package/modules/container/adapters/jobs.mjs +47 -0
- package/modules/container/adapters/objects.mjs +84 -0
- package/modules/container/adapters/retained.mjs +14 -0
- package/modules/container/adapters/sqlite-error.mjs +7 -0
- package/modules/container/adapters/sqlite-worker.mjs +26 -0
- package/modules/container/assets.mjs +14 -0
- package/modules/container/bindings.mjs +1 -0
- package/modules/container/boundary.mjs +38 -0
- package/modules/container/build.mjs +65 -0
- package/modules/container/deploy-input.mjs +17 -0
- package/modules/container/entrypoint.sh +5 -0
- package/modules/container/host.mjs +43 -0
- package/modules/container/ingress.mjs +23 -0
- package/modules/container/lock.mjs +11 -0
- package/modules/container/migrations.mjs +16 -0
- package/modules/container/node-engine.mjs +39 -0
- package/modules/container/portability-schema.mjs +14 -0
- package/modules/container/remote/deploy.py +76 -0
- package/modules/container/remote/files.py +275 -0
- package/modules/container/remote/resources.py +157 -0
- package/modules/container/runner.mjs +10 -0
- package/modules/container/ssh-plan.mjs +44 -0
- package/modules/container/ssh.mjs +63 -0
- package/modules/container/transfer.mjs +27 -0
- package/modules/container/worker-engine.mjs +32 -0
- package/modules/dependencies/README.md +211 -0
- package/modules/dependencies/approval.mjs +51 -0
- package/modules/dependencies/auth.mjs +40 -0
- package/modules/dependencies/authority.mjs +14 -0
- package/modules/dependencies/crypto.mjs +13 -0
- package/modules/dependencies/index.d.mts +23 -0
- package/modules/dependencies/index.mjs +113 -0
- package/modules/dependencies/logout.mjs +42 -0
- package/modules/dependencies/native.mjs +9 -0
- package/modules/dependencies/protocol.mjs +23 -0
- package/modules/dependencies/schema/approval-attempt.sql +3 -0
- package/modules/dependencies/schema/dependencies.sql +15 -0
- package/modules/dependencies/store.mjs +19 -0
- package/modules/deploy-kit/README.md +308 -0
- package/modules/deploy-kit/artifact.mjs +47 -0
- package/modules/deploy-kit/build-modules.mjs +21 -0
- package/modules/deploy-kit/check.mjs +13 -0
- package/modules/deploy-kit/cli.mjs +50 -0
- package/modules/deploy-kit/container-config.mjs +8 -0
- package/modules/deploy-kit/default-stage.mjs +14 -0
- package/modules/deploy-kit/deploy.mjs +80 -0
- package/modules/deploy-kit/health-request.mjs +86 -0
- package/modules/deploy-kit/health.mjs +99 -0
- package/modules/deploy-kit/index.mjs +12 -0
- package/modules/deploy-kit/local-only.mjs +10 -0
- package/modules/deploy-kit/migrations.mjs +48 -0
- package/modules/deploy-kit/owner-cli.mjs +63 -0
- package/modules/deploy-kit/owner.mjs +297 -0
- package/modules/deploy-kit/prepare.mjs +62 -0
- package/modules/deploy-kit/provider.mjs +99 -0
- package/modules/deploy-kit/queue-consumer.mjs +10 -0
- package/modules/deploy-kit/receipt.mjs +16 -0
- package/modules/deploy-kit/render.mjs +47 -0
- package/modules/deploy-kit/resources.mjs +106 -0
- package/modules/deploy-kit/service-grants.mjs +25 -0
- package/modules/deploy-kit/sql-safety.mjs +94 -0
- package/modules/deploy-kit/sql-tokens.mjs +49 -0
- package/modules/deploy-kit/teardown.mjs +100 -0
- package/modules/deploy-kit/templates.mjs +31 -0
- package/modules/deploy-kit/validation.mjs +58 -0
- package/modules/deploy-kit/worker.mjs +105 -0
- package/modules/erasure/CONTRACT.md +90 -0
- package/modules/erasure/README.md +221 -0
- package/modules/erasure/audit.mjs +23 -0
- package/modules/erasure/blobs.mjs +45 -0
- package/modules/erasure/cascade.mjs +91 -0
- package/modules/erasure/completion.mjs +62 -0
- package/modules/erasure/declaration.mjs +51 -0
- package/modules/erasure/fence.mjs +19 -0
- package/modules/erasure/index.d.mts +62 -0
- package/modules/erasure/index.mjs +85 -0
- package/modules/erasure/order.mjs +56 -0
- package/modules/erasure/plan.mjs +121 -0
- package/modules/erasure/rate.mjs +57 -0
- package/modules/erasure/receipt.mjs +32 -0
- package/modules/erasure/root.mjs +21 -0
- package/modules/erasure/schema/erasure-rates.sql +5 -0
- package/modules/erasure/schema/erasure.sql +27 -0
- package/modules/erasure/scope.mjs +29 -0
- package/modules/erasure/sql.mjs +23 -0
- package/modules/erasure/verification.mjs +69 -0
- package/modules/integrations/core/CONTRACT.md +50 -0
- package/modules/integrations/core/README.md +27 -0
- package/modules/integrations/core/crypto.ts +19 -0
- package/modules/integrations/core/database.ts +21 -0
- package/modules/integrations/core/delivery.ts +97 -0
- package/modules/integrations/core/destination.ts +13 -0
- package/modules/integrations/core/index.ts +7 -0
- package/modules/integrations/core/node-transport.ts +72 -0
- package/modules/integrations/core/public-address.ts +57 -0
- package/modules/integrations/core/repository.ts +74 -0
- package/modules/integrations/core/schema.sql +36 -0
- package/modules/integrations/core/sqlite.ts +20 -0
- package/modules/integrations/core/timestamped-body-signature.ts +38 -0
- package/modules/integrations/core/tokens.ts +71 -0
- package/modules/integrations/core/types.ts +52 -0
- package/modules/integrations/core/upgrade-token-usage-context.sql +5 -0
- package/modules/integrations/core/webhook.ts +73 -0
- package/modules/job-queue/README.md +173 -0
- package/modules/job-queue/cli.mjs +64 -0
- package/modules/job-queue/command.mjs +64 -0
- package/modules/job-queue/config.mjs +48 -0
- package/modules/job-queue/identity.mjs +48 -0
- package/modules/job-queue/index.mjs +135 -0
- package/modules/job-queue/membership.mjs +30 -0
- package/modules/job-queue/module.json +10 -0
- package/modules/job-queue/policy.mjs +29 -0
- package/modules/job-queue/processes.mjs +80 -0
- package/modules/job-queue/resources.mjs +37 -0
- package/modules/job-queue/storage.mjs +64 -0
- package/modules/job-queue/supervisor.mjs +30 -0
- package/modules/job-queue/waiting.mjs +16 -0
- package/modules/mail/LICENSE +21 -0
- package/modules/mail/README.md +336 -0
- package/modules/mail/doctor.mjs +81 -0
- package/modules/mail/index.mjs +8 -0
- package/modules/mail/live-proof/README.md +113 -0
- package/modules/mail/live-proof/run.mjs +55 -0
- package/modules/mail/package.json +19 -0
- package/modules/mail/pnpm-lock.yaml +537 -0
- package/modules/mail/src/adapters/cloudflare/README.md +84 -0
- package/modules/mail/src/adapters/cloudflare/headers.mjs +63 -0
- package/modules/mail/src/adapters/cloudflare/index.mjs +47 -0
- package/modules/mail/src/adapters/cloudflare/response.mjs +99 -0
- package/modules/mail/src/adapters/messaging/README.md +92 -0
- package/modules/mail/src/adapters/messaging/contract.mjs +66 -0
- package/modules/mail/src/adapters/messaging/event-schema.mjs +28 -0
- package/modules/mail/src/adapters/messaging/index.mjs +61 -0
- package/modules/mail/src/adapters/messaging/jws.mjs +68 -0
- package/modules/mail/src/adapters/messaging/request.mjs +52 -0
- package/modules/mail/src/adapters/messaging/serialize.mjs +21 -0
- package/modules/mail/src/adapters/resend/README.md +120 -0
- package/modules/mail/src/adapters/resend/index.mjs +22 -0
- package/modules/mail/src/adapters/resend/response.mjs +54 -0
- package/modules/mail/src/adapters/resend/serialize.mjs +46 -0
- package/modules/mail/src/adapters/resend/size.mjs +99 -0
- package/modules/mail/src/adapters/sendgrid/README.md +75 -0
- package/modules/mail/src/adapters/sendgrid/index.mjs +35 -0
- package/modules/mail/src/adapters/sendgrid/serialize.mjs +104 -0
- package/modules/mail/src/core/errors.mjs +9 -0
- package/modules/mail/src/core/transport.mjs +33 -0
- package/modules/mail/src/core/validation.mjs +172 -0
- package/modules/mail/src/development/index.d.mts +37 -0
- package/modules/mail/src/development/index.mjs +35 -0
- package/modules/mail/src/development/outbox.mjs +78 -0
- package/modules/mail/src/development/schema.sql +9 -0
- package/modules/mail/src/development/viewer-html.mjs +42 -0
- package/modules/mail/src/development/viewer.mjs +65 -0
- package/modules/mail/src/doctor/README.md +107 -0
- package/modules/mail/src/doctor/common.mjs +64 -0
- package/modules/mail/src/doctor/dns.mjs +102 -0
- package/modules/mail/src/doctor/index.mjs +28 -0
- package/modules/mail/src/doctor/probe.mjs +66 -0
- package/modules/mail/src/doctor/receive.mjs +81 -0
- package/modules/mail/src/doctor/records.mjs +45 -0
- package/modules/mail/src/events/README.md +268 -0
- package/modules/mail/src/events/d1-schema.sql +25 -0
- package/modules/mail/src/events/d1-storage.mjs +76 -0
- package/modules/mail/src/events/index.mjs +3 -0
- package/modules/mail/src/events/intake.mjs +201 -0
- package/modules/mail/src/events/storage.mjs +52 -0
- package/modules/mail/src/events/verify.mjs +92 -0
- package/modules/mail/src/inbound/README.md +137 -0
- package/modules/mail/src/inbound/bytes.mjs +91 -0
- package/modules/mail/src/inbound/headers.mjs +143 -0
- package/modules/mail/src/inbound/index.mjs +29 -0
- package/modules/mail/src/inbound/mime.mjs +36 -0
- package/modules/mail/src/inbound/multipart.mjs +27 -0
- package/modules/mail/src/inbound/resend-attachment.mjs +43 -0
- package/modules/mail/src/inbound/resend.mjs +54 -0
- package/modules/mail/src/inbound/sendgrid.mjs +60 -0
- package/modules/mail/src/sender.mjs +33 -0
- package/modules/mail/src/sendgrid-email/index.d.mts +33 -0
- package/modules/mail/src/sendgrid-email/index.mjs +86 -0
- package/modules/mail/src/unsubscribe/index.mjs +142 -0
- package/modules/operator-auth/README.md +599 -0
- package/modules/operator-auth/accounts/adapter.mjs +41 -0
- package/modules/operator-auth/accounts/admin.mjs +159 -0
- package/modules/operator-auth/accounts/credentials.mjs +27 -0
- package/modules/operator-auth/accounts/editor-owner.mjs +13 -0
- package/modules/operator-auth/accounts/index.d.mts +9 -0
- package/modules/operator-auth/accounts/index.mjs +9 -0
- package/modules/operator-auth/accounts/native.d.mts +38 -0
- package/modules/operator-auth/accounts/native.mjs +171 -0
- package/modules/operator-auth/accounts/oa.mjs +90 -0
- package/modules/operator-auth/accounts/provider-control.mjs +50 -0
- package/modules/operator-auth/accounts/provider-pin.mjs +14 -0
- package/modules/operator-auth/accounts/roles.mjs +26 -0
- package/modules/operator-auth/accounts/schema/dependency-setup.sql +17 -0
- package/modules/operator-auth/accounts/schema/dev-sessions.sql +22 -0
- package/modules/operator-auth/accounts/schema/domain-rules-step-up.sql +20 -0
- package/modules/operator-auth/accounts/schema/invitation-cancellation.sql +17 -0
- package/modules/operator-auth/accounts/schema/operator-auth.sql +142 -0
- package/modules/operator-auth/accounts/schema/provider-control.sql +30 -0
- package/modules/operator-auth/accounts/schema/provider-pins.sql +6 -0
- package/modules/operator-auth/accounts/settings-page.mjs +4 -0
- package/modules/operator-auth/accounts/store.mjs +246 -0
- package/modules/operator-auth/branding.mjs +66 -0
- package/modules/operator-auth/config.mjs +35 -0
- package/modules/operator-auth/conformance/README.md +81 -0
- package/modules/operator-auth/conformance/index.d.mts +43 -0
- package/modules/operator-auth/conformance/index.mjs +300 -0
- package/modules/operator-auth/conformance/presentation.mjs +57 -0
- package/modules/operator-auth/crypto.mjs +17 -0
- package/modules/operator-auth/dev/badge.mjs +62 -0
- package/modules/operator-auth/dev/index.d.mts +14 -0
- package/modules/operator-auth/dev/index.mjs +137 -0
- package/modules/operator-auth/dev/personas.mjs +17 -0
- package/modules/operator-auth/dev/sign-in-as.d.mts +3 -0
- package/modules/operator-auth/dev/sign-in-as.mjs +25 -0
- package/modules/operator-auth/dev-admission.d.mts +4 -0
- package/modules/operator-auth/dev-admission.mjs +10 -0
- package/modules/operator-auth/dev-gate.mjs +86 -0
- package/modules/operator-auth/docs/README.md +78 -0
- package/modules/operator-auth/docs/native-accounts.md +313 -0
- package/modules/operator-auth/docs/tanstack-start.md +218 -0
- package/modules/operator-auth/docs/vite-spa.md +144 -0
- package/modules/operator-auth/errors.mjs +9 -0
- package/modules/operator-auth/http.mjs +42 -0
- package/modules/operator-auth/identity/admission.mjs +105 -0
- package/modules/operator-auth/identity/after-confirm.mjs +18 -0
- package/modules/operator-auth/identity/email-link/confirmation.mjs +14 -0
- package/modules/operator-auth/identity/email-link/index.d.mts +48 -0
- package/modules/operator-auth/identity/email-link/index.mjs +128 -0
- package/modules/operator-auth/identity/email-link/message.mjs +16 -0
- package/modules/operator-auth/identity/index.d.mts +7 -0
- package/modules/operator-auth/identity/index.mjs +5 -0
- package/modules/operator-auth/identity/oidc/README.md +171 -0
- package/modules/operator-auth/identity/oidc/client-auth.mjs +16 -0
- package/modules/operator-auth/identity/oidc/config.mjs +102 -0
- package/modules/operator-auth/identity/oidc/crypto.mjs +29 -0
- package/modules/operator-auth/identity/oidc/errors.mjs +5 -0
- package/modules/operator-auth/identity/oidc/index.d.mts +33 -0
- package/modules/operator-auth/identity/oidc/index.mjs +287 -0
- package/modules/operator-auth/identity/oidc/jwt.mjs +102 -0
- package/modules/operator-auth/identity/oidc/network.mjs +93 -0
- package/modules/operator-auth/identity/oidc/presets.mjs +26 -0
- package/modules/operator-auth/identity/oidc/schema/oidc.sql +50 -0
- package/modules/operator-auth/identity/oidc/store.mjs +68 -0
- package/modules/operator-auth/identity/principal.mjs +28 -0
- package/modules/operator-auth/index.d.mts +223 -0
- package/modules/operator-auth/index.mjs +11 -0
- package/modules/operator-auth/input.mjs +55 -0
- package/modules/operator-auth/local-cli.mjs +16 -0
- package/modules/operator-auth/page.mjs +34 -0
- package/modules/operator-auth/policy.mjs +20 -0
- package/modules/operator-auth/routes.mjs +91 -0
- package/modules/operator-auth/service.mjs +152 -0
- package/modules/operator-auth/signin/index.mjs +67 -0
- package/modules/owner-claim/README.md +137 -0
- package/modules/owner-claim/idp.mjs +40 -0
- package/modules/owner-claim/index.d.mts +27 -0
- package/modules/owner-claim/index.mjs +39 -0
- package/modules/owner-claim/page.mjs +11 -0
- package/modules/owner-claim/schema/idp.sql +4 -0
- package/modules/owner-claim/schema/owner-claim.sql +18 -0
- package/modules/owner-claim/transaction.mjs +87 -0
- package/modules/owner-claim/verify.mjs +80 -0
- package/modules/portability/README.md +444 -0
- package/modules/portability/bridge.mjs +102 -0
- package/modules/portability/catalogue.mjs +118 -0
- package/modules/portability/cli-options.mjs +38 -0
- package/modules/portability/cli.mjs +56 -0
- package/modules/portability/copies.mjs +68 -0
- package/modules/portability/dev-data.mjs +32 -0
- package/modules/portability/diff.mjs +33 -0
- package/modules/portability/export.mjs +129 -0
- package/modules/portability/files.mjs +65 -0
- package/modules/portability/format.mjs +122 -0
- package/modules/portability/generated.mjs +60 -0
- package/modules/portability/hash.mjs +79 -0
- package/modules/portability/http.mjs +42 -0
- package/modules/portability/import.mjs +185 -0
- package/modules/portability/index.d.mts +58 -0
- package/modules/portability/index.mjs +22 -0
- package/modules/portability/journal.mjs +49 -0
- package/modules/portability/legacy-files.mjs +43 -0
- package/modules/portability/legacy-safety.mjs +27 -0
- package/modules/portability/lines.mjs +36 -0
- package/modules/portability/migration-history.mjs +18 -0
- package/modules/portability/migration-statements.mjs +23 -0
- package/modules/portability/payloads.mjs +52 -0
- package/modules/portability/provider-data.mjs +25 -0
- package/modules/portability/restore-safety.mjs +30 -0
- package/modules/portability/schema/portability.sql +25 -0
- package/modules/portability/storage.mjs +49 -0
- package/modules/release/README.md +212 -0
- package/modules/release/catalogue.mjs +79 -0
- package/modules/release/export.mjs +51 -0
- package/modules/release/produce.mjs +136 -0
- package/modules/release/public-child-transport-state.cjs +29 -0
- package/modules/release/public-child.mjs +71 -0
- package/modules/release/public-git.mjs +21 -0
- package/modules/release/publication-scan.mjs +22 -0
- package/modules/release/publish-handoff.mjs +37 -0
- package/modules/release/source.mjs +71 -0
- package/modules/release/test-summary.mjs +50 -0
- package/onboarding/README.md +163 -0
- package/onboarding/activity.mjs +31 -0
- package/onboarding/adapter-auth.mjs +88 -0
- package/onboarding/adapter-hosting.mjs +35 -0
- package/onboarding/adapter-labels.mjs +13 -0
- package/onboarding/adapter-settings.mjs +129 -0
- package/onboarding/adapter.mjs +238 -0
- package/onboarding/agent-handoff.mjs +9 -0
- package/onboarding/app-processes.mjs +21 -0
- package/onboarding/archive-output.d.mts +3 -0
- package/onboarding/archive-output.mjs +54 -0
- package/onboarding/command-custody.mjs +24 -0
- package/onboarding/command-recovery.mjs +8 -0
- package/onboarding/commands.mjs +166 -0
- package/onboarding/dependency-approval.mjs +36 -0
- package/onboarding/dev-identity.mjs +23 -0
- package/onboarding/email.mjs +24 -0
- package/onboarding/failures.mjs +42 -0
- package/onboarding/input-limits.mjs +7 -0
- package/onboarding/installer-inputs.mjs +24 -0
- package/onboarding/launcher.mjs +34 -0
- package/onboarding/local/build-files.mjs +64 -0
- package/onboarding/local/build.mjs +49 -0
- package/onboarding/local/environment.mjs +30 -0
- package/onboarding/local/files.mjs +35 -0
- package/onboarding/local/operation.mjs +166 -0
- package/onboarding/local/owner.mjs +34 -0
- package/onboarding/local/process-table.mjs +114 -0
- package/onboarding/local/recovery.mjs +79 -0
- package/onboarding/local/state.mjs +31 -0
- package/onboarding/metadata.mjs +7 -0
- package/onboarding/operator-install.mjs +45 -0
- package/onboarding/operator-installer.mjs +39 -0
- package/onboarding/operator-prerequisites.mjs +27 -0
- package/onboarding/package.json +6 -0
- package/onboarding/prefill.mjs +16 -0
- package/onboarding/private-files.mjs +97 -0
- package/onboarding/private.mjs +35 -0
- package/onboarding/process-cleanup.mjs +134 -0
- package/onboarding/process-diagnostics.mjs +91 -0
- package/onboarding/process-scope.mjs +118 -0
- package/onboarding/process-table.mjs +118 -0
- package/onboarding/process-tree.mjs +36 -0
- package/onboarding/production-modules.mjs +22 -0
- package/onboarding/production-options.mjs +40 -0
- package/onboarding/production-plan.mjs +8 -0
- package/onboarding/production-runtime.mjs +30 -0
- package/onboarding/project-vite.mjs +14 -0
- package/onboarding/providers.mjs +289 -0
- package/onboarding/queue.mjs +53 -0
- package/onboarding/queued-entry.mjs +34 -0
- package/onboarding/readiness.mjs +59 -0
- package/onboarding/redaction-jwt.mjs +32 -0
- package/onboarding/redaction.mjs +298 -0
- package/onboarding/schema/SETUP.schema.json +514 -0
- package/onboarding/schema/dependencies.mjs +35 -0
- package/onboarding/schema/json-schema.mjs +202 -0
- package/onboarding/schema/setup-validation.mjs +325 -0
- package/onboarding/secrets.mjs +21 -0
- package/onboarding/server.mjs +188 -0
- package/onboarding/setup-manifest.mjs +116 -0
- package/onboarding/state.mjs +46 -0
- package/onboarding/theme-files.mjs +37 -0
- package/onboarding/theme.mjs +118 -0
- package/onboarding/ui/activity.js +98 -0
- package/onboarding/ui/address-client.mjs +33 -0
- package/onboarding/ui/app.js +377 -0
- package/onboarding/ui/index.html +1 -0
- package/onboarding/ui/model-core.mjs +127 -0
- package/onboarding/ui/model.mjs +5 -0
- package/onboarding/ui/style.css +63 -0
- package/onboarding/ui/theme.css +37 -0
- package/onboarding/ui/workspace-art.js +30 -0
- package/onboarding/wrangler-auth.mjs +43 -0
- package/operations/README.md +246 -0
- package/operations/operations.mjs +168 -0
- package/operations/project-operations.mjs +157 -0
- package/package.json +11 -4
- package/scripts/publish-check/README.md +72 -0
- package/scripts/publish-check/checksum_maps.py +52 -0
- package/scripts/publish-check/cli.py +34 -0
- package/scripts/publish-check/command_arguments.py +51 -0
- package/scripts/publish-check/command_shell_quotes.py +41 -0
- package/scripts/publish-check/command_source_quotes.py +120 -0
- package/scripts/publish-check/content_identities.py +250 -0
- package/scripts/publish-check/copy_identities.py +41 -0
- package/scripts/publish-check/der.py +61 -0
- package/scripts/publish-check/destination.py +117 -0
- package/scripts/publish-check/env_values.py +74 -0
- package/scripts/publish-check/font_licence.py +23 -0
- package/scripts/publish-check/git_history.py +115 -0
- package/scripts/publish-check/github_refs.py +217 -0
- package/scripts/publish-check/gitleaks.py +72 -0
- package/scripts/publish-check/gitleaks.toml +40 -0
- package/scripts/publish-check/history_scan.py +176 -0
- package/scripts/publish-check/hit_location.py +18 -0
- package/scripts/publish-check/hygiene_config.py +42 -0
- package/scripts/publish-check/hygiene_text.py +11 -0
- package/scripts/publish-check/identity-recipe.mjs +54 -0
- package/scripts/publish-check/json_identity.py +79 -0
- package/scripts/publish-check/license-exceptions.json +11 -0
- package/scripts/publish-check/licenses.py +49 -0
- package/scripts/publish-check/policy.py +18 -0
- package/scripts/publish-check/project_identity.py +89 -0
- package/scripts/publish-check/provenance.py +91 -0
- package/scripts/publish-check/provenance_pins.py +33 -0
- package/scripts/publish-check/public_base.py +63 -0
- package/scripts/publish-check/public_hygiene.py +80 -0
- package/scripts/publish-check/publication-config.json +12 -0
- package/scripts/publish-check/publication_config.py +34 -0
- package/scripts/publish-check/report.py +52 -0
- package/scripts/publish-check/repository_commands.py +75 -0
- package/scripts/publish-check/repository_intent.py +52 -0
- package/scripts/publish-check/reviewed.py +41 -0
- package/scripts/publish-check/source_hashes.mjs +6 -0
- package/scripts/publish-check/tree_scan.py +88 -0
- package/scripts/publish-check/trust_bundle.py +87 -0
- package/scripts/publish-check.mjs +58 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { access, constants } from 'node:fs/promises';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { delimiter, isAbsolute, resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const PROVIDER_NAMES = ['cloudflare', 'github'];
|
|
6
|
+
const MAX_OUTPUT = 256 * 1024;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* These are the only provider commands the installer can run. Values returned
|
|
10
|
+
* by local files or HTTP requests never become command arguments.
|
|
11
|
+
*/
|
|
12
|
+
export const PROVIDER_COMMANDS = Object.freeze({
|
|
13
|
+
cloudflare: Object.freeze({
|
|
14
|
+
binary: 'wrangler',
|
|
15
|
+
version: Object.freeze(['--version']),
|
|
16
|
+
auth: Object.freeze(['whoami']),
|
|
17
|
+
connect: Object.freeze(['login']),
|
|
18
|
+
}),
|
|
19
|
+
github: Object.freeze({
|
|
20
|
+
binary: 'gh',
|
|
21
|
+
version: Object.freeze(['--version']),
|
|
22
|
+
auth: Object.freeze(['auth', 'status', '--hostname', 'github.com']),
|
|
23
|
+
account: Object.freeze(['api', 'user', '--hostname', 'github.com', '--jq', '{login,id,name}']),
|
|
24
|
+
repository: Object.freeze(['repo', 'view', '--json', 'nameWithOwner,isPrivate,defaultBranchRef,pushedAt']),
|
|
25
|
+
connect: Object.freeze(['auth', 'login', '--hostname', 'github.com', '--git-protocol', 'https', '--web']),
|
|
26
|
+
}),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function providerName(value) {
|
|
30
|
+
if (typeof value !== 'string' || !PROVIDER_NAMES.includes(value)) {
|
|
31
|
+
throw new Error('Unsupported provider');
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function commandConfig(provider) {
|
|
37
|
+
return PROVIDER_COMMANDS[providerName(provider)];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function output(value) {
|
|
41
|
+
return typeof value === 'string' ? value.slice(0, MAX_OUTPUT) : '';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function executable(binary, env = process.env) {
|
|
45
|
+
if (isAbsolute(binary)) {
|
|
46
|
+
try {
|
|
47
|
+
await access(binary, constants.X_OK);
|
|
48
|
+
return binary;
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const directory of String(env.PATH || '').split(delimiter)) {
|
|
54
|
+
if (!directory) continue;
|
|
55
|
+
const candidate = resolve(directory, binary);
|
|
56
|
+
try {
|
|
57
|
+
await access(candidate, constants.X_OK);
|
|
58
|
+
return candidate;
|
|
59
|
+
} catch {
|
|
60
|
+
// Continue through PATH without exposing filesystem errors to the UI.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function runCommand(file, args, { cwd, signal, interactive = false, onDevice, env = process.env } = {}) {
|
|
67
|
+
return new Promise((resolveResult, reject) => {
|
|
68
|
+
let child;
|
|
69
|
+
try {
|
|
70
|
+
child = spawn(file, args, {
|
|
71
|
+
cwd,
|
|
72
|
+
env,
|
|
73
|
+
shell: false,
|
|
74
|
+
detached: false,
|
|
75
|
+
stdio: [interactive ? 'pipe' : 'ignore', 'pipe', 'pipe'],
|
|
76
|
+
});
|
|
77
|
+
} catch {
|
|
78
|
+
resolveResult({ code: null, signal: null, stdout: '', stderr: '' });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (interactive) child.stdin?.end('\n');
|
|
83
|
+
let stdout = '';
|
|
84
|
+
let stderr = '';
|
|
85
|
+
const collect = (kind, chunk) => {
|
|
86
|
+
// Provider auth tools can print credentials or token fragments. Keep
|
|
87
|
+
// output private to this process and bounded; callers only parse it.
|
|
88
|
+
if (kind === 'stdout') stdout = (stdout + String(chunk)).slice(0, MAX_OUTPUT);
|
|
89
|
+
else stderr = (stderr + String(chunk)).slice(0, MAX_OUTPUT);
|
|
90
|
+
if (interactive && onDevice) {
|
|
91
|
+
const clean = (stdout + stderr).replace(/\x1b\[[0-9;]*m/g, '');
|
|
92
|
+
const code = clean.match(/one-time code:\s*([A-Z0-9]{4}-[A-Z0-9]{4})/i)?.[1];
|
|
93
|
+
if (code) onDevice(code);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
child.stdout?.on('data', chunk => collect('stdout', chunk));
|
|
97
|
+
child.stderr?.on('data', chunk => collect('stderr', chunk));
|
|
98
|
+
|
|
99
|
+
const timeout = setTimeout(() => child.kill('SIGTERM'), interactive ? 180000 : 12000);
|
|
100
|
+
let settled = false;
|
|
101
|
+
const abort = () => {
|
|
102
|
+
if (!settled) child.kill('SIGTERM');
|
|
103
|
+
};
|
|
104
|
+
let processExit;
|
|
105
|
+
const finish = result => {
|
|
106
|
+
if (settled) return;
|
|
107
|
+
settled = true;
|
|
108
|
+
clearTimeout(timeout);
|
|
109
|
+
signal?.removeEventListener('abort', abort);
|
|
110
|
+
if (processExit) process.removeListener('exit', processExit);
|
|
111
|
+
resolveResult(result);
|
|
112
|
+
};
|
|
113
|
+
processExit = () => abort();
|
|
114
|
+
process.once('exit', processExit);
|
|
115
|
+
if (signal?.aborted) abort();
|
|
116
|
+
else signal?.addEventListener('abort', abort, { once: true });
|
|
117
|
+
child.once('error', () => finish({ code: null, signal: null, stdout, stderr }));
|
|
118
|
+
child.once('close', (code, childSignal) => finish({ code, signal: childSignal, stdout, stderr }));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function status(provider, executablePath, state, extra = {}) {
|
|
123
|
+
return {
|
|
124
|
+
provider,
|
|
125
|
+
installed: Boolean(executablePath),
|
|
126
|
+
executable: executablePath || null,
|
|
127
|
+
state,
|
|
128
|
+
authenticated: state === 'connected',
|
|
129
|
+
...extra,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function cloudflareAccounts(text) {
|
|
134
|
+
const lines = String(text).split(/\r?\n/);
|
|
135
|
+
const accounts = [];
|
|
136
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
137
|
+
const line = lines[index];
|
|
138
|
+
const idMatch = line.match(/\b([a-f0-9]{32})\b/i);
|
|
139
|
+
if (!idMatch) continue;
|
|
140
|
+
let name = line
|
|
141
|
+
.replace(idMatch[0], '')
|
|
142
|
+
.replace(/[│|]/g, ' ')
|
|
143
|
+
.replace(/account\s*id\s*:?/gi, '')
|
|
144
|
+
.trim();
|
|
145
|
+
if (!name || /^id$/i.test(name)) {
|
|
146
|
+
const previous = lines[index - 1] || '';
|
|
147
|
+
const nameMatch = previous.match(/account\s*name\s*:?\s*([^│|]+)$/i);
|
|
148
|
+
name = nameMatch?.[1]?.trim() || null;
|
|
149
|
+
}
|
|
150
|
+
if (name && /email|logged|token|account\s*id/i.test(name)) name = null;
|
|
151
|
+
if (!accounts.some(account => account.id === idMatch[1])) {
|
|
152
|
+
accounts.push({ id: idMatch[1], ...(name ? { name } : {}) });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return accounts;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function cloudflareAuthenticated(result) {
|
|
159
|
+
const text = `${result.stdout}\n${result.stderr}`.toLowerCase();
|
|
160
|
+
return result.code === 0 && !/(not logged|not authenticated|run .*login|authentication required)/i.test(text);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function githubAuthenticated(result) {
|
|
164
|
+
const text = `${result.stdout}\n${result.stderr}`.toLowerCase();
|
|
165
|
+
return result.code === 0 && !/(not logged|not authenticated|no accounts|authentication required)/i.test(text);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function safeJson(value) {
|
|
169
|
+
try {
|
|
170
|
+
return JSON.parse(value);
|
|
171
|
+
} catch {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function gitRemoteName(value) {
|
|
177
|
+
const remote = String(value || '').trim();
|
|
178
|
+
const match = remote.match(/^(?:https?:\/\/github\.com\/|git@github\.com:)([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/i);
|
|
179
|
+
if (!match) return null;
|
|
180
|
+
return `${match[1]}/${match[2]}`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function discoverCloudflare(root, options) {
|
|
184
|
+
const config = commandConfig('cloudflare');
|
|
185
|
+
const path = await executable(config.binary, options.env);
|
|
186
|
+
if (!path) return status('cloudflare', null, 'not_installed', { accounts: [] });
|
|
187
|
+
const versionResult = await options.run(path, config.version, { cwd: root, signal: options.signal, env: options.env });
|
|
188
|
+
const authResult = await options.run(path, config.auth, { cwd: root, signal: options.signal, env: options.env });
|
|
189
|
+
const connected = cloudflareAuthenticated(authResult);
|
|
190
|
+
return status('cloudflare', path, connected ? 'connected' : 'auth_required', {
|
|
191
|
+
version: output(versionResult.stdout || versionResult.stderr).split(/\r?\n/, 1)[0] || null,
|
|
192
|
+
accounts: connected ? cloudflareAccounts(`${authResult.stdout}\n${authResult.stderr}`) : [],
|
|
193
|
+
connect: { command: config.connect.slice(), opensBrowser: true },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function discoverGithub(root, options) {
|
|
198
|
+
const config = commandConfig('github');
|
|
199
|
+
const path = await executable(config.binary, options.env);
|
|
200
|
+
if (!path) return status('github', null, 'not_installed', { account: null, repository: null });
|
|
201
|
+
const versionResult = await options.run(path, config.version, { cwd: root, signal: options.signal, env: options.env });
|
|
202
|
+
const authResult = await options.run(path, config.auth, { cwd: root, signal: options.signal, env: options.env });
|
|
203
|
+
const connected = githubAuthenticated(authResult);
|
|
204
|
+
const result = status('github', path, connected ? 'connected' : 'auth_required', {
|
|
205
|
+
version: output(versionResult.stdout || versionResult.stderr).split(/\r?\n/, 1)[0] || null,
|
|
206
|
+
account: null,
|
|
207
|
+
repository: null,
|
|
208
|
+
connect: { command: config.connect.slice(), opensBrowser: true },
|
|
209
|
+
});
|
|
210
|
+
if (!connected) return result;
|
|
211
|
+
|
|
212
|
+
const accountResult = await options.run(path, config.account, { cwd: root, signal: options.signal, env: options.env });
|
|
213
|
+
const account = safeJson(output(accountResult.stdout));
|
|
214
|
+
if (account && typeof account === 'object' && typeof account.login === 'string' && (typeof account.id === 'number' || typeof account.id === 'string')) {
|
|
215
|
+
result.account = {
|
|
216
|
+
login: account.login,
|
|
217
|
+
id: String(account.id),
|
|
218
|
+
...(typeof account.name === 'string' && account.name ? { name: account.name } : {}),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const remoteResult = await options.run('git', ['config', '--get', 'remote.origin.url'], { cwd: root, signal: options.signal, env: options.env });
|
|
223
|
+
const nameWithOwner = gitRemoteName(remoteResult.stdout);
|
|
224
|
+
if (!nameWithOwner) return result;
|
|
225
|
+
const repositoryResult = await options.run(path, [...config.repository, nameWithOwner], { cwd: root, signal: options.signal, env: options.env });
|
|
226
|
+
const repository = safeJson(output(repositoryResult.stdout));
|
|
227
|
+
if (repository && typeof repository === 'object' && typeof repository.nameWithOwner === 'string') {
|
|
228
|
+
result.repository = {
|
|
229
|
+
nameWithOwner: repository.nameWithOwner,
|
|
230
|
+
...(typeof repository.isPrivate === 'boolean' ? { isPrivate: repository.isPrivate } : {}),
|
|
231
|
+
...(repository.defaultBranchRef?.name ? { defaultBranch: repository.defaultBranchRef.name } : {}),
|
|
232
|
+
...(typeof repository.pushedAt === 'string' ? { pushedAt: repository.pushedAt } : {}),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Discover local CLI availability and account metadata without returning CLI output. */
|
|
239
|
+
export async function discoverProviders(root = process.cwd(), { signal, run = runCommand, env = process.env } = {}) {
|
|
240
|
+
const directory = resolve(root);
|
|
241
|
+
const options = { signal, run, env };
|
|
242
|
+
const [cloudflare, github] = await Promise.all([
|
|
243
|
+
discoverCloudflare(directory, options),
|
|
244
|
+
discoverGithub(directory, options),
|
|
245
|
+
]);
|
|
246
|
+
return { schemaVersion: 1, providers: { cloudflare, github } };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Start one of the fixed, browser-based provider logins. This function is
|
|
251
|
+
* intended for an explicit Connect action; discovery alone has no remote side
|
|
252
|
+
* effects. The returned status is refreshed after the child exits, so a zero
|
|
253
|
+
* exit code never becomes a false connected state.
|
|
254
|
+
*/
|
|
255
|
+
export async function connectProvider(root = process.cwd(), provider, { signal, onProgress, run = runCommand, env = process.env } = {}) {
|
|
256
|
+
const name = providerName(provider);
|
|
257
|
+
const config = commandConfig(name);
|
|
258
|
+
const directory = resolve(root);
|
|
259
|
+
const path = await executable(config.binary, env);
|
|
260
|
+
if (!path) {
|
|
261
|
+
const result = (await discoverProviders(directory, { signal, run, env })).providers[name];
|
|
262
|
+
onProgress?.({ provider: name, state: result.state });
|
|
263
|
+
return { ...result, operation: { state: 'failed', reason: 'not_installed' } };
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
onProgress?.({ provider: name, state: 'awaiting_browser' });
|
|
267
|
+
const login = await run(path, config.connect.slice(), {
|
|
268
|
+
cwd: directory,
|
|
269
|
+
signal,
|
|
270
|
+
env,
|
|
271
|
+
interactive: true,
|
|
272
|
+
onDevice: name === 'github' ? deviceCode => onProgress?.({ provider: name, state: 'awaiting_browser', deviceCode, verificationUrl: 'https://github.com/login/device' }) : undefined,
|
|
273
|
+
});
|
|
274
|
+
if (signal?.aborted) {
|
|
275
|
+
onProgress?.({ provider: name, state: 'cancelled' });
|
|
276
|
+
const result = (await discoverProviders(directory, { signal, run, env })).providers[name];
|
|
277
|
+
return { ...result, operation: { state: 'cancelled' } };
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
onProgress?.({ provider: name, state: 'refreshing' });
|
|
281
|
+
const result = (await discoverProviders(directory, { signal, run, env })).providers[name];
|
|
282
|
+
const operation = result.authenticated
|
|
283
|
+
? { state: 'connected' }
|
|
284
|
+
: { state: 'auth_required', reason: login.code === 0 ? 'authentication_not_confirmed' : 'login_failed' };
|
|
285
|
+
onProgress?.({ provider: name, state: operation.state });
|
|
286
|
+
return { ...result, operation };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export const providerNames = Object.freeze(PROVIDER_NAMES.slice());
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { basename, dirname, join, relative } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { readFile, realpath } from 'node:fs/promises';
|
|
5
|
+
const portable = basename(dirname(fileURLToPath(import.meta.url))) === 'base-onboarding';
|
|
6
|
+
const queueURL = new URL(portable ? '../base-cli/modules/job-queue/' : '../modules/job-queue/', import.meta.url);
|
|
7
|
+
export const heavyVerbs = new Set(['install', 'setup', 'build', 'verify', 'dev', 'preview', 'deploy', 'release', 'export', 'import', 'installer']);
|
|
8
|
+
export async function queueLabel(root, verb, phase) {
|
|
9
|
+
root = await realpath(root);
|
|
10
|
+
let project='project';
|
|
11
|
+
for(const file of ['OPERATIONS.json','package.json']){
|
|
12
|
+
try{const value=JSON.parse(await readFile(join(root,file),'utf8')),name=value.project??value.name;
|
|
13
|
+
if(typeof name==='string'&&/^@?[a-zA-Z0-9_.-]+(?:\/[a-zA-Z0-9_.-]+)?$/.test(name)){project=name;break;}
|
|
14
|
+
}catch{}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return `${project} ${verb}:${phase} [${createHash('sha256').update(root).digest('hex').slice(0, 12)}]`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function shellQuote(value) {
|
|
21
|
+
if (process.platform === 'win32') return `"${String(value).replaceAll('"', '""')}"`;
|
|
22
|
+
return `'${String(value).replaceAll("'", "'\\''")}'`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function waitingText(wait, waitingMessage) {
|
|
26
|
+
return `${waitingMessage(wait)}\nRun from the project root. Inspect the queue with: ${wait.statusCommandText}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function queuedCommand(command, args, options) {
|
|
30
|
+
const { createQueue } = await import(new URL('index.mjs', queueURL));
|
|
31
|
+
const { liveMembership } = await import(new URL('membership.mjs', queueURL));
|
|
32
|
+
const { waitingMessage } = await import(new URL('waiting.mjs', queueURL));
|
|
33
|
+
const statusCommand = [process.execPath, fileURLToPath(new URL('cli.mjs', queueURL)), 'status', '--json'];
|
|
34
|
+
// An inherited credential-shaped PWD can redact an absolute project prefix.
|
|
35
|
+
// Keep the human recipe relative while retaining the executable argv for tools.
|
|
36
|
+
const statusCommandText = [basename(process.execPath), relative(options.cwd ?? process.cwd(), statusCommand[1]), ...statusCommand.slice(2)].map(shellQuote).join(' ');
|
|
37
|
+
// Read the original caller's decision before an install synthesizes CI=true.
|
|
38
|
+
if (options.originalCI === true || await liveMembership()) return null;
|
|
39
|
+
const queue = await createQueue();
|
|
40
|
+
try {
|
|
41
|
+
const result = await queue.run([command, ...args], { ...options, kind: 'heavy', maxWait: 1200,
|
|
42
|
+
onWaiting: (reason, detail) => {
|
|
43
|
+
const wait = { ...(detail ?? { reason }), statusCommand, statusCommandText };
|
|
44
|
+
if (typeof options.onWaiting === 'function') return options.onWaiting(wait);
|
|
45
|
+
return options.report?.(waitingText(wait, waitingMessage));
|
|
46
|
+
},
|
|
47
|
+
onStarted: () => options.report(`Heavy job admitted: ${options.label}`) });
|
|
48
|
+
if (result.supervisorEnded) options.report?.(result.error);
|
|
49
|
+
return result;
|
|
50
|
+
} finally { await queue.close(); }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function commandPolicy(){const {callerPolicy}=await import(new URL('policy.mjs',queueURL));return callerPolicy();}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { fileURLToPath,pathToFileURL } from 'node:url';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { mkdtemp,rm } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { createCommands } from './commands.mjs';
|
|
7
|
+
import { commandPolicy,queuedCommand,queueLabel } from './queue.mjs';
|
|
8
|
+
|
|
9
|
+
// Called by real suite entrypoints before their runtime imports/side effects.
|
|
10
|
+
// The admitted child runs the original file/argv, retaining its own stack.
|
|
11
|
+
export async function queuedEntrypoint(url,verb='verify') {
|
|
12
|
+
const directory=await mkdtemp(join(tmpdir(),'rer-heavy-'));
|
|
13
|
+
let store;
|
|
14
|
+
try{
|
|
15
|
+
store=await createCommands(directory,{logs:[]},{terminal:text=>process.stderr.write(text),queue:{verb}});
|
|
16
|
+
const policy=await commandPolicy();
|
|
17
|
+
try{
|
|
18
|
+
const result=await queuedCommand(process.execPath,[...process.execArgv,fileURLToPath(url),...process.argv.slice(2)],{
|
|
19
|
+
cwd:process.cwd(),originalCI:policy.ci,label:await queueLabel(process.cwd(),verb,'suite'),report:text=>store.report(text),env:{...process.env,...policy.environment},
|
|
20
|
+
spawn:(command,args,options)=>store.spawn(verb,command,args,options),cleanup:child=>store.stop(child)});
|
|
21
|
+
return result?.code??null;
|
|
22
|
+
}finally{await policy.close();}
|
|
23
|
+
}finally{await store?.closeCommands();await rm(directory,{recursive:true,force:true});}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if(process.argv[1] && pathToFileURL(resolve(process.argv[1])).href===import.meta.url){
|
|
27
|
+
const [verb,separator,command,...args]=process.argv.slice(2);
|
|
28
|
+
if(separator!=='--'||!command)throw Error('Usage: queued-entry VERB -- COMMAND ARGS');
|
|
29
|
+
const directory=await mkdtemp(join(tmpdir(),'rer-heavy-'));
|
|
30
|
+
const store=await createCommands(directory,{logs:[]},{terminal:text=>process.stdout.write(text),queue:{verb}});
|
|
31
|
+
try{await store.run(verb,command,args,{cwd:process.cwd()});}
|
|
32
|
+
catch(error){process.exitCode=error.childExitCode??1;}
|
|
33
|
+
finally{await store.closeCommands();await rm(directory,{recursive:true,force:true});}
|
|
34
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const defaultWait = (ms,signal) => new Promise(resolve => {
|
|
2
|
+
const done = () => { clearTimeout(timer); signal?.removeEventListener('abort',done); resolve(); };
|
|
3
|
+
const timer = setTimeout(done,ms); signal?.addEventListener('abort',done,{once:true}); if(signal?.aborted)done();
|
|
4
|
+
});
|
|
5
|
+
|
|
6
|
+
export async function waitForReadiness(label, child, health, options, capture, report, failure) {
|
|
7
|
+
const {signal, timeoutMs=900000, intervalMs=1000, softAfterMs=30000, probeTimeoutMs=Math.max(5000,intervalMs*3), now=Date.now, wait=defaultWait}=options;
|
|
8
|
+
if (!Number.isFinite(timeoutMs)||timeoutMs<=0||!Number.isFinite(intervalMs)||intervalMs<=0||!Number.isFinite(probeTimeoutMs)||probeTimeoutMs<=0)throw TypeError('Readiness intervals must be positive.');
|
|
9
|
+
const start=now(), scope=new AbortController();
|
|
10
|
+
let lastHealth='No healthy response yet', cancelled;
|
|
11
|
+
const aborted = new Promise(resolve=>{cancelled=()=>resolve({kind:'cancel'});signal?.addEventListener('abort',cancelled,{once:true});if(signal?.aborted)cancelled();});
|
|
12
|
+
const closed = capture.closed.then(result=>({kind:'closed',result}));
|
|
13
|
+
const exited = capture.exited.then(result=>({kind:'exit',result}));
|
|
14
|
+
const failed = capture.failed.then(result=>({kind:'error',result}));
|
|
15
|
+
const deadline = wait(timeoutMs,scope.signal).then(()=>({kind:'deadline'}));
|
|
16
|
+
const progress=(async()=>{
|
|
17
|
+
await wait(Math.max(1,softAfterMs),scope.signal);
|
|
18
|
+
while(!scope.signal.aborted){report(`${label}: Still starting (${Math.floor((now()-start)/1000)} s)`);await wait(Math.max(1000,intervalMs),scope.signal);}
|
|
19
|
+
})();
|
|
20
|
+
const stopped = () => child.exitCode!==null&&child.exitCode!==undefined || child.signalCode!==null&&child.signalCode!==undefined;
|
|
21
|
+
const fail = (reason,result) => {throw failure(label,{...result,reason,lastHealth});};
|
|
22
|
+
// Give ordinary final pipe bytes a bounded chance to arrive after exit. A
|
|
23
|
+
// descendant holding stdio cannot keep an already-dead app in readiness.
|
|
24
|
+
const drain = async () => {
|
|
25
|
+
const result=await Promise.race([closed,failed,aborted,deadline,wait(50,scope.signal).then(()=>({kind:'exit',result:capture.exitResult}))]);
|
|
26
|
+
return fail(result.kind,result.result);
|
|
27
|
+
};
|
|
28
|
+
try {
|
|
29
|
+
for (;;) {
|
|
30
|
+
if(signal?.aborted)return await fail('cancel');
|
|
31
|
+
if(stopped())return await drain();
|
|
32
|
+
if(now()-start>=timeoutMs)return await fail('deadline');
|
|
33
|
+
const probeScope=new AbortController();
|
|
34
|
+
const probeSignal=AbortSignal.any([scope.signal,probeScope.signal]);
|
|
35
|
+
const probe=Promise.resolve().then(()=>health(probeSignal)).then(value=>({kind:'health',value}),()=>({kind:'health',value:{ready:false,message:'Health probe failed'}}));
|
|
36
|
+
// Race independently of the callback: adapters that ignore abort must not
|
|
37
|
+
// consume the entire startup window with one request.
|
|
38
|
+
const probeDeadline=wait(probeTimeoutMs,probeScope.signal).then(()=>{
|
|
39
|
+
if(!probeScope.signal.aborted)probeScope.abort();
|
|
40
|
+
return {kind:'health',value:{ready:false,message:'Health probe timed out'}};
|
|
41
|
+
});
|
|
42
|
+
let result;
|
|
43
|
+
try { result=await Promise.race([probe,probeDeadline,closed,exited,failed,aborted,deadline]); }
|
|
44
|
+
finally { probeScope.abort(); }
|
|
45
|
+
|
|
46
|
+
if(result.kind==='exit')return await drain();
|
|
47
|
+
if(result.kind!=='health')return await fail(result.kind,result.result);
|
|
48
|
+
if(stopped())return await drain();
|
|
49
|
+
if(signal?.aborted)return await fail('cancel');
|
|
50
|
+
if(now()-start>=timeoutMs)return await fail('deadline');
|
|
51
|
+
if(result.value===true||result.value?.ready===true)return result.value;
|
|
52
|
+
if(typeof result.value==='string')lastHealth=result.value;
|
|
53
|
+
else if(typeof result.value?.message==='string')lastHealth=result.value.message;
|
|
54
|
+
result=await Promise.race([wait(Math.min(intervalMs,timeoutMs-(now()-start)),scope.signal).then(()=>({kind:'tick'})),closed,exited,failed,aborted,deadline]);
|
|
55
|
+
if(result.kind==='exit')return await drain();
|
|
56
|
+
if(result.kind!=='tick')return await fail(result.kind,result.result);
|
|
57
|
+
}
|
|
58
|
+
} finally { scope.abort();signal?.removeEventListener('abort',cancelled);await progress; }
|
|
59
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Scan each base64url segment once. A header may start inside a diagnostic
|
|
2
|
+
// word (session-eyJ...), so retrying a regex at each eyJ in a long segment
|
|
3
|
+
// would be quadratic. Only three adjacent dot-separated segments can be a JWT.
|
|
4
|
+
const SEGMENT = /[A-Za-z0-9_-]+/g;
|
|
5
|
+
const HEADER = /eyJ(?=[A-Za-z0-9_-])/i;
|
|
6
|
+
const TOKEN_CHAR = /[A-Za-z0-9_.-]/;
|
|
7
|
+
|
|
8
|
+
export function jwtRanges(text) {
|
|
9
|
+
const found = [];
|
|
10
|
+
let previous = [];
|
|
11
|
+
for (const part of text.matchAll(SEGMENT)) {
|
|
12
|
+
const last = previous.at(-1);
|
|
13
|
+
if (last && (part.index !== last.end + 1 || text[last.end] !== '.')) previous = [];
|
|
14
|
+
previous.push({ start: part.index, end: part.index + part[0].length, text: part[0] });
|
|
15
|
+
if (previous.length < 3) continue;
|
|
16
|
+
const header = HEADER.exec(previous[0].text);
|
|
17
|
+
if (header) found.push([previous[0].start + header.index, previous[2].end]);
|
|
18
|
+
previous.shift();
|
|
19
|
+
}
|
|
20
|
+
return found;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const jwtHold = { exec(text) {
|
|
24
|
+
// Only the tail after the third-last dot can still become a partial JWT.
|
|
25
|
+
let start = text.length, dots = 0;
|
|
26
|
+
while (start > 0 && TOKEN_CHAR.test(text[start - 1])) {
|
|
27
|
+
if (text[start - 1] === '.' && ++dots === 3) break;
|
|
28
|
+
start--;
|
|
29
|
+
}
|
|
30
|
+
const at = /eyJ/i.exec(text.slice(start));
|
|
31
|
+
return at ? { index: start + at.index } : null;
|
|
32
|
+
} };
|