Skip to content

Declare and certify a secret-free Tedix installation before provisioning begins.

Installation manifests

Source preview: The manifest engine and clean-account installation path are part of the private OSS release candidate. The referenced package and example files are not publicly downloadable yet, and this page is not a supported self-hosted release. See Release status.

@tedix/installation-manifest defines the versioned handoff from installation planning to provisioning. It describes organization profile, Cloudflare account and domain topology, Workers, routes, bindings, resources, provider prerequisites, capabilities, lifecycle requirements, and sanitized bootstrap inputs.

The manifest contains secret names only. Credentials remain in the operator’s secret provider and are injected after preflight. Runtime entitlements are independent from optional billing settlement metadata.

billingSettlement is explicit deployment policy. An omitted block generates TEDIX_BILLING_SETTLEMENT_MODE=disabled; configured external or managed mode is emitted unchanged. Disabled and external overlays do not require Stripe secrets. Managed Stripe settlement fails overlay generation unless the live and test API-key and webhook-secret names are declared. The overlay also projects the manifest’s entitlement grants through the non-secret TEDIX_RUNTIME_ENTITLEMENT_GRANTS JSON variable.

fleetAuthority.mode is also required and is emitted as TEDIX_FLEET_AUTHORITY_MODE. The sanitized developer/OSS manifest uses disabled, emits no FLEET_DB, and requires no Stripe or fleet secret names. co-located requires the worker’s DB binding. Reserved service mode requires an explicit D1 binding named FLEET_DB; API runtime calls still fail closed until all classified fleet owners have moved, so declaring the binding is not a claim that the separate service is operational.

Installation authority is also distinct from tenant and fleet authority. The machine-checked map in scripts/oss/authority-classification.json keeps runtime entitlements in tenant-product, puts bootstrap, upgrade, backup, restore, and installation-owner health in installation-operations, and reserves Stripe, provider settlement, reconciliation, global catalog promotion, and cross-installation administration for fleet-commercial. An installation manifest may supply coordinates for enabled planes; it does not merge their authority or make commercial settlement a prerequisite for tenant entitlement enforcement.

Certification

Import parseInstallationManifest or certifyInstallationManifest from @tedix/installation-manifest/schema. A document marked certified is rejected when it has unresolved coordinates, unavailable required capabilities, a profile/access-plan mismatch, missing required entitlements, or an unready required provider. Issues are sorted deterministically for CI and automation.

The execution policy is fixed to fail-before-mutation: provisioning tools must validate and certify the complete manifest before creating or changing any resource. The package also exposes deterministic JSON Schema generation for systems that do not execute TypeScript.

Use @tedix/installation-manifest/developer-example as a sanitized reference. It uses example-only coordinates and contains no production installation IDs or secret values. It is intentionally uncertified at the schema-valid level; schema evidence is not clean-account or installation-ready certification.

Account capability preflight

Import preflightCloudflareAccount from @tedix/installation-manifest/preflight to verify a live Cloudflare account before provisioning. The preflight is strictly read-only: it issues only GET requests, and callers must refuse to provision when the returned mutationAllowed is false. It checks that every declared account is reachable with the supplied token, that each account exposes every product capability the declared resources need (D1, R2, KV, Durable Objects, Workflows, Queues, Workers, Browser Rendering, Workers AI, Vectorize, Hyperdrive, Containers, assets), and that every declared zone exists, contains its declared hostname, and belongs to its declared account.

Every manifest resource kind maps to exactly one probe; adding a resource kind to the schema without deciding its probe fails compilation, so a required dependency can never be silently omitted. Unresolved account or zone coordinates fail the preflight without any network call. Optional-resource capabilities that are missing are recorded but do not block.

For a disposable-account certification, set freshAccount: true on the target account. The same read-only preflight then verifies that Worker scripts and every declared resource inventory with a Cloudflare list endpoint are empty. A non-empty inventory fails before provisioning, so an old alpha environment cannot be misrepresented as a fresh-account result.

Run bunx wrangler login once using your own Cloudflare account. Then bun run preflight --manifest <path> (in packages/installation-manifest, --json for machine output) runs the same read-only check and exits non-zero when a required capability is missing. The CLI reuses Wrangler authentication through its supported auth token --json command; Tedix does not read Wrangler’s private credential files or store a second copy. An explicit CLOUDFLARE_API_TOKEN takes precedence for automation. Global API key/email authentication is not supported by these bearer-token installation tools. The manifest, not the login, selects the target account. --help needs no credentials and does not make network calls.

Identity-provider readiness

An interactive Tedix OS also needs an operator-owned Descope project. For alpha and beta rehearsal, use a dedicated non-production project instead of reusing a shared production identity project. This keeps test users, approved origins, flows, keys, and later cleanup inside the installation being tested.

For provisioning, declare OS_URL and DESCOPE_PROJECT_ID in the manifest’s OS worker vars. Optional DESCOPE_BASE_URL defaults to https://api.descope.com. Both URL values must be canonical HTTPS origins: no ports, credentials, paths, queries, fragments, or trailing slash. The provisioning path supports one OS worker (multiple surfaces may reference it) and refuses missing, malformed, or ambiguous targets before provider or Cloudflare requests.

Create a temporary, project-scoped management key with read access to project configuration. provision --apply needs only DESCOPE_MANAGEMENT_KEY from the environment for identity checks; the manifest supplies the target. For a standalone diagnostic independent of provisioning, run:

DESCOPE_PROJECT_ID=your-project-id \
DESCOPE_MANAGEMENT_KEY=temporary-project-key \
TEDIX_OS_URL=https://os.example.workers.dev \
bun run --cwd packages/installation-manifest identity:preflight

The report lists the supplied OS hostname and its expected login URL:

Surface Approved Web Domain Redirect URL
Tedix OS os.example.workers.dev https://os.example.workers.dev/login

Approved Web Domains contain hostnames only — no scheme, path, or trailing slash. The preflight checks the project’s OIDC issuer, verifies the management key by exporting project configuration, confirms every exact hostname, and checks that the sign-up-or-in flow exists and is enabled. It also verifies that the project-level owner, admin, member, and viewer roles grant tedis:read, which an authenticated Tedix OS needs to load its workspace. Descope exposes project export as an HTTP POST, but it is a read operation: Tedix does not call project import, update, or key-management endpoints. Revoke the temporary key after validation; treat diagnostic output as potentially sensitive.

For a manifest that requires Descope plus Tedix OS, provision --apply requires a passing identity report before the Cloudflare account preflight and before any resource mutation. Plan mode remains read-only and does not require identity credentials.

This is a configuration check, not deployed authentication certification. It does not verify redirect registration, execute the login flow, or exercise broker callbacks, cookies, tenant selection, session renewal, or logout. Provisioning checks the manifest OS worker’s declared configuration, not deployed routes or browser build settings. Those must still agree with it.

The current OS hostname resolver and session-broker origin allowlist remain Tedix-host-specific; the broker’s Descope refresh-cookie twin also names auth.tedix.dev. Therefore an approved workers.dev hostname and a passing identity report do not make independent OS login work. Installation-owned routing, login/broker origins, and the matching authentication cookie topology must be implemented together, then verified in a live browser. workersDev controls Worker exposure only; it is not an authentication setup switch.

Deployment profiles

@tedix/installation-manifest/profiles defines what each supported profile — developer, smb, enterprise — must declare before it can be certified profile-ready. Requirements are additive: SMB includes developer plus an operator UI surface (Tedix OS), a required queue, and lifecycle backup; enterprise includes SMB plus required browser capability and governed workstation containers, and a mandatory restore test. Every profile requires the identity provider prerequisite and lifecycle export — customer-owned data contracts are part of the product promise, not an upsell.

certifyProfileReadiness(manifest) checks a manifest against its declared profile and returns deterministic, sorted issues; this is what the profile-ready certification level means before any live-account proof. The sanitized developer example passes for developer and reports exactly the missing surfaces and requirement upgrades when re-declared as a higher profile.

Resource provisioning

Import provisionCloudflareResources from @tedix/installation-manifest/provision to materialize the manifest’s account-level resources. It runs the capability preflight first and refuses to act when that fails, honoring fail-before-mutation. The default plan mode stays strictly read-only and reports the action an apply run would take per resource; apply creates missing resources idempotently and adopts existing ones instead of recreating them, resolving unresolved coordinates from the created ids.

Every resource kind has exactly one compile-time-checked provisioning path: D1, R2, KV, Queues, and Vectorize are API-creatable; Durable Objects, Workflows, services, assets, and containers are deploy-owned (materialized by deploying the declaring Workers, reported but untouched); Browser Rendering and Workers AI are account capabilities proven by the preflight; Hyperdrive requires operator-held origin credentials and is only verified.

executeD1Statements runs ordered SQL against a provisioned D1 database over the REST API, stopping at the first failure — the sanctioned path for migrations and sanitized seed data, whose SQL always comes from the caller’s tracked files, never from this package. bootstrapPlan derives the sanitized seed profile, secret-free bootstrap inputs, and target D1 resources from the manifest.

bun run provision --manifest <path> (in packages/installation-manifest) uses the same Wrangler login or explicit API token and prints the plan; mutation requires the explicit --apply flag, and --json emits the machine-readable report. Interactive apply reads only DESCOPE_MANAGEMENT_KEY for the identity check above. The former --os-url, --descope-base-url, and --descope-management-api-base provisioning flags are removed; target settings belong in the manifest, not parallel command-line or environment overrides. Provisioning creates resources, not a complete running installation; it does not deploy Workers or replace the remaining bootstrap and identity setup.

Backup, restore, and upgrade

@tedix/installation-manifest/lifecycle implements the manifest’s lifecycle promises against a live account: exportD1Database (the polling export protocol, returning the SQL dump), restoreD1Database (statement-split restore through the same caller-supplied-SQL path the bootstrap uses), verifyD1Restore (per-table row-count diff enumerated from the source schema, so a missing table fails instead of narrowing the check), r2BackupRoundtrip (write → copy under a backup prefix → byte-compare), and applyD1Upgrade (migration statements plus a schema verification against a restored database — recovery must accept the next upgrade, not just serve reads). All network access is injectable; tests never leave the process.

Wrangler overlays

Each worker declares a workspace-relative authored sourceConfig and its installation-specific non-secret vars. Import createWranglerOverlay from @tedix/installation-manifest/wrangler-overlay to combine that manifest with the authored Wrangler JSONC for one worker and installation environment.

workersDev is an explicit per-worker installation decision. The overlay discards an authored workers_dev setting and uses the manifest value, so a fresh-account rehearsal can intentionally expose a worker at its account’s <subdomain>.workers.dev hostname without requiring a DNS zone. Set it to false for a custom-domain-only worker.

The generator strips authored env branches and all source account, worker, route, var, secret, binding, and resource coordinates before applying the manifest. It preserves non-coordinate runtime structure, including main, compatibility flags, observability, placement, triggers, and Durable Object migrations. Output is deterministic Wrangler-compatible JSON; required secret names are returned separately and secret values are never emitted.

Preview mode permits an uncertified schema-valid manifest but rejects unresolved coordinates. Deploy mode requires a successfully certified manifest at installation-ready or operational. The tracked apps/api/wrangler.oss-example.json and matching .secrets.json name artifact are regenerated with bun run installation-manifest:overlay; CI enforces drift with bun run installation-manifest:overlay:check.

These generated files are sanitized public preview artifacts, not deployment or clean-account certification. Managed production coordinates are never published: the export rewrites every published wrangler.jsonc to a sanitized public base with no account, zone, or resource identifiers, and the development repository that holds the authored configuration stays private. See Release status.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close