Delivery and environment rules
Environments
An environment is a stage of the product, such as production or staging. It is two GCP projects:
- The workload project runs the product.
- The platform project holds everything long-lived. Examples: Terraform state, image registries, the CI identity.
An environment's tier is how close it is to production. These are the tiers, highest first: production,
staging, devel.
| Environment | Workload project | Platform project |
|---|---|---|
production |
production-492618 |
platform-production-510011 |
staging |
staging-505318 |
platform-staging-506908 |
devel |
devel-466814 |
platform-staging-506908 |
productionMUST NOT share its platform project.- Every other environment MUST use
staging's platform project. This is by design. - DO NOT create a third platform project.
platform-productionandplatform-stagingname platform projects, not environments. Their env files apply the platform project's own units.
ENV-1: An environment is a complete, self-contained stack
- An environment MUST own every service it needs, data plane and control plane, in its workload project.
- This includes the API backend clients call and the identity store they authenticate against.
- Everything long-lived MUST live in the environment's platform project.
- A resource one environment owns in a shared platform project MUST carry the environment's name as a prefix. A resource shared by design, such as an image registry, does not.
- DO NOT borrow a piece of another environment's workload project.
Enforcement: Review only, plus the isolation check at stand-up.
ENV-2: No cross-environment wiring
- A service's rendered configuration in environment X MUST NOT name a host, database, queue, bucket, project or secret of another environment's workload project.
- In a shared platform project, X MUST use only its own resources, its own state prefix and what is shared by design.
- DO NOT reference another environment's platform resources or state.
Enforcement: Review only, plus the isolation check at stand-up.
ENV-3: Parity of shape, not of capacity
- A non-production environment's workload project MUST run the same services, topology and region as
production's. - You MUST size it down through per-environment variables.
Enforcement: Review only.
ENV-4: Dependencies point up
- An environment MAY depend on what a higher-tier environment shares with it.
- An environment MUST NOT depend on a lower-tier environment.
- An environment MAY use only what another environment shares explicitly.
productionis the highest tier. It MUST NOT depend on any other environment.
Example: devel pulls images from the registries in staging's platform project.
Enforcement: Review only.
ENV-5: Promotion is a pin change, never a rebuild
- You MUST promote an artefact by committing a change to the target environment's pin.
- DO NOT rebuild per environment.
- Rollback is the same operation backwards.
Enforcement: Review only. Production still deploys manually. See environments.
ENV-6: Do not name a new environment production
DO NOT name an environment production. The name switches on the production-only settings and the deletion protection
in gcp/common.hcl.
Enforcement: the is_production check in gcp/common.hcl.
Credentials and access
SECURITY-1: No long-lived credentials
- CI MUST authenticate by Workload Identity Federation.
- An operator MUST use their own ADC.
- DO NOT create a long-lived service-account key.
Enforcement: sops-find-unencrypted-secrets for the plaintext case. Review only otherwise.
SECURITY-2: No standing administrative access
- Production admin rights MUST be elevated on request, time-boxed and audited.
- DO NOT hold them permanently on a laptop.
Enforcement: Review only, on IAM changes. See
/people.
SECURITY-3: Secret material MUST be unique per environment
- You MUST generate a secret fresh for the environment that uses it.
- DO NOT copy one from another environment.
Enforcement: Review only.
SECURITY-4: Secrets in the repository MUST be sops-encrypted
- Runtime secrets MUST live encrypted in
infra/inventory/<env>/config.yml. - You MUST register the merge driver once per clone:
git config --local include.path ../.gitconfig. See SOPS.
Enforcement: sops-find-unencrypted-secrets and detect-private-key (pre-commit).
SECURITY-5: One credential model, no side doors
- The same federated identity that pushes an image MUST pull the base images it builds on.
- DO NOT add a second credential for one workflow's convenience.
- If a workflow genuinely needs its own identity, then scope it to that job.
Enforcement: Review only.
Changing infrastructure
INFRA-1: Infrastructure is applied by CI, from a merged commit
- This binds every environment, not just production.
- DO NOT run
terragrunt applyfrom a laptop. - Emergencies and first stand-ups are legitimate. Announce them at the time, then reconcile into a merged commit.
Enforcement: Review only. CI-driven apply is being built.
INFRA-2: All modules MUST be Terragrunt-managed
- A new module MUST be a Terragrunt unit from the start.
- The rest MUST migrate on a stated deadline.
Enforcement: Review only. Deadline tracked in current state of the architecture.
INFRA-3: Drift MUST be detected on a schedule
- A scheduled plan MUST report drift.
- Unexplained drift is an incident, not a nuisance.
Enforcement: none. See enforcement gaps.
INFRA-4: Nothing new in _modules/gcp/legacy
- DO NOT add to it.
- It MAY shrink into new or existing Terragrunt units.
Enforcement: Review only.
INFRA-5: Environment differences are variables, not conditionals
- Every knob that differs between environments MUST be a per-environment
TF_VARininfra/terraform/envs/<env>.env. - DO NOT branch on the environment name inside a module. ENV-6 is the one place we do.
Enforcement: Review only.
INFRA-6: IP ranges come from the address plan
- You MUST take a new environment, subnet or peering range from the address plan.
- You MUST record it there in the same change.
- Ranges MUST NOT overlap. VPC peering and the tailnet both break on an overlap.
Enforcement: Review only.
INFRA-7: Terraform state lives in the environment's platform project
- An environment MUST keep its Terraform state in its platform project's bucket,
<platform project>-terraform-state. - The state MUST be stored with an environment-specific prefix.
- A unit's state MUST live at
<env>/<unit>/terraform.tfstate.root.hclderives it fromTF_VAR_lyceum_env. platform/state_bucketMUST manage every state bucket.- An environment's identities MUST get access to their own prefix only. DO NOT grant a bucket-wide role.
- DO NOT add state to
lyceum-terraform-state. It is deprecated, and it is deleted once nothing uses it.
Enforcement: root.hcl for the prefix. Review only otherwise. See
enforcement gaps.
Related
- Deploying services: the mechanics for
systemdservices. - Bootstrapping platform images
- Environments: what exists, where images live, how a version is promoted.