workload_deployer — version 1.0
Source: presets
Purpose
One deployer identity per customer team. A Google project of the team's own holds the service account its pipelines run as and the bucket its states live in, and the account holds the roles it needs to roll out folders and Google projects under the workload folder — nothing more.
A team rolls out many Google projects and folders with templates of its own, in OpenTofu or
in Satz, each with its own state; it never runs as the organisation's IaC account. One entry
of workload_deployers, { name = "platform" group = "gcp-project-admins@example,
is one team — bound in the estate, or requested by the team as contributes
in a small pack of its own, checked with satz check-request and vendored by pull request.
name is lowercase letters, digits and -, starting with a letter; group is the address
of the group that may become the account; folder is the parent the team creates under,
google unless the entry names another.
PER ENTRY. The team's infrastructure project {customer under
deployer_project_folder, billed to the infrastructure billing account, with the APIs a
deployer's calls need. Inside it the account svc-deploy-<name> and the state bucket
{customer, which the account may write; the group reads the
project and may become the account — that account only.
WHAT THE ACCOUNT MAY DO. On the parent folder, deployer_folder_roles: create and manage
folders and Google projects under it, set their IAM and enable their APIs. On the billing
account, deployer_billing_roles: link a new project to it. On the organisation,
deployer_organization_roles — roles/browser and nothing else by default: the interface
looks the workload folder up by its name among the organisation's folders, and that listing
needs resourcemanager on the organisation; without it the team's plan stops at
the lookup. The three lists are params, so a customer changes the set without a fork.
MORE PARENT FOLDERS. A team that creates under several folders gets one entry of
workload_deployer_folders per further parent, { name = "platform-shared" deployer = "platform" folder = "google_folder.shared.name" }, which grants deployer_folder_roles on that folder
to the team's account.
WHO RUNS WHAT. The team's pipeline impersonates svc-deploy-<name> and keeps its state in
the team's bucket; the organisation's state is never read — a looked-up value asks the
Google API for the live resource. The account's address is the pattern above; the pack
exports no interface.
NO CLAIM. The teams' identities are workloads, not controls: this pack witnesses nothing.
Use it
params {
use_workload_deployer = true
// the pack's own defaults — copy only the lines you change
workload_deployers = []
workload_deployer_folders = []
deployer_project_folder = ""
deployer_folder_roles = [
"roles/resourcemanager.folderAdmin",
"roles/resourcemanager.projectCreator",
"roles/resourcemanager.projectIamAdmin",
"roles/serviceusage.serviceUsageAdmin",
]
deployer_organization_roles = [ "roles/browser" ]
deployer_billing_roles = [ "roles/billing.user" ]
deployer_group_roles = [
"roles/iam.serviceAccountTokenCreator",
"roles/iam.serviceAccountUser",
]
}
use "presets/workload-deployer.satz" when use_workload_deployer
use_workload_deployer is the gate: while it is falsy the pack contributes nothing — no resources, no params, no claims. It is declared by estate_map, and the estate's own binding wins.
Needs from outside the pack:
billing_account_infra— declared byestate_core; use one of them alongside, or declare it in the estate.customer_shortname— declared byestate_core; use one of them alongside, or declare it in the estate.default_region— declared byestate_core; use one of them alongside, or declare it in the estate.
Params
| param | default |
|---|---|
workload_deployers |
[] |
workload_deployer_folders |
[] |
deployer_project_folder |
"" |
deployer_folder_roles |
[ "roles |
deployer_organization_roles |
[ "roles/browser" ] |
deployer_billing_roles |
[ "roles/billing.user" ] |
deployer_group_roles |
[ "roles |
Questions
What to ask before this pack is configured, and what changing the answer costs.
| asks about | prompt | reversal | blast | recommends |
|---|---|---|---|---|
deployer_project_folder |
The folder the teams' infrastructure projects are created in — the infrastructure folder as google, another folder the estate declares as google_folder.<label>.name, an existing one by its numeric id, or empty for the organisation |
edit | low | "google |
deployer_project_folder — It decides the policies the teams' projects inherit. Changing it afterwards moves every live team project between parents.
An empty answer, "", is an answer: the organisation itself.
Contributes
| resource type | labels |
|---|---|
google |
billing_account_id (grant map), one per entry of workload_deployers, by name |
google_folder_iam_member |
one per entry of workload_deployers, by name, one per entry of workload_deployer_folders, by name |
google |
one per entry of workload_deployers, by name |
google_project |
one per entry of workload_deployers, by name |
Requests
What a project may add to this pack's lists, through contributes_<param> in a file the estate uses after a reviewed pull request; satz check-request checks such a file.
| list | key | fields | description |
|---|---|---|---|
workload_deployers |
name |
name matching [a-z][a-z0-9-]*, group matching [^@: ]+@[^@: ]+, folder |
A team that rolls out folders and Google projects: its name, the address of the group that may become its account, and the folder it creates under |
workload_deployer_folders |
name |
name matching [a-z][a-z0-9-]*, deployer matching [a-z][a-z0-9-]*, folder |
A further parent folder a team creates under: the entry's name, the team's name, and the folder |
Claims
None — this pack proves no control by itself.
History
| version | date | change |
|---|---|---|
| 1.0 | 2026-10-15 | first version: one deployer identity per customer team — per entry of the request point workload_deployers, { name group folder }, the team's infrastructure Google project under deployer_project_folder, inside it the account svc-deploy-<name> and the state bucket, deployer_folder_roles on the entry's folder and on each entry of workload_deployer_folders, deployer_billing_roles on the billing account, deployer_organization_roles (roles/browser, for the interface's lookups) on the organisation, and deployer_group_roles for the team's group on the account alone |
The whole library's history: the changelog in presets/CHANGELOG.md.
Notes
No notes yet.