Architecture decisions
The six accepted OrkStage ADRs in brief. Placement slots, provider adapters, BullMQ workflows, tenancy, OpenTofu state and the toolchain.
Architecture decision records (ADRs) live in docs/adr/ of the platform repository. Each summary
below links to the full record.
0001 Per resource placement through template slots
Accepted. Templates are shared across tenants, but each tenant has its own cloud accounts. So the provider, account and region cannot live in the template.
Instead, a template declares placement slots, each with a list of allowed providers. Every
resource names a slot, and every instance binds each slot to { targetId, region }. The same
template runs on one cloud or on several, depending only on the bindings. Networks bind only to
resources in the same slot.
Read ADR 0001
0002 Provider adapters, capability catalogs and simulation
Accepted. CloudProviderAdapter is the only way the platform touches a cloud. Its
ensureResource call converges a resource to the desired state, so a retry cannot create a
duplicate.
The mapping from a logical resource to a provider implementation is data: capability catalogs
that list features, regional gaps and static prices. A deterministic mock provider simulates
AWS, Azure or OCI with injectable failures, and the platform labels everything it simulates. One
shared contract test suite runs against every adapter.
Read ADR 0002
0003 Deployment workflow on BullMQ with persisted steps
Accepted. Temporal would add a cluster to operate. BullMQ reuses the Redis and Postgres that the platform already requires.
A job carries only the deployment id. Steps are database rows, created when the deployment is requested and updated before and after each action. Resuming a deployment means running the same job again, which skips the phases that already finished. Temporal is worth another look if long flows that wait on people, or very large fan out, appear. Read ADR 0003
0004 Tenancy, sessions and authorization
Accepted. All tenants share one database, and every row a tenant owns carries a tenantId.
Isolation works in four layers: the request principal, query scoping by membership, a CASL check
on the loaded record, and the audit log. A record from another tenant is reported as not found.
CASL rules are defined once. The API enforces them, and the console receives them only to decide what to show. Sessions are opaque and stored on the server, not JWTs. OIDC providers are plain configuration. Read ADR 0004
0005 OpenTofu execution and state
Accepted. Every tofu command runs in a throwaway container with a pinned image. Credentials
exist only in that container's environment.
Each resource has its own state file in S3, locked with use_lockfile and encrypted. This keeps
the platform's own DAG and isolates a failure to one resource. State holds no secrets: passwords
come from ephemeral resources and travel through write only attributes. The same code serves real
AWS and MiniStack.
Read ADR 0005
0006 Toolchain choices
Accepted.
- pnpm workspaces without Turborepo, because development machines block native binaries from
node_modules. - TypeScript 7.
- Prisma 7.10, not the 8.0 release candidate.
- Zod 4, shared by request validation, the OpenAPI document and console forms.
- ESM everywhere.
0007 Profiles, tenant limits and template tags instead of plans
Accepted.
Plans and their entitlements are gone. Each tenant has optional limits that platform owners and
admins set, and feature flags decide whether its templates may use several clouds, several
regions, autoscaling and custom domains. Templates carry free form tags instead of a list of plans
and a size profile (spec.plans and metadata.profile are ignored with a warning for one
release). Named profiles of accounts and regions per environment replace the default cloud
targets: new instances bind the slots they leave unbound from a profile.
Read ADR 0007
Writing a new ADR
Copy the structure of an existing record: Status, Context, Decision and Consequences. Give it the next number and keep it short. To change an accepted decision, write a new ADR that supersedes it instead of editing the old one.
Repository map
The focused repositories that make up OrkStage, what each one publishes, how they depend on each other, and the workspace that brings them together.
Code of conduct
OrkStage follows the Contributor Covenant 2.1. The behaviour expected in every project space, and how to report a problem privately.