Skip to content

Installation manifests

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

Agent setup

Self-hosting is experimental; see Release status.

@tedix/installation-manifest helps you check an installation plan before creating Cloudflare resources. Start by listing the organization, its Cloudflare account and domains, the services it needs, and its setup requirements. The manifest also records lifecycle needs and safe setup 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.

Managed settlement finds every Stripe price by lookup key; no Stripe product or price id is stored in the installation. The Stripe account (live or test, matching TEDIX_STRIPE_MODE) needs an active EUR price for each key:

  • plans: tedix_growth_month_v4, tedix_growth_year_v4, tedix_business_month_v4, tedix_business_year_v4, tedix_enterprise_month_v4, tedix_enterprise_year_v4;
  • metered overage: tedix_token_overage_v4;
  • capacity packs: tedix_inference_capacity_daily_1m_v2, tedix_inference_capacity_daily_5m_v2, tedix_inference_capacity_daily_10m_v2, tedix_inference_capacity_daily_25m_v2, tedix_inference_capacity_daily_50m_v2.

apps/api/scripts/billing/reconcile-stripe.ts --apply creates every one of these prices; without --apply it lists the missing ones. The overage price is metered only for organizations whose owner or admin has turned overage on with a monthly cap; see Usage limits and overage.

fleetAuthority.mode is also required and is emitted as TEDIX_FLEET_AUTHORITY_MODE. The sanitized developer/OSS manifest uses disabled and requires no Stripe secret names. co-located requires the worker’s DB binding. No other mode is accepted.

Installation authority is also distinct from tenant and fleet authority. Runtime entitlements stay in tenant-product; bootstrap, upgrade, backup, restore, and installation-owner health are installation-operations; Stripe, provider settlement, reconciliation, global catalog promotion, and cross-installation administration are fleet-commercial (see Cloudflare architecture). 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, so a required dependency is never silently skipped. 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 a used account cannot pass as a fresh one.

Run bunx wrangler login once using your own Cloudflare account. Then bun run --cwd packages/installation-manifest preflight --manifest <path> (--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. While evaluating, 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 interactive provisioning, declare OS_URL, SESSION_BROKER_URL, DESCOPE_BASE_URL, and DESCOPE_PROJECT_ID in the manifest’s OS Worker vars. Declare one apps/session-broker/wrangler.jsonc Worker with those same four values. DESCOPE_BASE_URL and SESSION_BROKER_URL must name the same auth origin, distinct from OS_URL: Descope’s bootstrap cookie and the broker’s refresh rotation share that host. URLs must be canonical HTTPS origins with no ports, credentials, paths, queries, fragments, or trailing slash. Interactive apply refuses missing, malformed, split, 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 OS and broker runtime consume those exact installation origins. The browser build must receive the same values through its Wrangler overlay or TEDIX_BUILD_OS_URL and TEDIX_BUILD_SESSION_BROKER_URL. The OS Worker serves the exact launcher host; it does not infer tenant subdomains from a workers.dev hostname. A passing provider report and source-level host tests still do not prove independent login, tenant selection, session renewal, or logout. Those need an operator-owned Descope custom auth domain, deployed Workers, and live browser proof on the installation’s endpoints. 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 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 --cwd packages/installation-manifest provision --manifest <path> 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. Target settings come only from the manifest. 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).

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 its matching .secrets.json list of secret names are regenerated with bun run installation-manifest:overlay.

These generated files are sanitized examples, not deployment or clean-account certification. Managed production coordinates are never published: every checked-in wrangler.jsonc is an example with placeholders instead of account, zone, or resource identifiers, and the private operations repository holds the live configuration. See Release status.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close