estate_map — version 2.9
Source: presets/estate-map.satz
Purpose
The map: which packs make up this estate, asked as questions — so an interview has a path. First the day-0 params (estate-core), then these choices, then the questions of every pack the answers switched on.
The map declares the choices, and at the bottom of the file one offers entry
per pack in the library: the gate that switches it on, the phase that has to be
finished before it can go in, the block its line belongs in, and — in file
order — the order the packs can be adopted. satz pack-graph reads the entries,
derives who needs whom from the packs' own param references and ask_when, and
writes presets/pack-graph.json; an entry declares requires or excludes only
for an edge the packs do not show. The estate carries the matching use … when
lines, each written commented under its phase. satz init, satz interview --create and the MCP tool satz_interview write them; answering a choice yes in
the interview uncomments its line. A pack switched on brings its own questions
with it; one switched off asks nothing and emits nothing. A question that gates a
pack cannot live in the pack it gates, which is why they all live here.
The CIS baseline is the first choice and barely one: the estate exists for it,
and its opt-in extensions are the baseline pack's own questions. It is asked
because it is thirty organisation policies in one apply, not because an estate
is expected to go without. Defender's plan fragments are offered with by_hand:
their gates are the Defender pack's own, and their lines are written by hand
beside the Defender line, as their headers show.
Turning a pack off later destroys what it created. The reversal of each
choice says so; the blast says how much that costs the running organisation.
Use it
params {
// the pack's own defaults — copy only the lines you change
use_cis_baseline = true
security_model_s1 = true
security_model_s2 = false
use_audit_logsink = true
use_central_alerts = true
use_billing_permissions = true
use_essential_contacts = true
use_budget = false
use_billing_export = false
use_shared_network = false
use_project_onboarding = false
use_workload_deployer = false
use_project_cis_log_alerts = false
use_scc_enablement = false
use_scc_notifications = false
use_scc_findings_mail = false
use_scc_findings_siem = false
use_scc_export = false
use_security_audit_sa = false
use_defender = false
use_sentinel = false
use_sentinel_auditlogs = use_sentinel
use_sentinel_network_logs = use_sentinel
use_verification_runner = false
use_verification_runner_grant = use_verification_runner
use_exemption_tag = false
interface_notice_pubsub = false
}
use "presets/estate-map.satz"
Params
| param | default |
|---|---|
use_cis_baseline |
true |
security_model_s1 |
true |
security_model_s2 |
false |
use_audit_logsink |
true |
use_central_alerts |
true |
use_billing_permissions |
true |
use_essential_contacts |
true |
use_budget |
false |
use_billing_export |
false |
use_shared_network |
false |
use_project_onboarding |
false |
use_workload_deployer |
false |
use_project_cis_log_alerts |
false |
use_scc_enablement |
false |
use_scc_notifications |
false |
use_scc_findings_mail |
false |
use_scc_findings_siem |
false |
use_scc_export |
false |
use_security_audit_sa |
false |
use_defender |
false |
use_sentinel |
false |
use_sentinel_auditlogs |
use_sentinel |
use_sentinel_network_logs |
use_sentinel |
use_verification_runner |
false |
use |
use_verification_runner |
use_exemption_tag |
false |
interface_notice_pubsub |
false |
Questions
What to ask before this pack is configured, and what changing the answer costs.
| asks about | prompt | reversal | blast | recommends |
|---|---|---|---|---|
use_cis_baseline |
Put the CIS GCP Foundation baseline — thirty organisation policies — in this estate? | recreate | high | — |
security_model (choice) |
Which security-group model does this customer run? | state_surgery | low | — |
use_audit_logsink |
Archive the organisation's audit logs into a bucket in a logging project? | recreate | high | — |
use_central_alerts |
Alert on the CIS log events — ownership, IAM, firewall, route, network, bucket and SQL changes — organisation-wide? | recreate | low | — |
use_billing_permissions |
Grant the billing-admins group its roles on the billing account? | edit | low | — |
use_essential_contacts |
Register the organisation's essential contact? | recreate | low | — |
use_budget |
Put budgets with alerts at 50, 80 and 100 % on the infrastructure billing account — the organisation's, and any for projects or folders? | recreate | none | — |
use_shared_network |
Run a shared VPC for the projects: a host project, one network, and a firewall policy whose subnets and rules the projects request? | recreate | high | — |
use_project_onboarding |
Onboard projects from this estate: per project a Google project with its own IaC service account and state bucket, and the interface the project's estate reads? | recreate | high | — |
use_workload_deployer |
Give each customer team that rolls out folders and projects its own deployer identity: an infrastructure project of its own with the service account its pipelines run as and the bucket its states live in, and the roles that account needs under the workload folder? | recreate | high | — |
use_billing_export |
Export Cloud Billing usage and cost data to BigQuery, in a project of its own? | recreate | low | — |
use_project_cis_log_alerts |
Alert on the CIS log events inside one project of its own as well? | recreate | low | — |
use_scc_enablement |
Turn Security Command Center on for the organisation? | edit | low | true |
use_scc_notifications |
Publish findings to a Pub/Sub topic, for a SIEM or a ticket system to pick up? | edit | low | — |
use_scc_findings_mail |
Mail a security address when findings arrive? | edit | low | — |
use_scc_findings_siem |
Let an external SIEM pull findings off the topic? | edit | low | — |
use_scc_export |
Keep findings in BigQuery, so they can be queried months later? | edit | low | — |
use_security_audit_sa |
Create a read-only security-audit service account with an impersonation group for auditors? | recreate | low | — |
use_defender |
Onboard Microsoft Defender for Cloud through workload identity federation to the customer's Entra tenant? | recreate | high | — |
use_sentinel |
Connect Microsoft Sentinel to this organisation? | recreate | low | — |
use_sentinel_auditlogs |
Send the organisation's audit logs to Sentinel? | recreate | low | — |
use_sentinel_network_logs |
Send the network streams too — VPC flow logs, firewall, DNS queries, Cloud NAT? | recreate | low | — |
use_verification_runner |
Run continuous verification from this estate's own project — transpile --check on every push, report-compliance every night? | recreate | low | — |
use |
Let a verification runner act as this estate's IaC service account? | edit | low | — |
use_exemption_tag |
Create the organisation tag that lets a policy exempt named resources? | edit | none | — |
interface_notice (choice) |
How do the projects that read this estate's interface hear that an exported value changed? | edit | low | — |
use_cis_baseline — This is what the estate is FOR, not an addition to it: every CIS claim the compliance report makes rests on these policies, and the opt-in extensions below are gated on params this pack declares. It is asked rather than assumed because it is thirty policies at the organisation node in one apply, which goes in deliberately — after the state and the identity have moved to the service account, with its plan read first. Turning it off later takes every one of those policies off the organisation.
security_model — Splitting network authority out later means a new group, membership moves and re-granted roles.
security_model_s1— S1 — five admin groups; network authority sits with project admins (A small team that separates org admins, project admins and security roles, and nothing more.)security_model_s2— S2 — S1 plus a distinct network-admins group (For a customer with a separate network team.)
use_audit_logsink — The compliance archive: every Admin Activity, Data Access, System Event and Policy log, organisation-wide, in one bucket with a retention. Without it there is no record to answer an auditor with. Turning it off later destroys the logging project and the archive.
use_central_alerts — CIS 2.5–2.12 as eight metrics and alert policies in the logging project, into one mailbox. Needs the audit-log archive above: it lives in that project. Turning it off later destroys the alerting bucket and its policies, and with them thirty days of alert history.
use_billing_permissions — billing.admin and billing.costsManager for the model's billing-admins group, and use/view for the domain. Without it nobody but the first admin and the IaC account can see or move spend.
use_essential_contacts — Google's suspension, security and legal notices need an address to go to. Without a contact they go to nobody, and the first sign of a problem is the consequence.
use_budget — The one alarm on runaway cost. The pack asks for the amount and who beyond the billing account's administrators gets the alerts; a budget that already exists is adopted through its entry's import_id.
use_shared_network — Projects then run in one network the estate owns instead of each building its own: a project asks for a subnet or a firewall rule by pull request, the estate applies it, and the interface publishes it. Turning it off later destroys the host project, the network and every subnet and rule in it, and cuts off every project attached to it.
use_project_onboarding — A project — a team's estate beside this one, in its own repository — is then one entry of projects, requested by pull request, and satz init --project writes its estate from the interface. Turning it off later destroys every onboarded project's Google project, with everything the project built in it.
use_workload_deployer — A team then never runs as the organisation's IaC account: it impersonates its own account, keeps its own state, and holds the roles the estate grants it — on its parent folder, on the billing account, and the one read on the organisation the interface lookups need. Turning it off later destroys every team's project, with its state bucket and every state in it.
use_billing_export — A budget says when a threshold is crossed; the export says what the money went on, per project, per SKU, per day. It creates a project and a dataset, and it allows Google's export account past domain-restricted sharing while it is on. Switching the export itself on is a console step Cloud Billing has no API for, which the pack's notice names. Turning the pack off later destroys the project and the spend history in it.
use_project_cis_log_alerts — The central alerts cover every project from the logging project. This pack puts the same eight metrics and alert policies, and a channel, into ONE project — for a project with its own on-call, delegated ownership or tenant isolation, or an organisation without the central logging bucket. One project per line: a second project is a fork, because the labels are fixed. Turning it off later destroys the project's metrics, policies and channel, and their alert history.
use_scc_enablement — Google's own detector platform: it watches every project for misconfigurations, leaked keys, crypto-mining and attack patterns, and nothing else in this library replaces it. The tier this library assumes is Premium, and it is not free: the charge is per covered resource per hour, not a share of the bill — at organisation level 0.0057 USD per instance-hour for Compute Engine, Cloud SQL and App Engine Flex, per vCPU-hour for Cloud Run and AlloyDB, 0.20 USD per container image scanned, plus Cloud Storage operation and BigQuery analysis rates (https://cloud.google.com/security-command-center/pricing). Because it follows the NUMBER of resources and not their size, it lands near the 5% of Google Cloud spend Google charges for the equivalent annual subscription on an estate of ordinary machines, and at 10% or more on an estate of many small ones. The 30-day trial is started in the console and becomes pay-as-you-go by itself; pay-as-you-go carries no commitment, and putting the organisation back to Standard stops the charge. Answering yes here declares the step that switches the detectors on — the tier itself is activated in the console.
use_scc_notifications — Findings that stay in the console are read when somebody remembers to look. The topic is the one place another system can read them from as they are raised. Whoever can read the topic reads every finding in the organisation.
use_scc_findings_mail — For an organisation with nothing subscribed to the topic — and a topic nobody subscribes to drops every message it receives. This adds a subscription that keeps seven days, an e-mail channel and an alert that fires when findings reach the topic. The mail says findings arrived and links to them; the finding itself stays in the topic, the console and the export. Off when a SIEM already reads the topic.
use_scc_findings_siem — For a customer whose security team works in Sentinel, Defender for Cloud, Splunk or QRadar rather than in a mailbox. It adds the connector's own pull subscription and roles/pubsub.subscriber for the identity it reads as, which is asked — without that grant a connector authenticates and reads nothing. This and the mailbox are not exclusive: the SIEM ingests every finding, the mailbox is told they are arriving.
use_scc_export — A notification tells somebody now; the export answers what the organisation looked like in March. Whoever can read the dataset reads every finding the organisation has ever raised, and the dataset's location cannot be changed afterwards.
use_security_audit_sa — Auditor access without keys and without remediation rights. Turning it off later removes the account and every auditor's access with it.
use_defender — Only for a customer who runs Defender. It needs the two ids from Microsoft's onboarding script and creates a workload identity pool; turning it off later removes the pool and Defender loses its connector. The plan fragments are added by hand per that pack's header.
use_sentinel — Sentinel reads Google Cloud logs by pulling them from Pub/Sub, federated through workload identity — no service-account key leaves the organisation. This creates the federation half: the pool named after the customer's Entra tenant, the provider that trusts Microsoft, and the account Sentinel acts as. Onboarding is two-sided: the connector in Azure is configured with what this creates, and nothing flows until both halves are done. Turning it off later leaves the connector authenticated against a pool that no longer exists.
use_sentinel_auditlogs — What a SIEM is for: who did what, organisation-wide, with include_children so a project created tomorrow is covered. On with Sentinel, because a connector with no audit logs answers no question anybody asks it. The one cost decision inside it is asked separately — Data Access logs are most of the volume and Sentinel bills by the gigabyte ingested.
use_sentinel_network_logs — Each of these is EMPTY until somebody enables that feature on a subnet, a firewall rule, a DNS policy or a NAT gateway, and Google charges nothing to route logs, so a sink for a feature nobody enabled costs nothing. Switching them off therefore saves nothing; what it costs is the day somebody enables flow logs and finds Sentinel was not watching. On with Sentinel. The volume once a feature IS on is real and lands on Sentinel's ingestion bill — an estate can leave one stream out with a suppress.
use_verification_runner — The customer-hosted shape: Cloud Build triggers and a runner account in the infrastructure project. The grant that lets the runner read as the estate is the next choice, and follows this one. An MSP-hosted runner lives in the MSP's estate: answer this one no here and the grant yes.
use_verification_runner_grant — One binding: the runner's account may mint tokens for the estate's account, the right a human operator holds through the IaC users group. It follows the runner choice, because a runner in this estate needs it; with the runner in another estate — an MSP's — it is answered on its own, and the grant's own question names that runner's account. Whoever holds the runner account reads the estate as its service account.
use_exemption_tag — An organisation policy is all-or-nothing per node: letting ONE service account or ONE project out of a control today means lowering the policy for a whole folder and raising it again afterwards, a window during which nothing is enforced and which nobody remembers to close. A Resource Manager tag is IAM-governed and an organisation policy's rule can condition on it, so the policy stays enforced everywhere and named resources are let out one at a time — visible in the compliance report and listable organisation-wide through Cloud Asset Inventory. Creating the tag exempts nothing on its own: a binding does, and each binding is written in the estate with its owner and its reason. Before granting any exemption, ask whether the consumer needs it at all — a workload in Google Cloud, a Cloud Run service and external CI can all federate instead.
interface_notice — The projects beside the estate read its exports through interfaces/, in their own state and their own pipelines. Without a notice they learn of a changed folder or project on their next plan, or never. The choice has one option per delivery form, and none is an answer: Pub/Sub is the one satz has. Turning a form off later removes what it created, and every project that listens to it stops hearing.
interface_notice_pubsub— Pub/Sub — a message on a topic in the infrastructure project (A bucket holds the exported values as one JSON object, and a storage notification publishes one message to a topic for every apply that changes one. A project subscribes in its own state: a push to its CI's webhook or a pull from a runner.)
Offers
The packs the library offers an estate, in the order they can be adopted. Edges the packs show by their param references are derived by satz pack-graph and are not listed here.
| # | pack | gate | line | declared edges |
|---|---|---|---|---|
| 1 | presets/estate-map.satz |
— | menu | — |
| 2 | presets |
security_model_s1 |
menu | — |
| 3 | presets |
security_model_s2 |
menu | — |
| 4 | presets |
use_billing_permissions |
menu | requires presetsrequires presets |
| 5 | presets |
use_budget |
menu | — |
| 6 | presets/billing-export.satz |
use_billing_export |
menu | — |
| 7 | presets |
use_project_onboarding |
menu | — |
| 8 | presets |
use_workload_deployer |
menu | — |
| 9 | presets/shared-network.satz |
use_shared_network |
menu | — |
| 10 | presets |
use_security_audit_sa |
menu | — |
| 11 | presets |
use_scc_enablement |
menu | — |
| 12 | presets |
use_project_cis_log_alerts |
menu | — |
| 13 | presets |
use_essential_contacts |
in google |
— |
| 14 | presets |
use_audit_logsink |
menu | — |
| 15 | presets |
use_central_alerts |
menu | — |
| 16 | presets |
use_cis_baseline |
menu | — |
| 17 | presets |
cis_block_project_ssh_keys |
menu | — |
| 18 | presets |
cis_require_shielded_vm |
menu | — |
| 19 | presets |
cis_dns_logging |
menu | — |
| 20 | presets |
cis_confidential_computing |
menu | — |
| 21 | presets/cis/cloud-sql.satz |
cis_cloud_sql_hardening |
menu | — |
| 22 | presets/cis/cmek.satz |
cis_cmek_required |
menu | — |
| 23 | presets |
cis_api_key_services |
menu | — |
| 24 | presets |
cis_bucket_retention |
menu | — |
| 25 | presets |
cis_access_approval |
menu | — |
| 26 | presets |
cis_block_internet_ssh_rdp |
menu | — |
| 27 | presets |
cis |
menu | — |
| 28 | presets |
cis |
menu | excludes presets |
| 29 | presets |
cis |
menu | excludes presets |
| 30 | presets |
cis |
menu | excludes presets |
| 31 | presets |
cis |
menu | excludes presets/cis/cloud-sql.satz |
| 32 | presets |
cis |
menu | excludes presets |
| 33 | presets |
cis |
menu | excludes presets |
| 34 | presets |
use_scc_notifications |
menu | — |
| 35 | presets/scc/scc-export.satz |
use_scc_export |
menu | — |
| 36 | presets |
use_scc_findings_siem |
menu | — |
| 37 | presets |
use_scc_findings_mail |
menu | — |
| 38 | presets |
use_defender |
menu | — |
| 39 | presets |
mdc_plan_cspm |
by hand — a Defender plan fragment, written beside the Defender line once the plan is licensed, as that pack's header shows | — |
| 40 | presets |
mdc_cspm_default_access |
by hand — the CSPM plan's custom role in the default access mode, written with the plan fragment | — |
| 41 | presets |
mdc_cspm_least_privilege |
by hand — the CSPM plan's custom role in the least-privilege mode, written with the plan fragment | — |
| 42 | presets |
use_sentinel |
menu | — |
| 43 | presets |
use_sentinel_auditlogs |
menu | — |
| 44 | presets |
use_sentinel_network_logs |
menu | — |
| 45 | presets |
use_verification_runner |
menu | — |
| 46 | presets |
use |
menu | — |
| 47 | presets |
use_exemption_tag |
menu | — |
| 48 | presets |
interface_notice_pubsub |
menu | — |
Contributes
No resources — params and claims only.
Claims
None — this pack proves no control by itself.
History
| version | date | change |
|---|---|---|
| 2.9 | 2026-10-15 | offers workload-deployer on use_workload_deployer, off by default, with its question; nothing already on changes |
| 2.8 | 2026-10-02 | use_budget asks for budgets on projects and folders too, and no longer speaks of a placeholder id; nothing on or off changes |
| 2.7 | 2026-09-30 | offers project-onboarding on use_project_onboarding, off by default, with its question; nothing already on changes |
| 2.6 | 2026-09-26 | offers shared-network on use_shared_network, off by default, with its question; nothing already on changes |
| 2.5 | 2026-09-26 | the interface_notice question and the notice's offers phase say project where they said team, and interfaces/ where they said hcl/interfaces/; nothing it offers changes |
| 2.4 | 2026-09-25 | the change notice is question oneof interface_notice, not required, with the option interface_notice_pubsub (default false) in place of the boolean use_interface_notice, which is refused by name; offers "presets is gated on the option |
| 2.3 | 2026-09-25 | offers interface-notice on use_interface_notice, off by default, with the question that asks for it |
| 2.2 | 2026-09-22 | the S1 model is offered as one entry, security-group-models, at the top level: the two by_hand entries for s1-group-definitions.satz and s1-group-permissions.satz are gone with the packs, and the billing grants require one of the two models rather than one of three files |
| 2.1 | 2026-09-22 | offers billing-export on use_billing_export, off by default |
| 2.0 | 2026-09-19 | one offers entry per pack in the library — its gate, the phase that has to be finished before it can go in, the block its line belongs in, and its adoption order — from which satz pack-graph writes presets/pack-graph.json. Every library file is offered: the S1 model's second spelling and Defender's plan fragments with by_hand, because their lines are written by hand. The edges the packs do not show are declared on the entries: the billing grants require a security model, the S1 split packs and every dry-run twin exclude what they replace. Two new choices: use, following use_verification_runner by reference, because in the MSP-hosted shape the runner and its grant live in different estates; and use_project_cis_log_alerts, off, for a project that alerts on its own beside the central alerts. The grant's line in a newly written estate is gated on its own choice; an estate that carries it gated on the runner's keeps compiling and planning as before |
| 1.9 | 2026-09-18 | the header says what order the estate's lines are in: the order the packs can be adopted, each written commented under the phase that has to be finished first, not the map's own order. A comment change: no choice, default or question changes, and an estate that uses the map upgrades without a fork |
| 1.8 | 2026-09-17 | the CIS baseline joins the map as use_cis_baseline, defaulting to true. It was the one pack the map did not declare — the skeleton wrote its line as fixed text, so the interview could not switch it on, merge-presets could not add it to an estate that lacked it, and the compile could not report it missing. Framing it as a choice does not make it optional: the question says the estate exists for these thirty policies, and its why says what turning it off would take off the organisation. What it buys is that the baseline is adopted, reported and listed by the same machinery as every other pack |
| 1.7 | 2026-09-13 | one more choice: use_exemption_tag, gating exemptions. Its why carries the question that usually ends the conversation — does the consumer need a key at all, when a workload in Google Cloud, a Cloud Run service and external CI can all federate instead |
| 1.6 | 2026-09-12 | the two Sentinel log paths default to use_sentinel BY REFERENCE, so a customer who connects Sentinel and accepts the defaults gets the logs it exists to read; use_sentinel_network_logs is the new one, and either can be answered false to leave that path out |
| 1.5 | 2026-09-12 | use_sentinel and, behind it, use_sentinel_auditlogs: a customer's SIEM is a choice the interview makes, not a fragment somebody remembers to wire |
| 1.4 | 2026-09-12 | use_scc_findings_siem beside the mailbox choice, asked with it when the topic is on: a customer with a SIEM answers where findings go without being asked for an address nobody reads |
| 1.3 | 2026-09-12 | Security Command Center is one decision with follow-ups: use_scc_enablement carries what the Premium tier costs (per covered resource-hour, not a share of the bill) and that the 30-day trial becomes pay-as-you-go by itself, and recommend = true offers it — the param default stays off, so --accept-defaults never switches a paid service on. use_scc_notifications and use_scc_export are asked only when enablement is on (ask_when), and use_scc_findings_mail only when the topic is |
| 1.2 | 2026-09-12 | one more choice: use_scc_export, the BigQuery dataset findings are kept and queried in |
| 1.1 | 2026-09-12 | one more choice: use_scc_notifications, the Pub/Sub chain that carries Security Command Center findings out of the console. Off by default like the enablement choice beside it — it needs SCC switched on to have findings to publish |
| 1.0 | 2026-09-10 | first version: which packs make up the estate, as questions — the S1/S2 model as a oneof (moved here from estate-core) and one boolean per optional pack, four on by default (audit archive, central alerts, billing permissions, essential contact), five off (budget, SCC enablement, security-audit account, Defender, verification runner). Declares the choices only; the estate carries the use … when lines, which the interview skeleton writes and a test keeps in step (ADR 0006) |
The whole library's history: the changelog in presets/CHANGELOG.md.
Notes
The map declares the choices and their questions; the use … when lines that realise them are written into the estate by satz init (and by satz interview --create), so switching a choice on later means adding its use line too.
Turning a choice off after an apply is not a no-op: the pack's resources leave the estate, and the next apply destroys what they created. Suppress or migrate first.