@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,127 @@
|
|
|
1
|
+
export function createModel(seed) {
|
|
2
|
+
const fields = seed.fields;
|
|
3
|
+
const safeKeys = seed.safeKeys || Object.keys(fields).filter(key => fields[key].type !== 'password');
|
|
4
|
+
const product = seed.product;
|
|
5
|
+
const branding = seed.branding || product;
|
|
6
|
+
const features = seed.features || {};
|
|
7
|
+
// Browser editions opt specific safe values into the collapsed answer summary.
|
|
8
|
+
const summaryDefaults = [...new Set((Array.isArray(seed.summaryDefaults) ? seed.summaryDefaults : []).filter(key => safeKeys.includes(key) && fields[key]?.type !== 'password'))];
|
|
9
|
+
function normalizeWebsite(value) {
|
|
10
|
+
const text = typeof value === 'string' ? value.trim() : '';
|
|
11
|
+
if (!text) return '';
|
|
12
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(text) && !/^[\w.-]+:\d+(?:[/?#]|$)/.test(text)) return text;
|
|
13
|
+
return text.startsWith('//') ? 'https:' + text : 'https://' + text;
|
|
14
|
+
}
|
|
15
|
+
function safeDraft(draft) { return Object.fromEntries(safeKeys.filter(key => typeof draft[key] === 'string').map(key => [key, draft[key]])); }
|
|
16
|
+
function initialDraft(state) {
|
|
17
|
+
const draft = { ...safeDraft(seed.initialValues?.(state) || {}), ...safeDraft(state.draft || {}) };
|
|
18
|
+
const accounts = state.known?.providers?.cloudflare?.accounts || [];
|
|
19
|
+
if (features.hosting && !draft.accountId && accounts.length === 1) draft.accountId = accounts[0].id;
|
|
20
|
+
// This explicit edition feature makes the local/no-email starting choices reviewable in setup.
|
|
21
|
+
if (features.localTrialWithoutEmail === true) {
|
|
22
|
+
if (features.hosting && !draft.target && fields.target?.valid?.('local')) draft.target = 'local';
|
|
23
|
+
}
|
|
24
|
+
return normalizeAutomaticDraft(draft);
|
|
25
|
+
}
|
|
26
|
+
function secretReady(key, draft, known = {}) {
|
|
27
|
+
const readiness = known.secretReadiness || {};
|
|
28
|
+
if (readiness.scopes?.[key]) return readiness[key] === true && Object.entries(readiness.scopes[key]).every(([field,value]) => draft[field] === value);
|
|
29
|
+
return readiness[key] === true;
|
|
30
|
+
}
|
|
31
|
+
const hostingKeys = ['target', 'accountId', 'prefix', 'appOrigin', 'apiToken'];
|
|
32
|
+
function hostingModel(draft, known = {}) {
|
|
33
|
+
if (!features.hosting) return { complete: true, accessReady: false };
|
|
34
|
+
const accessReady = Boolean(known.providers?.cloudflare?.authenticated || fields.apiToken.valid(draft.apiToken) || secretReady('apiToken', draft, known));
|
|
35
|
+
const complete = draft.target === 'local' || (draft.target === 'remote' && accessReady && ['accountId', 'prefix', 'appOrigin'].every(key => fields[key].valid(draft[key])));
|
|
36
|
+
return { complete, accessReady };
|
|
37
|
+
}
|
|
38
|
+
function setupModel(draft, known = {}) {
|
|
39
|
+
const keys = [...(seed.requiredKeys?.(draft, known) || Object.keys(fields).filter(key => !fields[key].optional))];
|
|
40
|
+
const connections = [];
|
|
41
|
+
if (features.hosting && draft.target === 'remote') {
|
|
42
|
+
keys.push('accountId', 'prefix', 'appOrigin');
|
|
43
|
+
if (!known.providers?.cloudflare?.authenticated && !fields.apiToken.valid(draft.apiToken) && !secretReady('apiToken', draft, known)) connections.push('cloudflare');
|
|
44
|
+
}
|
|
45
|
+
const missing = keys.filter(key => !fields[key].valid(draft[key]) && !(fields[key].type === 'password' && secretReady(key, draft, known)));
|
|
46
|
+
const complete = keys.filter(key => fields[key].valid(draft[key]) || (fields[key].type === 'password' && secretReady(key, draft, known)));
|
|
47
|
+
return { missing, complete, connections, remaining: missing.length + connections.length, ready: !missing.length && !connections.length };
|
|
48
|
+
}
|
|
49
|
+
function installInput(draft) {
|
|
50
|
+
if (seed.installInput) return seed.installInput(draft);
|
|
51
|
+
return { ...safeDraft(draft), ...Object.fromEntries(Object.keys(fields).filter(key => fields[key].type === 'password' && draft[key]).map(key => [key, draft[key]])) };
|
|
52
|
+
}
|
|
53
|
+
function displayValue(key, value) { return fields[key]?.options?.find(([option]) => option === value)?.[1] || value; }
|
|
54
|
+
function summaryKeys(draft, state = {}) {
|
|
55
|
+
const answered = new Set(Array.isArray(state.answered) ? state.answered : []), sources = state.sources || {};
|
|
56
|
+
return safeKeys.filter(key => {
|
|
57
|
+
const field = fields[key], value = draft[key], source = sources[key];
|
|
58
|
+
if (typeof value !== 'string' || !value.trim() || field?.type === 'password' || typeof field?.valid !== 'function' || !field.valid(value)) return false;
|
|
59
|
+
return answered.has(key) || ['agent', 'browser', 'saved'].includes(source) || summaryDefaults.includes(key);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function failureDetails(state = {}) {
|
|
64
|
+
const error = typeof state.error === 'string' ? state.error : '';
|
|
65
|
+
// Commands append their private log path after the captured output. A child
|
|
66
|
+
// can print its own Log: lines, so only the final, anchored line is metadata.
|
|
67
|
+
const diagnostic = error.match(/\nLast output \(up to 40 lines\):\n([\s\S]*)\nLog: ([^\r\n]+)$/);
|
|
68
|
+
const commandOutput = diagnostic?.[1] || '';
|
|
69
|
+
return {
|
|
70
|
+
step: typeof state.step === 'string' && state.step ? state.step : 'the last installation step',
|
|
71
|
+
output: commandOutput === '(no output)' ? '' : commandOutput,
|
|
72
|
+
logPath: diagnostic?.[2] || '',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function failureNote(failure) {
|
|
76
|
+
const note = failure.output
|
|
77
|
+
? `Output from ${failure.step} is shown above.`
|
|
78
|
+
: `Installation stopped during ${failure.step}. Review the installation activity above.`;
|
|
79
|
+
return note + (failure.logPath ? ` Installer log: ${failure.logPath}` : '');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function mergeAgentDraft(draft, state, appliedRevision = 0, pendingKeys = []) {
|
|
83
|
+
const update = state.lastUpdate;
|
|
84
|
+
if (!Number.isFinite(update?.revision) || update.revision <= appliedRevision) return draft;
|
|
85
|
+
const keys = new Set(Object.entries(state.sources || {}).filter(([, source]) => source === 'agent').map(([key]) => key));
|
|
86
|
+
if (update.source === 'agent' && Array.isArray(update.keys)) for (const key of update.keys) keys.add(key);
|
|
87
|
+
const pending = new Set(pendingKeys), values = safeDraft(state.draft || {}), merged = { ...draft }; let changed = false;
|
|
88
|
+
for (const key of keys) if (!pending.has(key) && Object.hasOwn(values, key) && values[key] !== draft[key]) { merged[key] = values[key]; changed = true; }
|
|
89
|
+
return changed ? merged : draft;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function derivePrefix(value) {
|
|
93
|
+
let slug = String(value || '').normalize('NFKD').replace(/[\u0300-\u036f]/g, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
94
|
+
if (!slug) return '';
|
|
95
|
+
if (!/^[a-z]/.test(slug) || slug.length < 3) slug = (product.slugPrefix || 'app') + '-' + slug;
|
|
96
|
+
return slug.slice(0, 40).replace(/-+$/g, '');
|
|
97
|
+
}
|
|
98
|
+
function normalizeAutomaticDraft(value) {
|
|
99
|
+
const draft = { ...value };
|
|
100
|
+
if (!features.hosting) return draft;
|
|
101
|
+
draft.prefixMode ||= draft.prefix ? 'custom' : 'automatic';
|
|
102
|
+
draft.addressMode ||= draft.appOrigin ? 'custom' : 'automatic';
|
|
103
|
+
if (draft.prefixMode === 'automatic') draft.prefix = derivePrefix(draft[seed.nameKey]);
|
|
104
|
+
return draft;
|
|
105
|
+
}
|
|
106
|
+
// Navigation is deliberately separate from readiness: only the user advances a step.
|
|
107
|
+
const setupGroups = seed.setupGroups.map(group => ({ ...group, complete: group.complete || (group.kind === 'hosting'
|
|
108
|
+
? ((draft, known) => (!features.hosting || hostingModel(draft, known).complete))
|
|
109
|
+
: ((draft, known) => !setupModel(draft, known).missing.some(key => group.keys.includes(key)))) }));
|
|
110
|
+
function readySummary(draft) { return seed.readySummary?.(draft) || `${draft[seed.nameKey] || product.name} is ready to be installed.`; }
|
|
111
|
+
function nextIncompleteGroup(draft, known = {}) {
|
|
112
|
+
return setupGroups.find(group => !group.complete(draft, known))?.id || null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Retain steps the owner actually reached; only unvisited, complete groups drop out.
|
|
116
|
+
// Editing known details is separate from the numbered setup journey.
|
|
117
|
+
function setupProgress(draft, known = {}, { active = null, visited = [], editing = false } = {}) {
|
|
118
|
+
const group = setupGroups.find(group => group.id === active);
|
|
119
|
+
if (!group) return 'Your choices are ready';
|
|
120
|
+
if (editing) return `Editing ${group.title}`;
|
|
121
|
+
const reached = [...new Set([...visited, active])];
|
|
122
|
+
const remaining = setupGroups.filter(group => !reached.includes(group.id) && !group.complete(draft, known));
|
|
123
|
+
return `Step ${reached.indexOf(active) + 1} of ${reached.length + remaining.length}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { fields, safeKeys, product, branding, features, summaryDefaults, normalizeWebsite, safeDraft, initialDraft, secretReady, hostingKeys, hostingModel, setupModel, installInput, displayValue, summaryKeys, failureDetails, failureNote, mergeAgentDraft, derivePrefix, normalizeAutomaticDraft, setupGroups, readySummary, nextIncompleteGroup, setupProgress };
|
|
127
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as seed from './seed.mjs';
|
|
2
|
+
import {readSetupManifestBytes,createInstallerModel} from './setup-manifest.mjs';
|
|
3
|
+
const [manifestResponse,schemaResponse,optionsResponse]=await Promise.all([fetch('/rer-setup.json'),fetch('/SETUP.schema.json'),fetch('/model-options.json')]);
|
|
4
|
+
const manifest=readSetupManifestBytes(new Uint8Array(await manifestResponse.arrayBuffer()),new Uint8Array(await schemaResponse.arrayBuffer()));
|
|
5
|
+
export const { fields, safeKeys, product, branding, features, summaryDefaults, normalizeWebsite, safeDraft, initialDraft, secretReady, hostingKeys, hostingModel, setupModel, installInput, displayValue, summaryKeys, failureDetails, failureNote, mergeAgentDraft, derivePrefix, normalizeAutomaticDraft, setupGroups, readySummary, nextIncompleteGroup, setupProgress, fieldVisible, fieldDefinition, groupDefinition, groupKeys, secretScopes, nameKey } = createInstallerModel(manifest,seed,await optionsResponse.json());
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
*{box-sizing:border-box}[hidden]{display:none!important}body{margin:0;color:#173753;font:15px/1.6 Inter,Arial,sans-serif}.scene{min-height:100vh;padding:64px 5vw;background:#164661 url('/ocean.png') center/cover}.layout{max-width:1360px;margin:auto;display:grid;grid-template-columns:minmax(290px,.9fr) minmax(0,1.5fr);column-gap:70px;row-gap:24px;align-items:start}.sidebar{padding:0 28px;color:#f7f8ff;background:transparent;border:0;box-shadow:none}.brand{grid-column:1/-1;font-size:22px;font-weight:700;color:#f7f8ff;margin:0;padding-left:28px}.known-row{padding:7px 0;display:grid;grid-template-columns:1fr auto;gap:2px 15px}.known-label{font-size:12px}.known-value{grid-column:1;font-weight:500;font-size:14px;overflow-wrap:anywhere}.known-source{grid-column:1;font-size:10px;line-height:1.3}.edit{border:0;background:none;color:#dfcaff;font:inherit;cursor:pointer;padding:0;align-self:center;grid-column:2;grid-row:1/4}summary{cursor:pointer}.panel{padding:38px 40px;border-radius:26px;background:rgba(251,252,255,.97);box-shadow:0 18px 64px #001c3b33;min-width:0}.panel h1{font-size:29px;letter-spacing:-.6px;line-height:1.25;margin:0 0 24px}.fields{display:grid;gap:18px}.field{border:1px solid #e0e8f6;border-radius:15px;padding:20px;background:rgba(255,255,255,.5);min-width:0}.field label,.field-title{font-size:15px;font-weight:600;display:block;margin:0 0 7px;color:#153b66}.input{display:block;width:100%;min-width:0;padding:12px 14px;border:1px solid #cdd6e5;border-radius:10px;background:#fff;color:#173753;font:inherit}.input:focus-visible,button:focus-visible,a:focus-visible,summary:focus-visible{outline:3px solid #b796ff;outline-offset:3px}.help{color:#64788e;font-size:13px;line-height:1.6;margin:8px 0 0}.status{color:#57728b;font-size:13px;margin:10px 0}.field .edit{color:#7542d3;display:block;margin-top:12px;font-size:13px}.primary,.secondary{display:inline-flex;align-items:center;justify-content:center;min-height:46px;padding:12px 24px;border-radius:25px;font:600 14px/1.5 Inter,Arial,sans-serif;cursor:pointer;text-decoration:none}.primary{border:0;background:linear-gradient(120deg,#9255fc,#6537e7);color:white;box-shadow:0 5px 12px #7949de28}.secondary{border:1px solid #d2dcea;background:transparent;color:#224567}.actions{display:flex;justify-content:flex-end;margin-top:26px}.primary:disabled{opacity:.5;cursor:default}.error{padding:14px;background:#fff0ee;border:1px solid #f0c6c0;border-radius:10px;color:#98291b}.logs{white-space:pre-wrap;overflow-wrap:anywhere;max-height:360px;overflow:auto;background:#edf1f8;padding:16px;border-radius:12px;font:12px/1.65 monospace}.known-editor{grid-column:1/-1}.known-editor .input{margin-top:6px}.editor-actions{display:flex;gap:15px;margin-top:10px}.editor-actions button{font:inherit;border:0;background:none;padding:0;color:#dfcaff;cursor:pointer}.known-editor .help{color:#d5dff0}.ready-summary{padding:20px;background:#f1ecfc;border-radius:14px;color:#4f4570;margin:0}.connection-editor .field{margin-top:12px;background:#fff;color:#173753}.connection-actions{display:flex;gap:15px;align-items:center;flex-wrap:wrap}.token-field{margin-top:16px}.connected{color:#d1f2e9}.secret-value{font-size:13px}.badge{font-size:10px;color:#d0bcfa}
|
|
2
|
+
@media(max-width:1000px){.layout{gap:28px;grid-template-columns:minmax(250px,.85fr) minmax(0,1.4fr)}.panel{padding:28px}.sidebar{padding:0 22px}.brand{padding-left:22px}.scene{padding:35px 24px}}
|
|
3
|
+
@media(max-width:700px){.scene{padding:20px 16px;background-attachment:scroll}.layout{display:block}.brand{margin-bottom:24px}.sidebar{margin-bottom:24px;padding-left:0;padding-right:0}.panel{padding:25px 20px}.panel h1{font-size:25px}.field{padding:17px}.primary{width:100%}}
|
|
4
|
+
|
|
5
|
+
.agent-activity.known-group{backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border:0;border-radius:13px;background:linear-gradient(110deg,rgba(38,60,116,.5),rgba(132,118,143,.5));overflow:hidden;margin-bottom:16px}.known-group-header{display:flex;align-items:center;gap:16px;padding:16px 15px 7px}.known-group-title{font-size:16px;margin:0;font-weight:700;line-height:1.3}.category-icon{width:36px;height:36px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;border-radius:11px;background:linear-gradient(135deg,#aa98ff,#e5d1ff);color:#412199;box-shadow:inset 0 0 8px #ffffff44}.category-icon svg{width:23px;height:23px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.workspace .category-icon{background:linear-gradient(135deg,#a2dbff,#4fa9f5);color:#0070df}.hosting .category-icon,.email .category-icon{background:linear-gradient(135deg,#0ed4b6,#31f2cf);color:#005761}.known-group-body{padding:6px 16px 13px 23px}.known-group .known-row:last-child{padding-bottom:0}#known-summary .known-label{font-size:11px}.known-row{min-width:0}.known-editor{min-width:0}.group-symbols{position:absolute;width:0;height:0;overflow:hidden}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(max-width:700px){.known-group-header{gap:12px}.known-group-body{padding-left:15px}.known-group-title{font-size:15px}}
|
|
6
|
+
|
|
7
|
+
#fields>.field[data-field]{border:0;border-radius:0;background:transparent;padding:0}#fields{gap:24px}.select-wrap{position:relative}.select-wrap:after{content:"";position:absolute;right:18px;top:50%;width:7px;height:7px;border-right:1.5px solid #64788e;border-bottom:1.5px solid #64788e;transform:translateY(-70%) rotate(45deg);pointer-events:none}.select-wrap select{appearance:none;-webkit-appearance:none;padding-right:44px}
|
|
8
|
+
|
|
9
|
+
.known-value{display:flex;align-items:center;gap:7px;min-width:0}.known-value-text{min-width:0;overflow-wrap:anywhere}.value-icon,.colour-swatch{width:18px;height:18px;flex-shrink:0}.colour-swatch{width:16px;height:16px}.value-icon{fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.colour-swatch{border-radius:4px;box-shadow:inset 0 0 0 1px #ffffff70}
|
|
10
|
+
|
|
11
|
+
.target-choices{border:0;margin:0 0 8px;padding:0;display:flex;gap:8px;flex-wrap:wrap}.target-choices legend{margin-bottom:7px;padding:0}.target-choice{display:flex;align-items:center;gap:6px;padding:8px 10px;border:1px solid #ffffff35;border-radius:8px;font-size:12px;cursor:pointer;position:relative}.target-choice:has(input:checked){background:#ffffff20;border-color:#69efd0}.target-choice input{position:absolute;opacity:0;width:1px;height:1px}.target-choice:has(input:focus-visible){outline:3px solid #b796ff;outline-offset:3px}.target-tick{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border:1px solid #ffffff60;border-radius:50%;color:transparent;font-size:11px;flex-shrink:0}.target-choice input:checked+.target-tick{background:#69efd0;border-color:#69efd0;color:#005761}
|
|
12
|
+
|
|
13
|
+
.panel .target-choices{margin:0}.panel .target-choices legend{color:#153b66;font-size:15px;font-weight:600}.panel .target-choice{color:#173753;border-color:#cdd6e5;font-size:14px}.panel .target-choice:has(input:checked){background:#e9e4ff;border-color:#7542d3}.panel .target-tick{border-color:#8296aa}
|
|
14
|
+
|
|
15
|
+
.colour-control{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.colour-control input[type="color"]{width:52px;height:42px;padding:3px;flex-shrink:0;cursor:pointer}.colour-caption{font-size:14px}.known-editor .colour-control{margin-top:6px}.known-editor .colour-control .input{margin-top:0}
|
|
16
|
+
|
|
17
|
+
.panel label.target-choice{display:flex;align-items:center;gap:10px;padding:10px 12px;margin:0;line-height:1.4;font-weight:500}.panel .target-choices{gap:10px}.target-choice .value-icon{display:block}
|
|
18
|
+
|
|
19
|
+
.hosting-unit{display:grid;gap:18px}.hosting-unit>.field{border:0;border-radius:0;background:transparent;padding:0}.hosting-unit>[data-provider]{border-left:3px solid #ded3f8;padding-left:16px}.hosting-unit .field[data-field]{margin-top:14px}.hosting-unit>.field[data-field]{margin-top:0}.hosting-unit>.status{margin:0}
|
|
20
|
+
|
|
21
|
+
.secondary:disabled{opacity:.5;cursor:default}
|
|
22
|
+
|
|
23
|
+
.email-unit{display:grid;gap:18px}.email-unit>.field,.advanced>.field{border:0;border-radius:0;background:transparent;padding:0}.email-unit>.help{margin:0}.choice-copy{display:block}.choice-copy .help{display:block;margin:5px 0 0;font-weight:400;font-size:12px}.hosting-unit>.target-choices .target-choice{flex:1 1 200px;align-items:flex-start}.hosting-unit>.target-choices .target-tick{margin-top:3px}.hosting-unit>.target-choices .value-icon{margin-top:2px}.connection-row .field-title{font-size:14px}.connection-row>.help{margin-top:0}.connection-row .secondary{min-height:36px;padding:7px 15px;font-size:13px}.advanced{font-size:13px}.advanced summary{color:#64788e}.advanced-toggle{display:flex;align-items:center;gap:8px;margin:15px 0 8px}.advanced .field{margin-top:8px}.panel .advanced>.field>label{font-size:13px}.panel .edit{color:#7542d3}.email-unit .target-choices legend{font-size:15px;font-weight:600;color:#153b66;margin-bottom:7px}
|
|
24
|
+
|
|
25
|
+
.step-progress{font-size:12px;color:#64788e;margin:0 0 8px}.actions{gap:12px}.actions #back{margin-right:auto}.known-group-header .edit{margin-left:auto;font-size:12px}.known-group-header .known-group-title{flex:1}#heading:focus{outline:none}
|
|
26
|
+
|
|
27
|
+
.agent-activity{min-width:0;padding-bottom:16px;background:rgba(0,0,0,.5)}.agent-activity .known-group-header{padding-left:16px;padding-right:16px;justify-content:space-between;gap:12px;flex-wrap:wrap}.agent-activity .known-group-title{min-width:0}.agent-activity-message{font-size:13px;line-height:1.55;margin:6px 16px 0;color:#f7f8ff;overflow-wrap:anywhere}.agent-activity-history{margin:10px 16px 0;color:#d5e4f3;font-size:11px}.agent-activity-history summary{width:fit-content}.agent-activity-events{padding-left:15px;margin:8px 0 0;line-height:1.5}.agent-activity-events li{padding:3px 0;overflow-wrap:anywhere}
|
|
28
|
+
|
|
29
|
+
.agent-connect{display:block;margin:0 0 0 auto;max-width:100%;padding:7px 12px;border:1px solid #ffffff80;border-radius:8px;background:transparent;color:#fff;font:600 12px/1.5 Inter,Arial,sans-serif;cursor:pointer}.agent-handoff{width:min(540px,calc(100vw - 32px));max-height:calc(100dvh - 32px);padding:26px;border:0;border-radius:20px;background:#fbfcff;color:#173753;box-shadow:0 18px 64px #001c3b55}.agent-handoff::backdrop{background:#001c3b80}.agent-handoff h2{margin:0;font-size:22px;line-height:1.3}.agent-handoff textarea{margin-top:18px;resize:vertical;font:12px/1.6 monospace;min-height:140px}.agent-handoff-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:18px}.agent-handoff .status{min-height:21px}.agent-handoff .primary{width:auto}@media(max-width:700px){.agent-handoff{padding:20px}}
|
|
30
|
+
|
|
31
|
+
.agent-working{display:inline-flex;align-items:center;gap:7px;margin-left:auto;color:#f7f8ff;font-size:12px;line-height:1.5;white-space:nowrap}.agent-working-spinner{width:12px;height:12px;border:1.5px solid #ffffff50;border-top-color:currentColor;border-radius:50%;animation:agent-working-spin .9s linear infinite}@keyframes agent-working-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.agent-working-spinner{animation:none}}
|
|
32
|
+
|
|
33
|
+
textarea.input{resize:vertical;min-height:100px}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
.primary{background:var(--installer-accent,#7542d3);color:var(--installer-accent-text,#fff)}
|
|
38
|
+
|
|
39
|
+
.known-summary{min-width:0;margin-top:16px;color:#173753}
|
|
40
|
+
.known-summary>summary{width:fit-content;max-width:100%;padding:9px 12px;border:1px solid #d2dcea;border-radius:9px;background:#f4f6fb;color:#224567;font-weight:600}
|
|
41
|
+
.known-summary[open]>summary{margin-bottom:12px}
|
|
42
|
+
.known-summary #known{min-width:0}
|
|
43
|
+
.connection-row .help{overflow-wrap:anywhere}
|
|
44
|
+
#stop-installation{margin-top:14px}
|
|
45
|
+
@media(max-width:700px){
|
|
46
|
+
.scene{padding:16px}
|
|
47
|
+
.layout{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
|
|
48
|
+
.brand{grid-column:1;grid-row:1;margin:0;padding:0}
|
|
49
|
+
.panel{grid-column:1;grid-row:2;padding:20px 18px}
|
|
50
|
+
.panel h1{font-size:24px;margin-bottom:16px}
|
|
51
|
+
.sidebar{grid-column:1;grid-row:3;display:grid;gap:12px;margin:8px 0 0;padding:0}
|
|
52
|
+
#form{padding-bottom:74px}
|
|
53
|
+
.actions{position:fixed;left:0;right:0;bottom:0;z-index:20;justify-content:flex-end;gap:10px;margin:0;padding:12px 16px calc(12px + env(safe-area-inset-bottom));border-top:1px solid #e0e8f6;background:#fbfcff;box-shadow:0 -8px 24px #001c3b18}
|
|
54
|
+
.actions .primary{width:auto;min-width:0;flex:1}
|
|
55
|
+
.actions .secondary{width:auto;flex:0 0 auto;padding-inline:16px}
|
|
56
|
+
.known-summary>summary{max-width:100%}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.target-choice .help{color:#42546b}
|
|
60
|
+
|
|
61
|
+
#known-summary .known-group{border:0;border-radius:13px;background:#f2f5fc;overflow:hidden;margin-bottom:16px}#known-summary .known-group.workspace{background:#eef7fc}#known-summary .known-group.hosting,#known-summary .known-group.email{background:#eaf8f6}#known-summary .known-label,#known-summary .known-source{color:#42546b}#known-summary .known-group-title,#known-summary .known-value{color:#173753}#known-summary .known-group .edit{color:#4d2e87}.help-link{color:#4d2e87;font-weight:600;text-decoration:underline}.failure-log-path{margin:12px 0 0;color:#42546b;font-size:12px;overflow-wrap:anywhere}#retry-installation{margin-top:14px}
|
|
62
|
+
|
|
63
|
+
h1,h2,h3,legend{text-wrap:balance}p,.help,.status,.known-source,.agent-activity-message,.choice-copy{text-wrap:pretty}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* Loaded only for a seed that declares a theme (rer-theme.css); every rule is
|
|
2
|
+
scoped to .rer-themed so an unthemed installer keeps style.css alone. */
|
|
3
|
+
.rer-themed body{color:var(--rer-text);font-family:var(--rer-font-body,Inter,Arial,sans-serif)}
|
|
4
|
+
.rer-themed .scene{background:var(--rer-page)}
|
|
5
|
+
.rer-themed .brand,.rer-themed .panel h1,.rer-themed .agent-handoff h2,.rer-themed .known-group-title{font-family:var(--rer-font-heading,var(--rer-font-body,inherit))}
|
|
6
|
+
.rer-themed .brand,.rer-themed .sidebar{color:var(--rer-text)}
|
|
7
|
+
/* content toggles the mark only when --rer-logo is declared; the background draws it at size. */
|
|
8
|
+
.rer-themed .brand{display:flex;align-items:center;gap:12px}
|
|
9
|
+
.rer-themed .brand::before{content:var(--rer-logo,none);display:block;flex:none;width:36px;height:36px;overflow:hidden;text-indent:200%;white-space:nowrap;background:var(--rer-logo) center/contain no-repeat}
|
|
10
|
+
.rer-themed .panel{background:var(--rer-surface);border-radius:var(--rer-radius,26px);box-shadow:0 1px 2px #0000000d,0 14px 36px #00000014}
|
|
11
|
+
.rer-themed .field label,.rer-themed .field-title,.rer-themed .panel .target-choices legend,.rer-themed .email-unit .target-choices legend{color:var(--rer-text)}
|
|
12
|
+
.rer-themed .input{border-color:var(--rer-border);background:var(--rer-surface);color:var(--rer-text);border-radius:calc(var(--rer-radius,20px) / 2)}
|
|
13
|
+
.rer-themed .input:focus-visible,.rer-themed button:focus-visible,.rer-themed a:focus-visible,.rer-themed summary:focus-visible,.rer-themed .target-choice:has(input:focus-visible){outline-color:var(--rer-focus)}
|
|
14
|
+
.rer-themed .help,.rer-themed .status,.rer-themed .step-progress,.rer-themed .advanced summary,.rer-themed .target-choice .help,.rer-themed .failure-log-path,.rer-themed .agent-activity-history,.rer-themed .known-editor .help{color:var(--rer-muted)}
|
|
15
|
+
.rer-themed .select-wrap:after{border-color:var(--rer-muted)}
|
|
16
|
+
.rer-themed .edit,.rer-themed .field .edit,.rer-themed .panel .edit,.rer-themed .help-link,.rer-themed #known-summary .known-group .edit,.rer-themed .editor-actions button{color:var(--rer-link,var(--rer-text))}
|
|
17
|
+
.rer-themed .primary,.rer-themed .secondary,.rer-themed .agent-connect{font-family:inherit;border-radius:var(--rer-radius,25px)}
|
|
18
|
+
.rer-themed .primary{background:var(--rer-accent,var(--installer-accent,#7542d3));color:var(--rer-accent-text,var(--installer-accent-text,#fff));box-shadow:none}
|
|
19
|
+
.rer-themed .secondary,.rer-themed .agent-connect{border:1px solid var(--rer-border);background:transparent;color:var(--rer-text)}
|
|
20
|
+
.rer-themed .logs,.rer-themed .ready-summary{background:var(--rer-page);color:var(--rer-text);border-radius:calc(var(--rer-radius,24px) / 2)}
|
|
21
|
+
.rer-themed .panel .target-choice{color:var(--rer-text);border-color:var(--rer-border)}
|
|
22
|
+
.rer-themed .panel .target-choice:has(input:checked){background:var(--rer-page);border-color:var(--rer-focus);box-shadow:inset 0 0 0 1px var(--rer-focus)}
|
|
23
|
+
.rer-themed .target-tick,.rer-themed .panel .target-tick{border-color:var(--rer-muted)}
|
|
24
|
+
.rer-themed .target-choice input:checked+.target-tick{background:var(--rer-accent,var(--rer-text));border-color:var(--rer-accent,var(--rer-text));color:var(--rer-accent-text,var(--rer-surface))}
|
|
25
|
+
.rer-themed .hosting-unit>[data-provider]{border-left-color:var(--rer-border)}
|
|
26
|
+
.rer-themed .connection-editor .field{background:var(--rer-surface);color:var(--rer-text)}
|
|
27
|
+
.rer-themed .agent-activity.known-group,.rer-themed .agent-activity,.rer-themed .known-group{background:var(--rer-surface);color:var(--rer-text);backdrop-filter:none;-webkit-backdrop-filter:none;border-radius:var(--rer-radius,13px);box-shadow:0 1px 2px #0000000d}
|
|
28
|
+
.rer-themed .agent-activity-message,.rer-themed .agent-working,.rer-themed .connected,.rer-themed .badge{color:var(--rer-text)}
|
|
29
|
+
.rer-themed .agent-working-spinner{border-color:var(--rer-border);border-top-color:currentColor}
|
|
30
|
+
.rer-themed .category-icon,.rer-themed .workspace .category-icon,.rer-themed .hosting .category-icon,.rer-themed .email .category-icon{background:var(--rer-accent,var(--rer-page));color:var(--rer-accent-text,var(--rer-text));box-shadow:none;border-radius:calc(var(--rer-radius,22px) / 2)}
|
|
31
|
+
.rer-themed .known-summary{color:var(--rer-text)}
|
|
32
|
+
.rer-themed .known-summary>summary{border-color:var(--rer-border);background:var(--rer-page);color:var(--rer-text);border-radius:calc(var(--rer-radius,18px) / 2)}
|
|
33
|
+
.rer-themed #known-summary .known-group,.rer-themed #known-summary .known-group.workspace,.rer-themed #known-summary .known-group.hosting,.rer-themed #known-summary .known-group.email{background:var(--rer-page);box-shadow:none}
|
|
34
|
+
.rer-themed #known-summary .known-label,.rer-themed #known-summary .known-source{color:var(--rer-muted)}
|
|
35
|
+
.rer-themed #known-summary .known-group-title,.rer-themed #known-summary .known-value{color:var(--rer-text)}
|
|
36
|
+
.rer-themed .agent-handoff{background:var(--rer-surface);color:var(--rer-text);border-radius:var(--rer-radius,20px)}
|
|
37
|
+
@media(max-width:700px){.rer-themed .actions{background:var(--rer-surface);border-top-color:var(--rer-border)}}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
// Art is requested only when the user commits a changed workspace field.
|
|
3
|
+
export function workspaceArt({ request, read, save, model: {fields} }) {
|
|
4
|
+
const contextKeys = Object.keys(fields).filter(key => fields[key].artwork);
|
|
5
|
+
const activeKeys = draft => contextKeys.filter(key => fields[key].visible?.(draft) !== false);
|
|
6
|
+
const signature = draft => JSON.stringify(activeKeys(draft).map(key => [key, draft[key]]));
|
|
7
|
+
let dirty = false, attached = false, lastRequested = '', committing = Promise.resolve();
|
|
8
|
+
return {
|
|
9
|
+
update(state) { attached = state.agent?.attached === true; },
|
|
10
|
+
edited(key) { if (contextKeys.includes(key)) dirty = true; },
|
|
11
|
+
commit() {
|
|
12
|
+
committing = committing.catch(() => {}).then(async () => {
|
|
13
|
+
if (!dirty) return;
|
|
14
|
+
const draft = read(), current = signature(draft);
|
|
15
|
+
await save();
|
|
16
|
+
if (signature(read()) !== current) return;
|
|
17
|
+
if (!attached) return;
|
|
18
|
+
if (!activeKeys(draft).every(key => {
|
|
19
|
+
const definition = fields[key].definition?.(draft) ?? fields[key];
|
|
20
|
+
return (definition.optional && !draft[key]) || definition.valid(draft[key]);
|
|
21
|
+
})) return;
|
|
22
|
+
if (current === lastRequested) { dirty = false; return; }
|
|
23
|
+
await request('/api/workspace-art', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' });
|
|
24
|
+
lastRequested = current;
|
|
25
|
+
if (signature(read()) === current) dirty = false;
|
|
26
|
+
});
|
|
27
|
+
return committing;
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
export function assertProductionCloudflare(env) {
|
|
6
|
+
for(const name of ['WRANGLER_API_ENVIRONMENT','CLOUDFLARE_API_ENVIRONMENT'])if(env[name]&&env[name]!=='production')throw Error('The selected Cloudflare environment is not supported by this installer.');
|
|
7
|
+
for(const name of ['CLOUDFLARE_API_BASE_URL','CF_API_BASE_URL'])if(env[name]&&env[name].replace(/\/$/,'')!=='https://api.cloudflare.com/client/v4')throw Error('The selected Cloudflare API address is not supported by this installer.');
|
|
8
|
+
if(env.CLOUDFLARE_COMPLIANCE_REGION)throw Error('The selected Cloudflare environment is not supported by this installer.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Wrangler 4.45.4's actual credential-file layout; no login, refresh, or profile switching. */
|
|
12
|
+
export async function legacyWranglerCredentials(version, { env=process.env, home=homedir(), platform=process.platform, now=Date.now() }={}) {
|
|
13
|
+
if (version !== '4.45.4') throw Error('This Wrangler version does not provide a supported credential reader.');
|
|
14
|
+
assertProductionCloudflare(env);
|
|
15
|
+
if (env.WRANGLER_PROFILE) throw Error('The selected Wrangler environment is not supported by the credential reader.');
|
|
16
|
+
const legacy=join(home,'.wrangler');
|
|
17
|
+
let directory;
|
|
18
|
+
try { if((await stat(legacy)).isDirectory())directory=legacy; } catch(error) { if(error.code!=='ENOENT')throw error; }
|
|
19
|
+
if(!directory){
|
|
20
|
+
const base=env.XDG_CONFIG_HOME || (platform==='darwin'?join(home,'Library','Preferences'):platform==='win32'?join(env.APPDATA||join(home,'AppData','Roaming'),'xdg.config'):join(home,'.config'));
|
|
21
|
+
directory=join(base,'.wrangler');
|
|
22
|
+
}
|
|
23
|
+
const text=await readFile(join(directory,'config','default.toml'),'utf8');
|
|
24
|
+
if(text.length>65536)throw Error('Wrangler credential file is too large.');
|
|
25
|
+
// Wrangler emits simple quoted TOML scalar values. Reject other encodings instead of guessing.
|
|
26
|
+
const scalar=key=>{
|
|
27
|
+
const matches=[...text.matchAll(new RegExp('^'+key+'\\s*=\\s*("[^"\\r\\n]*"|\'[^\'\\r\\n]*\')\\s*(?:#.*)?$','gm'))];
|
|
28
|
+
if(matches.length!==1)return undefined;
|
|
29
|
+
const value=matches[0][1];return value[0]==='"'?JSON.parse(value):value.slice(1,-1);
|
|
30
|
+
};
|
|
31
|
+
const token=scalar('oauth_token'),expires=Date.parse(scalar('expiration_time'));
|
|
32
|
+
if(typeof token!=='string'||!token||/[\r\n]/.test(token)||!Number.isFinite(expires)||expires<=now)throw Error('Wrangler credentials are missing or expired.');
|
|
33
|
+
return {type:'oauth',token};
|
|
34
|
+
}
|
|
35
|
+
export async function wranglerCredentials(root, env, run) {
|
|
36
|
+
assertProductionCloudflare(env);
|
|
37
|
+
const options={cwd:root,env:{...env,CI:'true',WRANGLER_SEND_METRICS:'false'}};
|
|
38
|
+
try { return JSON.parse(await run('wrangler',['auth','token','--json'],options)); }
|
|
39
|
+
catch {
|
|
40
|
+
const version=(await run('wrangler',['--version'],options)).trim();
|
|
41
|
+
return legacyWranglerCredentials(version,{env});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Operations manifests and command inspection
|
|
2
|
+
|
|
3
|
+
First-party seeds expose inspection through their portable RER command. From the
|
|
4
|
+
seed root:
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
rer describe --json
|
|
8
|
+
rer check --profile first-party --json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`describe` returns the command contract: profile, declared Node and pnpm pins,
|
|
12
|
+
exposed verbs and supported flags, effects, matching package aliases, and local
|
|
13
|
+
state/settings locations. It reads `OPERATIONS.json` and the declared command
|
|
14
|
+
adapter; it does not return the operations manifest itself or test environment
|
|
15
|
+
values.
|
|
16
|
+
|
|
17
|
+
`check` validates declared command input files and required enabled loops.
|
|
18
|
+
The first-party profile also enforces the manifest's `seedContract` marker,
|
|
19
|
+
adapter hooks and flags, command targets, package aliases, tool pins, complete
|
|
20
|
+
portable source inventory and copied source hashes. An explicit
|
|
21
|
+
`--profile first-party` rejects a missing marker. With `--json`, it emits a
|
|
22
|
+
result event containing `ok`, `exitCode` and individual clauses on stdout;
|
|
23
|
+
without it, failed clauses are printed for the owner. Exit 0 means the structural
|
|
24
|
+
checks passed; failures exit nonzero. Read the seed's `OPERATIONS.md` to resolve
|
|
25
|
+
manifest or source problems.
|
|
26
|
+
|
|
27
|
+
These commands require Node but no installed packages. They do not run setup,
|
|
28
|
+
deployment, verification, configuration validators, environment readiness checks
|
|
29
|
+
or network requests. Structural success does not establish installed tool
|
|
30
|
+
versions, configured local inputs, provider access, remote health or product
|
|
31
|
+
acceptance. `rer doctor --json` separately diagnoses installed
|
|
32
|
+
tools and local inputs through the manifest inspector.
|
|
33
|
+
|
|
34
|
+
## Internal manifest tooling
|
|
35
|
+
|
|
36
|
+
The shared `operations.mjs` and `project-operations.mjs` modules implement
|
|
37
|
+
`readOperations`, `describeOperations` and `inspectOperations` for RER and other
|
|
38
|
+
local consumers. They ship together under the portable source tree. Manifest
|
|
39
|
+
reading validates fields, referenced documents and configuration modules, and
|
|
40
|
+
resolves declared command inputs. `describeOperations` returns the operations
|
|
41
|
+
manifest after checking command availability; it is distinct from RER's public
|
|
42
|
+
command descriptor.
|
|
43
|
+
Run directly in a project that has `scripts/rer.mjs`, `operations.mjs describe`
|
|
44
|
+
and `check` forward to that `scripts/rer.mjs` with `describe` and `check`. In an
|
|
45
|
+
independent project without RER they print the inspector's own JSON and advice,
|
|
46
|
+
naming the script by the path it was run from.
|
|
47
|
+
|
|
48
|
+
`inspectOperations` checks required environment names, selected loop inputs and
|
|
49
|
+
an optional pure `validateConfiguration(env)` module. It reports input names
|
|
50
|
+
and suppresses validator details and values because parser exceptions may contain
|
|
51
|
+
credentials. Consumers can pair the reported input names with
|
|
52
|
+
`environmentSources` and operating documentation to guide setup. Missing inputs
|
|
53
|
+
need configuration before readiness can pass; malformed supplied values are
|
|
54
|
+
reported without exposing them. Inspection never executes the declared
|
|
55
|
+
setup, deployment or verification commands. Generated deployment caches and build
|
|
56
|
+
artifacts, provider identity and permissions, credential validity, delivery,
|
|
57
|
+
deployed health and acceptance remain unchecked.
|
|
58
|
+
|
|
59
|
+
An optional `environmentSources` map explains where declared inputs come from.
|
|
60
|
+
Keys must name declared inputs; values must be short, plain source guidance
|
|
61
|
+
without URLs or credentials. Add safe sources so owners can find inputs without
|
|
62
|
+
putting values in the descriptor.
|
|
63
|
+
|
|
64
|
+
Version 1 manifests require edition identity, `OPERATIONS.md`, `ACCEPTANCE.md`,
|
|
65
|
+
`scripts/operations-config.mjs` and valid package command declarations for setup,
|
|
66
|
+
deploy and verify. The adapter validates local configuration only. Version 2
|
|
67
|
+
supports project-owned commands and documents as described below.
|
|
68
|
+
|
|
69
|
+
Run `node --test operations/*.test.mjs` in Base. Composition copies the shared
|
|
70
|
+
modules from its pinned Base commit. Configuration adapters stay project-owned;
|
|
71
|
+
these modules do not create a shared deployment engine or change authentication.
|
|
72
|
+
|
|
73
|
+
## Independent projects (version 2)
|
|
74
|
+
|
|
75
|
+
The manifest inspector is optional tooling, not the RER management admission
|
|
76
|
+
contract.
|
|
77
|
+
Software can keep its own language, framework, package manager, source layout and
|
|
78
|
+
operating procedures. A project choosing this inspector can use `OPERATIONS.json`
|
|
79
|
+
version 2 without `edition.json`, `seed.json`, `package.json`, `pnpm`, or a fixed
|
|
80
|
+
acceptance filename. Copy both `operations.mjs` and `project-operations.mjs` together.
|
|
81
|
+
Version 1 uses the edition-specific requirements listed above.
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"version": 2,
|
|
86
|
+
"project": "publisher/project",
|
|
87
|
+
"runtime": { "requirements": [{ "name": "python", "version": ">=3.11" }] },
|
|
88
|
+
"requiredEnvironment": [],
|
|
89
|
+
"commands": {
|
|
90
|
+
"verify": {
|
|
91
|
+
"argv": ["python3", "tools/verify.py"],
|
|
92
|
+
"inputs": ["tools/verify.py"],
|
|
93
|
+
"effects": "Runs local checks; no remote writes."
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Command names and argument arrays are project-owned; consumers should invoke
|
|
100
|
+
them directly without an implicit shell. Manifest inspection never invokes them.
|
|
101
|
+
`inputs` lists checkout files required to invoke the command, including its
|
|
102
|
+
script or build manifest. Missing inputs make that
|
|
103
|
+
command unavailable. Absolute paths, traversal and symlinks outside the checkout
|
|
104
|
+
are rejected. Declare accurate effects, including provider writes, migrations
|
|
105
|
+
and destructive actions; a description is not execution authorization.
|
|
106
|
+
|
|
107
|
+
Optional `documentation.document` and `acceptance.document` reference project-owned
|
|
108
|
+
local documents. For a version 2 project, a declared `documentation.document`
|
|
109
|
+
pointer is the setup guidance named by the internal inspector summary; without
|
|
110
|
+
that pointer, it names the project setup documentation generally. If no setup command is declared, the
|
|
111
|
+
summary reports that and directs the owner to the available setup guidance.
|
|
112
|
+
Optional `configuration.module` references a local ES module
|
|
113
|
+
exporting `validateConfiguration(env)`. It must only validate local configuration;
|
|
114
|
+
`inspectOperations` imports and calls it, so inspect untrusted source before
|
|
115
|
+
running a diagnostic that uses it, including RER doctor.
|
|
116
|
+
Without a module, configuration checking covers required environment names only.
|
|
117
|
+
Runtime requirements are descriptive: neither command availability in PATH nor
|
|
118
|
+
installed versions are checked. All command inputs must be declared accurately;
|
|
119
|
+
the inspector does not infer arbitrary language or build-system dependencies.
|
|
120
|
+
|
|
121
|
+
An optional per-input source map can guide setup without putting values in the
|
|
122
|
+
descriptor or diagnostic output:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"requiredEnvironment": ["RESEND_API_KEY"],
|
|
127
|
+
"environmentSources": {
|
|
128
|
+
"RESEND_API_KEY": "1Password production vault, mail integration item"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
For v2, source keys may also name inputs selected by declared mail loops. Source
|
|
134
|
+
text is limited to 8–180 characters and rejects URLs, equals assignments,
|
|
135
|
+
credential labels containing values, and token-like values. Use a document pointer
|
|
136
|
+
such as `OPERATIONS.md` or plain guidance such as `Team vault: production mail item`;
|
|
137
|
+
never paste an environment assignment or credential into this metadata.
|
|
138
|
+
`inspectOperations` still reports local inputs only; remote deployment,
|
|
139
|
+
provider access, and acceptance remain unchecked.
|
|
140
|
+
|
|
141
|
+
Agents can adapt any software and author operating knowledge in its repository.
|
|
142
|
+
Provider targets must separately support and verify the actual declared effects,
|
|
143
|
+
resources, migrations and recovery. This local descriptor does not admit a project
|
|
144
|
+
to hosted execution, provision resources, or prove provider/runtime compatibility.
|
|
145
|
+
|
|
146
|
+
## Required loops (version 2)
|
|
147
|
+
|
|
148
|
+
A v2 descriptor may add a declarative `loops` array:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
"loops": [
|
|
152
|
+
{ "id": "ticket-replies", "type": "mail", "required": true, "enabled": true, "provider": "resend" },
|
|
153
|
+
{ "id": "nightly-summary", "type": "worker", "required": false, "enabled": false }
|
|
154
|
+
]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`inspectOperations` fails for required disabled loops, missing/blank selected
|
|
158
|
+
mail inputs or a conflicting `MAIL_PROVIDER`. SendGrid requires `SENDGRID_API_KEY`; Resend requires
|
|
159
|
+
`RESEND_API_KEY`; Cloudflare Sending requires `CLOUDFLARE_EMAIL_API_TOKEN` and a
|
|
160
|
+
32-hex `CLOUDFLARE_EMAIL_ACCOUNT_ID`. Other providers' keys cannot satisfy the
|
|
161
|
+
selection. Disabled optional features stay optional. This is a local input check,
|
|
162
|
+
not credential validity, DNS verification, delivery or remote runtime health.
|
|
163
|
+
|
|
164
|
+
A mail loop can instead declare `binding` to follow a runtime-selected provider
|
|
165
|
+
and project-owned environment names. `provider` and `binding` are mutually
|
|
166
|
+
exclusive. For example:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"id": "sign-in-mail",
|
|
171
|
+
"type": "mail",
|
|
172
|
+
"required": true,
|
|
173
|
+
"enabled": true,
|
|
174
|
+
"binding": {
|
|
175
|
+
"providerEnvironment": "MAIL_PROVIDER",
|
|
176
|
+
"providers": {
|
|
177
|
+
"sendgrid": { "apiKeyEnvironment": "MAIL_API_KEY", "requiredEnvironment": ["MAIL_FROM"] },
|
|
178
|
+
"resend": { "apiKeyEnvironment": "MAIL_API_KEY", "requiredEnvironment": ["MAIL_FROM"] },
|
|
179
|
+
"development": {
|
|
180
|
+
"requiredEnvironment": ["MAIL_FROM"],
|
|
181
|
+
"development": { "modeEnvironment": "ENVIRONMENT", "originEnvironment": "APP_URL" }
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"whenUnset": {
|
|
185
|
+
"provider": "resend",
|
|
186
|
+
"apiKeyEnvironment": "RESEND_API_KEY",
|
|
187
|
+
"requiredEnvironment": ["RESEND_FROM_EMAIL"]
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Every environment name must match `[A-Z][A-Z0-9_]*`. A nonempty `providers` map
|
|
194
|
+
supports `sendgrid`, `resend`, `cloudflare` and `development` only. Every provider
|
|
195
|
+
entry declares `requiredEnvironment` (an empty array is allowed). Hosted entries
|
|
196
|
+
also require `apiKeyEnvironment`; Cloudflare additionally requires
|
|
197
|
+
`accountIdEnvironment`, checked as 32 hex characters. Those account declarations
|
|
198
|
+
are exclusive to Cloudflare. Only the selected entry's inputs can satisfy its
|
|
199
|
+
readiness check. The inspector checks presence and the declared guard; a project's
|
|
200
|
+
configuration module remains responsible for its native sender and credential
|
|
201
|
+
validation. A required mail loop still fails when foundation-only configuration
|
|
202
|
+
is valid but mail has not been configured.
|
|
203
|
+
|
|
204
|
+
Optional `whenUnset` declares a hosted provider and its inputs with the same
|
|
205
|
+
shape. It applies only if the selector is absent (`undefined`), never for blank,
|
|
206
|
+
unknown or non-string selectors. It cannot select development. Without
|
|
207
|
+
`whenUnset`, an absent selector blocks readiness and names the selector input.
|
|
208
|
+
|
|
209
|
+
Development entries require `development.modeEnvironment` and
|
|
210
|
+
`development.originEnvironment` and cannot declare a credential. The mode must
|
|
211
|
+
be exactly `development`. The origin must be a canonical HTTP(S) loopback origin
|
|
212
|
+
(host exactly `localhost`, `127.0.0.1` or `[::1]`, with optional port and trailing
|
|
213
|
+
slash), without user information, path, query or fragment. Alternate numeric
|
|
214
|
+
hosts and normalization-dependent spellings are rejected. Preview, production
|
|
215
|
+
and remote origins cannot satisfy this guard. No host lookup occurs. This only
|
|
216
|
+
checks a declared development guard; it does not create or send to an outbox.
|
|
217
|
+
|
|
218
|
+
Malformed loop or binding fields, unknown properties and unsupported providers
|
|
219
|
+
are rejected even for disabled loops. Valid optional disabled loops continue to
|
|
220
|
+
pass; required disabled loops continue to block readiness. `environmentSources`
|
|
221
|
+
may name the selector and any input declared by any provider or `whenUnset`.
|
|
222
|
+
Missing-input guidance uses the actual selected names and their declared source;
|
|
223
|
+
Inspector results and summaries never include environment values. Both modules
|
|
224
|
+
ship together; no additional runtime adapter is needed.
|
|
225
|
+
|
|
226
|
+
The [deploy kit](../modules/deploy-kit/README.md) creates new v2 inspector and
|
|
227
|
+
edition-authoring templates without overwriting an existing edition. Both inspector
|
|
228
|
+
modules ship together.
|
|
229
|
+
|
|
230
|
+
## First-party command profile
|
|
231
|
+
|
|
232
|
+
OPERATIONS v2 may declare:
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
"seedContract": {
|
|
236
|
+
"version": 1,
|
|
237
|
+
"profile": "first-party",
|
|
238
|
+
"adapter": "scripts/installer/local.mjs"
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The adapter exports `commandAdapter` and `install`. First-party adopters use the
|
|
243
|
+
shared RER commands and contract described above. The manifest inspector retains
|
|
244
|
+
its environment, configuration and loop diagnostics for RER doctor; RER check
|
|
245
|
+
performs structural validation before dependency installation. Independent
|
|
246
|
+
projects retain their own supported argument arrays and stack.
|