Implementation preview: these instructions describe locally verified development work that is not yet included in a published Webdock core release. Use them only with the matching implementation; the currently published main branch does not include all commands and paths below.
mail, hosting, databases and storage. Billing has been removed; there is no replacement billing plugin. Configuration controls product availability. It does not grant tenant membership, buy a plan, create provider accounts or provision infrastructure.
The core identity, customer/project registry, memberships, plans and usage surfaces remain separate from optional products. Existing resource allowance administration remains available; payment checkout, invoices and provider subscription management are not part of the core. See self-hosting for the container and Helm distribution, and authentication adapters for browser-provider selection.
Select modules
SetWEBDOCK_MODULES on the API and each worker, with the same configuration across replicas. Console receives the public state from its authenticated API session; there is no independent Console module switch or public build variable.
billing and cms entries and their API/worker ownership before upgrading. For a fresh core-only installation:
enabled and state fields, and unsupported configuration versions fail validation. Helm accepts the same configuration as a structured modules object and serializes it for the runtime. Its strict schema is generated from the runtime manifests.
Assign route and worker ownership
WEBDOCK_API_DOMAINS and WEBDOCK_WORKER_DOMAINS select process responsibilities independently of module activation. A module is unavailable in Console when the API does not own its domain. Canonical origin, authentication foundation and domain-dependency checks still apply.
These are ownership names, not a complete API-domain configuration: enabled routes may also require Auth, Portal, Registry or integration domains. Workers require an explicit supported domain list and reject disabled modules. A core-only installation starts no worker. Enabling a module never supplies provider credentials or grants an agent additional privileges.
Choose a lifecycle state
Use eitherenabled or state per entry.
Disable an existing module safely
1
Drain all replicas
Roll out
draining everywhere and stop older replicas that still admit provisioning. Keep the responsible workers and agents running for accepted work, delivery and reconciliation.2
Resolve retained resources
Use existing authorized workflows to finish, hand over or explicitly remove resources. Suspension retains data. Resolve uncertain provider writes, pending jobs and active bindings; a configuration change does not perform cleanup.
3
Disable and remove worker ownership
Set the module to
disabled and remove its worker assignment. Startup refuses retained resource rows, unfinished operations, missing preflight policies and incomplete database checks. Apply the required migrations before changing state.4
Preserve durable state
Retain encryption/signing keys, schemas, journals and required storage. Re-enabling does not move resources or change their provider/account bindings. Database migration, backup and deletion are separate workflows.
Develop a module
Modules do not import applications or discover runtime credentials through ambient configuration. API wrappers supply authorization, persistence, encryption and provider ports. Client entrypoints contain public DTOs and presentation; cookies, database credentials and provider secrets stay server-side. Existing server actions remain authenticated boundaries, and tenant/resource keys reset action results when context changes.
These legacy product modules remain known at build time. New runtime plugins use the separate signed manifest, isolated container and capability API; making a module optional does not make it an isolated runtime plugin. Existing compatibility exports, decimal string IDs, OAuth issuer, Studio protocol URLs and MCP audiences remain stable. Better Auth compatibility and explicitly configured Clerk use the same local authorization model; changing browser providers does not migrate identities or entitlements automatically.
Verify a change
From a configured checkout using local development:@webdock/api runs in apps/control-plane, and @webdock/admin runs in apps/console. Use the owned disposable database fixture and restricted-role suites for permission changes; never run integration tests against customer databases. Existing providers are the current scope. New cloud services, including AWS/GCP additions, are outside this work.
Provider directory layout
Adapters are grouped by product area and provider:adapters/hosting/vercel, adapters/hosting/github, adapters/mail/turbosmtp, adapters/databases/postgres, adapters/storage/vercel. Trusted authentication plugins live in packages/auth-better-auth and packages/auth-clerk; provider configuration lives in packages/auth-configuration, outside the core. Kubernetes runtime metadata is in adapters/hosting/kubernetes; its Python executor stays in agents/kubernetes.
The root workspace pattern is adapters/*/*. Area directories do not become packages. Import stable package names such as @webdock/adapter-hosting-vercel/projects; the filesystem grouping does not rename npm packages or protocol routes. Product policy belongs in modules, shared contracts in packages, and provider-specific I/O in these adapter leaves.