# StackToIT Assess — analysis details — gcp-candidates/terraform-dynamic-python-webapp/infra

> FOR REVIEW — generated by StackToIT Assess. Architect review required before any decision.

Run `6f8f72b2-1c34-4cfc-8483-344c41245364` · source digest `sha256:19bfed642d5789ccada81b91d5c36e33175dcafd66dc46b1644ffa105d020000`

The working behind `engineering/architect-report.md`. Nothing here is a second decision: the class, confidence and what to do are in `engineering/architect-report.md` and `assessment.json`. For a decision that depends on relations the engine could not resolve statically, this file keeps the engine's own text with every combination it evaluated.

## Uncertainty by cause

5 unit(s) exist only if a plan says so: their count/for_each is not known from the source. They are not counted in the unit totals and the classes above, they are not wave members (the migration plan lists them as prerequisites), they are not automation-eligible, and the class shown for them is the one they would get if they exist. Below, they are grouped by the kind of cause; each group names what decides them and the remedy.

By precision state (`summary.presence.conditional_by_state`; no state says the unit exists): 5 present with the defaults of their variables (a variable can change that).

### A root variable that a variable file or the command line can override — 5 unit(s)

**Remedy.** Only the default of a root variable decides whether this exists on the defaults (a default of 0, false or an empty set switches it off) and how often, and a default is not a fact of the source: a variable file, `-var` or `TF_VAR_<name>` can change it, so it is never read as existing now. Give the variable its value — `--var-file FILE`, or a `terraform.tfvars` / `*.auto.tfvars` next to the source — and assess again; StackToIT then reads that value as the source's.

| Decided by | Units | Which |
|---|---:|---|
| the default of variable `var.init` | 4 | `google_cloudbuild_trigger.activategcb`, `google_cloudbuild_trigger.init`, `google_cloudbuild_trigger.placeholder`, `google_service_account.init` |
| the default of variable `var.random_suffix` | 1 | `google_firebase_hosting_site.client` |

- `google_cloudbuild_trigger.activategcb` — count: `var.init ? 1 : 0` (a root variable that a variable file or the command line can override) — state PRESENT_ON_DEFAULTS — would map to REDESIGN / MEDIUM (a workflow in STACKIT Git Pipelines (GitHub Actions syntax, STACKIT-managed or custom runners) or the customer's CI/CD)
- `google_cloudbuild_trigger.init` — count: `var.init ? 1 : 0` (a root variable that a variable file or the command line can override) — state PRESENT_ON_DEFAULTS — would map to REDESIGN / LOW (a workflow in STACKIT Git Pipelines (GitHub Actions syntax, STACKIT-managed or custom runners) or the customer's CI/CD)
- `google_cloudbuild_trigger.placeholder` — count: `var.init ? 1 : 0` (a root variable that a variable file or the command line can override) — state PRESENT_ON_DEFAULTS — would map to REDESIGN / LOW (a workflow in STACKIT Git Pipelines (GitHub Actions syntax, STACKIT-managed or custom runners) or the customer's CI/CD)
- `google_service_account.init` — count: `var.init ? 1 : 0` (a root variable that a variable file or the command line can override) — state PRESENT_ON_DEFAULTS — would map to RECONFIGURE / MEDIUM (STACKIT service account)
- `google_firebase_hosting_site.client` — count: `var.random_suffix ? 1 : 0` (a root variable that a variable file or the command line can override) — state PRESENT_ON_DEFAULTS — would map to REDESIGN / LOW (STACKIT Object Storage as origin of a STACKIT CDN distribution, with a custom domain)

## Modules

Every module call the scan reached, as the loader found it. A module whose state is not LOADED was not read: its resources are invisible to this assessment.

| Module call | Source kind | Source | Version constraint → resolved | State | Reason | Presence | Dir |
|---|---|---|---|---|---|---|---|
| `module.project_services` | other | terraform-google-modules/project-factory/google//modules/project_services | 18.0.0 → 18.0.0 | LOADED | — | KNOWN_PRESENT | .terraform/modules/project_services/modules/project_services |

### Compute

#### `google_cloud_run_v2_job.migrate`

- **Source:** `google_cloud_run_v2_job` — jobs.tf:18
- **Classification:** CONTAINERIZE · **Confidence:** MEDIUM · rule `gcp.cloud_run/run-job`
- **Semantic surface** (contract `gcp.cloud_run`): 12 of 131 semantics stated by the source, 12 accounted, 0 unaccounted — critical left for review/accepted loss: cloud-run-v2-job-network-exposure, deployment-artifact, entry-point, k4-cloud-run-volume-mount-cloud-run-v2-job, location-residency, secrets, service-identity, tc-cloud-run-v2-job-name, tc-cloud-run-v2-job-template--template--containers--env--name, tc-cloud-run-v2-job-template--template--volumes--name, terraform-destroy-guard
  - `k4-cloud-run-volume-mount-cloud-run-v2-job` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. Where a volume appears in the container, which part of it is mounted there and the gcsfuse flags of a bucket mount (volume_mounts, mount_path and sub_path; volumes, gcs, mount_options). The application opens the bucket or share as a local directory, and the STACKIT draft mounts no volume into a container.
    - what closes it: A person provides the data in the target workload at the path the application expects, with an owner and mode it can use, and checks that it finds its files.
  - `cloud-run-v2-job-network-exposure` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. template.template.vpc_access.egress, template.template.vpc_access.network_interfaces.network, template.template.vpc_access.network_interfaces.subnetwork, template.template.volumes.cloud_sql_instance.instances (network exposure) — what the resource is reachable from and what it can reach. The draft names these settings NOT CARRIED: which database the job mounts and which network its egress goes through are re-created on the target (a database connection, the network of the workload) by a person. A person decides: REVIEW.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `container-image` (critical): TRANSFORMED · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
  - `terraform-destroy-guard` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. deletion_protection of a Cloud Run service, job or worker pool (on unless the source switches it off, which an explicit false states) only stops Terraform from destroying the resource; it is not an API protection.
    - what closes it: A person decides whether the replacement keeps the guard with lifecycle { prevent_destroy = true } in the Terraform code.
  - `service-identity` (critical): LEDGER · ledger:workload identity
    - why it is open: Whether the draft carries this setting is decided by its semantic ledger entry "workload identity", and that entry does not state it as carried (it reads review or unsupported, is missing, or rests on a variable's default). The Google service account the workload runs as. target.workload.identity asks the customer which model the pods use.
    - what closes it: The ledger entry reads preserved or transformed with a value that is a fact of the source, or a person accepts the difference.
  - `secrets` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. A Secret Manager reference in the environment becomes a secretKeyRef of the Deployment or Job and a secret volume a Kubernetes secret volume, and the head of the manifest lists the Secrets to create. The draft writes no Secret, because no value of a secret reaches an output.
    - what closes it: A person creates the Kubernetes Secrets the manifest lists, filled from STACKIT Secrets Manager (for example with an External Secrets Operator).
  - `location-residency` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The region the service, job or worker pool runs in (google 8.4.0 `location`). A person confirms the region — REVIEW (critical, the value is not verified against the target).
    - what closes it: A person confirms the STACKIT region of the SKE cluster the workload runs on holds the residency the source region gave, since no mapping between Google and STACKIT regions is evidenced.
  - `tc-cloud-run-v2-job-name` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_v2_job.name: The job's own name, used for identification.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `tc-cloud-run-v2-job-template--template--containers--env--name` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_v2_job.template.template.containers.env.name: The name of an environment variable; an identifier, not the value it carries.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `tc-cloud-run-v2-job-template--template--volumes--name` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_v2_job.template.template.volumes.name: The volume's own name, used only to cross-reference it from volume_mounts.name; an internal wiring identifier with no security meaning of its own.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `deployment-artifact` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_service.template.spec.containers.image; google_cloud_run_v2_service.template.containers.image, build_config.base_image, build_config.image_uri and 5 more; google_cloud_run_v2_job.template.template.containers.image; google_cloud_run_v2_worker_pool.template.containers.image, artifact or image reference (workload compatibility: a setting that binds the code to its runtime stays CRITICAL).
    - what closes it: A person confirms the executable artifact or image for the STACKIT target: where it is built or pulled from and that the same build runs there.
  - `entry-point` (critical): REVIEW · the mapping rule for google_cloud_run_v2_job (knowledge-base case run-job)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_service.template.spec.containers.command, template.spec.containers.args, template.spec.containers.working_dir; google_cloud_run_v2_service.template.containers.command, template.containers.args, template.containers.working_dir and 4 more.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
- **Property accounting:** 13 of 13 meaningful properties accounted (not carried 3 · contract 8 · consumed by the draft 1 · relation 0 · placement 1)
- **Critical-property gate:** `google_cloud_run_v2_job.migrate.deletion_protection` (CRITICAL/CLOSED:NC+REVIEW), `google_cloud_run_v2_job.migrate.location` (CRITICAL/OPEN:placement-only), `google_cloud_run_v2_job.migrate.name` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.containers.command` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.containers.env.name` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.containers.env.value_source.secret_key_ref.secret` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.containers.env.value_source.secret_key_ref.version` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.containers.image` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.containers.volume_mounts.mount_path` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_job.migrate.template.template.service_account` (CRITICAL/CLOSED:NC+REVIEW), `google_cloud_run_v2_job.migrate.template.template.volumes.cloud_sql_instance.instances` (CRITICAL/CLOSED:NC+REVIEW), `google_cloud_run_v2_job.migrate.template.template.volumes.name` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

#### `google_cloud_run_v2_service.server`

- **Source:** `google_cloud_run_v2_service` — service.tf:17
- **Classification:** CONTAINERIZE · **Confidence:** MEDIUM · rule `gcp.cloud_run/run-service`
- **Semantic surface** (contract `gcp.cloud_run`): 14 of 131 semantics stated by the source, 14 accounted, 0 unaccounted — critical left for review/accepted loss: cloud-sql-connection, deployment-artifact, environment, iam-invocation, iam-policy-grant, k4-cloud-run-volume-mount-cloud-run-v2-service, location-residency, secrets, service-identity, tc-cloud-run-v2-service-name, tc-cloud-run-v2-service-template--volumes--name, terraform-destroy-guard (**not automation-eligible**: no property the unit sets is read by iam-invocation, iam-policy-grant)
  - `k4-cloud-run-volume-mount-cloud-run-v2-service` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. Where a volume appears in the container, which part of it is mounted there and the gcsfuse flags of a bucket mount (volume_mounts, mount_path and sub_path; volumes, gcs, mount_options). The application opens the bucket or share as a local directory, and the STACKIT draft mounts no volume into a container.
    - what closes it: A person provides the data in the target workload at the path the application expects, with an owner and mode it can use, and checks that it finds its files.
  - `container-image` (critical): TRANSFORMED · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
  - `iam-invocation` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. Cloud Run lets only callers with the invoker role through unless the service is made public. The draft carries no invocation check; the SKE exposure and the authentication of callers (application, authenticating proxy, or no exposure at all) are decided by a person.
    - what closes it: A person decides how callers of the workload are authenticated (in the application, behind an authenticating proxy, or by no exposure at all) and how the SKE exposure is set, since the draft carries no invocation check.
  - `iam-policy-grant` (critical): REVIEW · a check of the knowledge base (run iam policy) (knowledge-base check run-iam-policy)
    - why it is open: A check of the knowledge base (run iam policy) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). A full IAM policy (member/role bindings) is set directly on the service via policy_data (google 8.4.0); STACKIT has no per-service IAM policy resource, so who may invoke the migrated SKE workload is decided by a person — REVIEW.
    - what closes it: A person decides what this finding asks, and records the evidence or the decision. The finding says: A full IAM policy (member/role bindings) is set directly on the service via policy_data; STACKIT has no per-service IAM policy resource, so who may invoke the migrated SKE workload is decided by a person — the draft carries no invocation check.
  - `scale-to-zero`: REVIEW · a check of the knowledge base (run min zero) (knowledge-base check run-min-zero)
  - `terraform-destroy-guard` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. deletion_protection of a Cloud Run service, job or worker pool (on unless the source switches it off, which an explicit false states) only stops Terraform from destroying the resource; it is not an API protection.
    - what closes it: A person decides whether the replacement keeps the guard with lifecycle { prevent_destroy = true } in the Terraform code.
  - `service-identity` (critical): LEDGER · ledger:workload identity
    - why it is open: Whether the draft carries this setting is decided by its semantic ledger entry "workload identity", and that entry does not state it as carried (it reads review or unsupported, is missing, or rests on a variable's default). The Google service account the workload runs as. target.workload.identity asks the customer which model the pods use.
    - what closes it: The ledger entry reads preserved or transformed with a value that is a fact of the source, or a person accepts the difference.
  - `environment` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The draft writes the environment keys into the ConfigMap and the env of the Deployment or Job. A value is copied only when it is a quantity under a name that says so or a boolean, because any other value can hold a secret, so the rest of the values are a person's.
    - what closes it: A person fills in the values the manifest lists as not copied, in the ConfigMap on the cluster.
  - `secrets` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. A Secret Manager reference in the environment becomes a secretKeyRef of the Deployment or Job and a secret volume a Kubernetes secret volume, and the head of the manifest lists the Secrets to create. The draft writes no Secret, because no value of a secret reaches an output.
    - what closes it: A person creates the Kubernetes Secrets the manifest lists, filled from STACKIT Secrets Manager (for example with an External Secrets Operator).
  - `cloud-sql-connection` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The Cloud SQL connection volume (a connector socket) has no counterpart: the workload connects to the migrated Flex instance endpoint over TLS.
    - what closes it: A person points the workload at the endpoint of the migrated database instance (a Flex or MariaDB instance) over TLS, because the Cloud SQL connector socket has no counterpart.
  - `location-residency` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The region the service, job or worker pool runs in (google 8.4.0 `location`). A person confirms the region — REVIEW (critical, the value is not verified against the target).
    - what closes it: A person confirms the STACKIT region of the SKE cluster the workload runs on holds the residency the source region gave, since no mapping between Google and STACKIT regions is evidenced.
  - `tc-cloud-run-v2-service-name` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_v2_service.name: The Service's own name; an identifier used for addressing/reference, not an access-control or safety property in itself.
    - what closes it: A person confirms the workload name on the cluster against what addresses or refers to the Cloud Run service name, or accepts the new name.
  - `tc-cloud-run-v2-service-template--volumes--name` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_v2_service.template.volumes.name: The volume's own name, used only to cross-reference it from a volume_mounts.name entry; internal wiring identifier.
    - what closes it: A person keeps each volume name matched with the volume mount that refers to it when the volumes are rebuilt as workload volumes on the cluster.
  - `deployment-artifact` (critical): REVIEW · the mapping rule for google_cloud_run_v2_service (knowledge-base case run-service)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloud_run_service.template.spec.containers.image; google_cloud_run_v2_service.template.containers.image, build_config.base_image, build_config.image_uri and 5 more; google_cloud_run_v2_job.template.template.containers.image; google_cloud_run_v2_worker_pool.template.containers.image, artifact or image reference (workload compatibility: a setting that binds the code to its runtime stays CRITICAL).
    - what closes it: A person confirms the executable artifact or image for the STACKIT target: where it is built or pulled from and that the same build runs there.
- **Property accounting:** 17 of 17 meaningful properties accounted (not carried 6 · contract 7 · consumed by the draft 3 · relation 0 · placement 1)
- **Critical-property gate:** `google_cloud_run_v2_service.server.deletion_protection` (CRITICAL/CLOSED:NC+REVIEW), `google_cloud_run_v2_service.server.location` (CRITICAL/OPEN:placement-only), `google_cloud_run_v2_service.server.name` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_service.server.template.containers.env.value` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_service.server.template.containers.env.value_source.secret_key_ref.secret` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_service.server.template.containers.env.value_source.secret_key_ref.version` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_service.server.template.containers.image` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_service.server.template.containers.volume_mounts.mount_path` (CRITICAL/CLOSED:REVIEW), `google_cloud_run_v2_service.server.template.service_account` (CRITICAL/CLOSED:NC+REVIEW), `google_cloud_run_v2_service.server.template.volumes.cloud_sql_instance.instances` (CRITICAL/CLOSED:NC+REVIEW), `google_cloud_run_v2_service.server.template.volumes.name` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

#### `google_cloudbuild_trigger.activategcb`

- **Source:** `google_cloudbuild_trigger` — postdeployment.tf:38
- **Standing:** conditional — whether it exists is decided only when a plan runs; the class below is the one it would get, it is not counted in the totals and not automation-eligible.
- **Classification:** REDESIGN · **Confidence:** MEDIUM · rule `gcp.cloudbuild/cicd-redesign`
- **Semantic surface** (contract `gcp.cloudbuild`): 6 of 19 semantics stated by the source, 6 accounted, 0 unaccounted — critical left for review/accepted loss: project-residency, build-identity, log-destination, deployment-artifact, entry-point, dep-references (**not automation-eligible**: no property the unit sets is read by dep-references)
  - `project-residency` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. Project and Cloud Build location are data-residency/project-boundary facts with no STACKIT CI/CD resource to remap them onto -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `build-identity` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The service account the build (or the Pub/Sub push notification) runs as; STACKIT Git Pipelines has its own, differently-shaped identity model -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `log-destination` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The setting states where/whether build logs are captured or exposed back to GitHub; STACKIT Git Pipelines' own logging model is different -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `deployment-artifact` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger.build.step.name, artifact or image reference (workload compatibility: a setting that binds the code to its runtime stays CRITICAL).
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `entry-point` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger.build.step.entrypoint, build.step.script, build.step.args, entry point (workload compatibility: a setting that binds the code to its runtime stays CRITICAL).
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `dep-references` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger and google_cloudbuild_worker_pool names other units or resources (google_cloudbuild_bitbucket_server_config, google_cloudbuild_worker_pool, google_cloudbuildv2_repository, google_compute_global_address, google_compute_network, google_developer_connect_git_repository_link, google_pubsub_topic, google_secret_manager_secret, google_secret_manager_secret_version, google_service_account, google_sourcerepo_repository, google_storage_bucket). A person confirms how the replacement carries the relation between this unit and the units it names, or accepts the difference.
    - what closes it: A person confirms how the replacement carries the relation, or accepts the difference.
- **Critical-property gate (not drafted — REDESIGN):** `google_cloudbuild_trigger.activategcb.build.options.logging` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.activategcb.build.step.name` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.activategcb.build.step.script` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.activategcb.location` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.activategcb.service_account` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

#### `google_cloudbuild_trigger.init`

- **Source:** `google_cloudbuild_trigger` — postdeployment.tf:144
- **Standing:** conditional — whether it exists is decided only when a plan runs; the class below is the one it would get, it is not counted in the totals and not automation-eligible.
- **Classification:** REDESIGN · **Confidence:** LOW · rule `gcp.cloudbuild/cicd-redesign`
- **Semantic surface** (contract `gcp.cloudbuild`): 6 of 19 semantics stated by the source, 6 accounted, 0 unaccounted — critical left for review/accepted loss: build-identity, dep-references, deployment-artifact, entry-point, log-destination, project-residency (**not automation-eligible**: no property the unit sets is read by dep-references, linked-dependency:google_firebase_hosting_site)
  - `project-residency` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. Project and Cloud Build location are data-residency/project-boundary facts with no STACKIT CI/CD resource to remap them onto -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `build-identity` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The service account the build (or the Pub/Sub push notification) runs as; STACKIT Git Pipelines has its own, differently-shaped identity model -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `log-destination` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The setting states where/whether build logs are captured or exposed back to GitHub; STACKIT Git Pipelines' own logging model is different -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `deployment-artifact` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger.build.step.name, artifact or image reference (workload compatibility: a setting that binds the code to its runtime stays CRITICAL).
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `entry-point` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger.build.step.entrypoint, build.step.script, build.step.args, entry point (workload compatibility: a setting that binds the code to its runtime stays CRITICAL). The unit names google_firebase_hosting_site.client (google_firebase_hosting_site) through this setting (the target does not carry it: it is REDESIGN), so what the reference becomes is part of this setting.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `dep-references` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger and google_cloudbuild_worker_pool names other units or resources (google_cloudbuild_bitbucket_server_config, google_cloudbuild_worker_pool, google_cloudbuildv2_repository, google_compute_global_address, google_compute_network, google_developer_connect_git_repository_link, google_pubsub_topic, google_secret_manager_secret, google_secret_manager_secret_version, google_service_account, google_sourcerepo_repository, google_storage_bucket). A person confirms how the replacement carries the relation between this unit and the units it names, or accepts the difference.
    - what closes it: A person confirms how the replacement carries the relation, or accepts the difference.
  - `linked-dependency:google_firebase_hosting_site` (critical): REVIEW · linked-dependency:google_firebase_hosting_site
- **Critical-property gate (not drafted — REDESIGN):** `google_cloudbuild_trigger.init.build.options.logging` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.init.build.step.name` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.init.build.step.script` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.init.location` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.init.service_account` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

#### `google_cloudbuild_trigger.placeholder`

- **Source:** `google_cloudbuild_trigger` — postdeployment.tf:87
- **Standing:** conditional — whether it exists is decided only when a plan runs; the class below is the one it would get, it is not counted in the totals and not automation-eligible.
- **Classification:** REDESIGN · **Confidence:** LOW · rule `gcp.cloudbuild/cicd-redesign`
- **Semantic surface** (contract `gcp.cloudbuild`): 5 of 19 semantics stated by the source, 5 accounted, 0 unaccounted — critical left for review/accepted loss: build-identity, dep-references, deployment-artifact, linked-dependency:google_firebase_hosting_site, log-destination, project-residency (**not automation-eligible**: no property the unit sets is read by dep-references, linked-dependency:google_firebase_hosting_site)
  - `project-residency` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. Project and Cloud Build location are data-residency/project-boundary facts with no STACKIT CI/CD resource to remap them onto -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `build-identity` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The service account the build (or the Pub/Sub push notification) runs as; STACKIT Git Pipelines has its own, differently-shaped identity model -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `log-destination` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The setting states where/whether build logs are captured or exposed back to GitHub; STACKIT Git Pipelines' own logging model is different -- REVIEW.
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `deployment-artifact` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger.build.step.name, artifact or image reference (workload compatibility: a setting that binds the code to its runtime stays CRITICAL).
    - what closes it: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
  - `dep-references` (critical): REVIEW · the mapping rule for google_cloudbuild_trigger (knowledge-base case cicd-redesign)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_cloudbuild_trigger and google_cloudbuild_worker_pool names other units or resources (google_cloudbuild_bitbucket_server_config, google_cloudbuild_worker_pool, google_cloudbuildv2_repository, google_compute_global_address, google_compute_network, google_developer_connect_git_repository_link, google_pubsub_topic, google_secret_manager_secret, google_secret_manager_secret_version, google_service_account, google_sourcerepo_repository, google_storage_bucket). A person confirms how the replacement carries the relation between this unit and the units it names, or accepts the difference.
    - what closes it: A person confirms how the replacement carries the relation, or accepts the difference.
  - `linked-dependency:google_firebase_hosting_site` (critical): REVIEW · linked-dependency:google_firebase_hosting_site
    - why it is open: This unit names a resource of the type google_firebase_hosting_site (by an attribute that configures it) and the target does not carry that resource as a mapped unit (it is redesigned, blocked, left for review or has no draft block of its own), and no semantic of this unit's contract reads that type: what the reference becomes on the target is not assessed.
    - what closes it: The contract of this unit gains a semantic that reads google_firebase_hosting_site (and lists it as carried), or a person decides what the reference to the resource becomes.
- **Critical-property gate (not drafted — REDESIGN):** `google_cloudbuild_trigger.placeholder.build.options.logging` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.placeholder.build.step.name` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.placeholder.location` (CRITICAL/CLOSED:REVIEW), `google_cloudbuild_trigger.placeholder.service_account` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

### Data

#### `google_sql_database_instance.postgres`

- **Source:** `google_sql_database_instance` — database.tf:25
- **Classification:** REPLATFORM · **Confidence:** MEDIUM · rule `gcp.sql_instance/sql-postgres`
- **Semantic surface** (contract `gcp.sql_instance`): 11 of 71 semantics stated by the source, 11 accounted, 0 unaccounted — critical left for review/accepted loss: database-users, user-and-database-settings, region-residency, project-scope, tc-name, tcf-sql-database--name
  - `engine` (critical): TRANSFORMED · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
  - `engine-version` (critical): PRESERVED · a check of the knowledge base (sql pg version supported) (knowledge-base check sql-pg-version-supported)
  - `network-exposure` (critical): LEDGER · ledger:network exposure
  - `terraform-destroy-guard-off` (critical): PRESERVED · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
  - `database-users` (critical): REVIEW · a check of the knowledge base that the source cannot settle (sql user not generated) (knowledge-base check sql-user-not-generated)
    - why it is open: A check of the knowledge base (sql user not generated) needs a value the scan cannot read statically, so it could not decide. A built-in user of a PostgreSQL instance becomes a stackit_postgresflex_user with the same username (pinned provider) — TRANSFORMED. IAM users (and a name or type not visible statically) are not generated — REVIEW (check sql-user-not-generated); users of the other engines are named NOT CARRIED — REVIEW.
    - what closes it: A literal value or a resolved reference in the source lets the check decide, or a person verifies the value.
  - `user-and-database-settings` (critical): REVIEW · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The source password is not copied (STACKIT generates it: stackit_postgresflex_user.password is computed), a host restriction and ABANDON deletion policies have no counterpart (pinned provider) — the draft names them NOT CARRIED — REVIEW.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `region-residency` (critical): REVIEW · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The region of the instance (google 8.4.0 `region`; unset means the provider's region). A person confirms the region — REVIEW (critical, the value is not verified against the target).
    - what closes it: A person confirms the STACKIT region of the instance (and of a read replica, decided with its primary) holds the residency the source region gave.
  - `project-scope` (critical): REVIEW · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The project of the instance (google 8.4.0 `project`: "The ID of the project in which the resource belongs. If it is not provided, the provider project is used"). A STACKIT project is the scope for ownership, resource consumption and access control (docs.stackit.cloud/platform/resource-manager/basics/projects/): whether the database's source project becomes the project of the rest of the estate is a design decision no rule evidences — a person confirms it — REVIEW (critical).
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `tcfp-sql-user--name` (critical): REVIEW · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
  - `tc-name` (critical): REVIEW · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_sql_database_instance.name: The instance's name/label; does not itself grant access, encrypt data, or control backups/availability/residency.
    - what closes it: A person confirms the instance name the STACKIT database carries against what refers to the source instance name, or accepts the new name.
  - `tcf-sql-database--name` (critical): REVIEW · the mapping rule for google_sql_database_instance (knowledge-base case sql-postgres)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_sql_database.name (a facet of the unit): The literal database name; determines the connection target's label but does not itself grant or restrict access, encrypt data, or affect backups/availability/residency.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
- **Property accounting:** 12 of 12 meaningful properties accounted (not carried 6 · contract 3 · consumed by the draft 1 · relation 0 · placement 2)
- **Critical-property gate:** `google_sql_database_instance.postgres.name` (CRITICAL/CLOSED:REVIEW), `google_sql_database_instance.postgres.project` (CRITICAL/OPEN:placement-only), `google_sql_database_instance.postgres.region` (CRITICAL/OPEN:placement-only), `google_sql_database.database.deletion_policy` (CRITICAL/CLOSED:NC+REVIEW), `google_sql_database.database.name` (CRITICAL/CLOSED:NC+REVIEW), `google_sql_user.django.deletion_policy` (CRITICAL/CLOSED:NC+REVIEW), `google_sql_user.django.name` (CRITICAL/CLOSED:NC+REVIEW), `google_sql_user.django.password` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

### Identity

#### `google_service_account.automation`

- **Source:** `google_service_account` — iam.tf:54
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.service_account/service-account`
- **Semantic surface** (contract `gcp.service_account`): 3 of 12 semantics stated by the source, 3 accounted, 0 unaccounted — critical left for review/accepted loss: role-bindings, account-name (**not automation-eligible**: no property the unit sets is read by role-bindings)
  - `workload-identity` (critical): TRANSFORMED · the mapping rule for google_service_account (knowledge-base case service-account)
  - `role-bindings` (critical): REVIEW · the mapping rule for google_service_account (knowledge-base case service-account)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The grants of the estate that name the account: a grant on a project, a folder or an organisation is written as a STACKIT role assignment of the account when its role and members are visible statically and it has no condition, and a grant that lets another account act as it is written as an Act-As assignment. A Google role is written as a STACKIT role only where the mapping shows the STACKIT role holds the same permissions or fewer on a project; every other role is an input that names the candidates, and a person confirms each. A binding or a policy is authoritative (it removes the members of its role that it does not list) and a role assignment only adds, which the draft says on each: members that hold the role outside the configuration keep it on STACKIT until a person removes them.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `account-name` (critical): REVIEW · a check of the knowledge base (sa account id not visible) (knowledge-base check sa-account-id-not-visible)
    - why it is open: A check of the knowledge base (sa account id not visible) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). The account ID becomes the stackit_service_account name (shortened to the STACKIT name rules; pinned provider) — TRANSFORMED; the e-mail address changes. An ID not visible statically (or a repeated account) is named NOT CARRIED — REVIEW (check sa-account-id-not-visible).
    - what closes it: A person decides what this finding asks, and records the evidence or the decision. The finding says: The account ID is not visible statically; the STACKIT account is named after the source address. — a variable's default, not a fact.
- **Property accounting:** 2 of 2 meaningful properties accounted (not carried 2 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_service_account.automation.account_id` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

#### `google_service_account.client`

- **Source:** `google_service_account` — iam.tf:48
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.service_account/service-account`
- **Semantic surface** (contract `gcp.service_account`): 3 of 12 semantics stated by the source, 3 accounted, 0 unaccounted — critical left for review/accepted loss: role-bindings, account-name (**not automation-eligible**: no property the unit sets is read by role-bindings)
  - `workload-identity` (critical): TRANSFORMED · the mapping rule for google_service_account (knowledge-base case service-account)
  - `role-bindings` (critical): REVIEW · the mapping rule for google_service_account (knowledge-base case service-account)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The grants of the estate that name the account: a grant on a project, a folder or an organisation is written as a STACKIT role assignment of the account when its role and members are visible statically and it has no condition, and a grant that lets another account act as it is written as an Act-As assignment. A Google role is written as a STACKIT role only where the mapping shows the STACKIT role holds the same permissions or fewer on a project; every other role is an input that names the candidates, and a person confirms each. A binding or a policy is authoritative (it removes the members of its role that it does not list) and a role assignment only adds, which the draft says on each: members that hold the role outside the configuration keep it on STACKIT until a person removes them.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `account-name` (critical): REVIEW · a check of the knowledge base (sa account id not visible) (knowledge-base check sa-account-id-not-visible)
    - why it is open: A check of the knowledge base (sa account id not visible) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). The account ID becomes the stackit_service_account name (shortened to the STACKIT name rules; pinned provider) — TRANSFORMED; the e-mail address changes. An ID not visible statically (or a repeated account) is named NOT CARRIED — REVIEW (check sa-account-id-not-visible).
    - what closes it: A person decides what this finding asks, and records the evidence or the decision. The finding says: The account ID is not visible statically; the STACKIT account is named after the source address. — a variable's default, not a fact.
- **Property accounting:** 2 of 2 meaningful properties accounted (not carried 2 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_service_account.client.account_id` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

#### `google_service_account.server`

- **Source:** `google_service_account` — iam.tf:42
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.service_account/service-account`
- **Semantic surface** (contract `gcp.service_account`): 3 of 12 semantics stated by the source, 3 accounted, 0 unaccounted — critical left for review/accepted loss: role-bindings, account-name (**not automation-eligible**: no property the unit sets is read by role-bindings)
  - `workload-identity` (critical): TRANSFORMED · the mapping rule for google_service_account (knowledge-base case service-account)
  - `role-bindings` (critical): REVIEW · the mapping rule for google_service_account (knowledge-base case service-account)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The grants of the estate that name the account: a grant on a project, a folder or an organisation is written as a STACKIT role assignment of the account when its role and members are visible statically and it has no condition, and a grant that lets another account act as it is written as an Act-As assignment. A Google role is written as a STACKIT role only where the mapping shows the STACKIT role holds the same permissions or fewer on a project; every other role is an input that names the candidates, and a person confirms each. A binding or a policy is authoritative (it removes the members of its role that it does not list) and a role assignment only adds, which the draft says on each: members that hold the role outside the configuration keep it on STACKIT until a person removes them.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `account-name` (critical): REVIEW · a check of the knowledge base (sa account id not visible) (knowledge-base check sa-account-id-not-visible)
    - why it is open: A check of the knowledge base (sa account id not visible) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). The account ID becomes the stackit_service_account name (shortened to the STACKIT name rules; pinned provider) — TRANSFORMED; the e-mail address changes. An ID not visible statically (or a repeated account) is named NOT CARRIED — REVIEW (check sa-account-id-not-visible).
    - what closes it: A person decides what this finding asks, and records the evidence or the decision. The finding says: The account ID is not visible statically; the STACKIT account is named after the source address. — a variable's default, not a fact.
- **Property accounting:** 2 of 2 meaningful properties accounted (not carried 2 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_service_account.server.account_id` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

#### `google_secret_manager_secret.django_admin_password`

- **Source:** `google_secret_manager_secret` — secrets.tf:25
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.secret/secret`
- **Semantic surface** (contract `gcp.secret`): 4 of 18 semantics stated by the source, 4 accounted, 0 unaccounted — critical left for review/accepted loss: secret-value, secret-settings, tcr-secret-id
  - `secret-values` (critical): TRANSFORMED · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
  - `secret-value` (critical): REVIEW · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_secret_manager_secret_version.secret_data: the value of the secret. StackToIT never reads it and never writes it into the draft; the API step of the secret writes the document the customer supplies.
    - what closes it: A person decides where the value comes from, supplies the document and the step has run.
  - `secret-settings` (critical): REVIEW · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The settings of the secret beside its value (secret-value): STACKIT replicates it itself (no replica locations or per-replica keys), tags and version states have no counterpart, and IAM members and policy map to Secrets Manager users (read-only or read-write for a whole instance) or to experimental role bindings on a secret group — REVIEW.
    - what closes it: A person recreates the secret in the Secrets Manager instance, since its data is not written into the draft, and decides for each IAM member whether it gets a user of the whole instance, a role binding on a secret group, or a separate instance.
  - `tcr-secret-id` (critical): REVIEW · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_secret_manager_secret.secret_id: The secret's own resource identifier; access to the secret's value is controlled by IAM bindings and replication/encryption settings, not by the id string itself.
    - what closes it: A person confirms the secret name in STACKIT Secrets Manager against what refers to the source secret ID, or accepts the new name.
- **Property accounting:** 5 of 5 meaningful properties accounted (not carried 5 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_secret_manager_secret.django_admin_password.replication.user_managed.replicas.location` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret.django_admin_password.secret_id` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret_iam_binding.django_admin_password.members` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret_iam_binding.django_admin_password.role` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret_version.django_admin_password.secret_data` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

#### `google_secret_manager_secret.django_settings`

- **Source:** `google_secret_manager_secret` — secrets.tf:56
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.secret/secret`
- **Semantic surface** (contract `gcp.secret`): 4 of 18 semantics stated by the source, 4 accounted, 0 unaccounted — critical left for review/accepted loss: secret-value, secret-settings, tcr-secret-id
  - `secret-values` (critical): TRANSFORMED · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
  - `secret-value` (critical): REVIEW · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_secret_manager_secret_version.secret_data: the value of the secret. StackToIT never reads it and never writes it into the draft; the API step of the secret writes the document the customer supplies.
    - what closes it: A person decides where the value comes from, supplies the document and the step has run.
  - `secret-settings` (critical): REVIEW · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The settings of the secret beside its value (secret-value): STACKIT replicates it itself (no replica locations or per-replica keys), tags and version states have no counterpart, and IAM members and policy map to Secrets Manager users (read-only or read-write for a whole instance) or to experimental role bindings on a secret group — REVIEW.
    - what closes it: A person recreates the secret in the Secrets Manager instance, since its data is not written into the draft, and decides for each IAM member whether it gets a user of the whole instance, a role binding on a secret group, or a separate instance.
  - `tcr-secret-id` (critical): REVIEW · the mapping rule for google_secret_manager_secret (knowledge-base case secret)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_secret_manager_secret.secret_id: The secret's own resource identifier; access to the secret's value is controlled by IAM bindings and replication/encryption settings, not by the id string itself.
    - what closes it: A person confirms the secret name in STACKIT Secrets Manager against what refers to the source secret ID, or accepts the new name.
- **Property accounting:** 5 of 5 meaningful properties accounted (not carried 5 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_secret_manager_secret.django_settings.replication.user_managed.replicas.location` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret.django_settings.secret_id` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret_iam_binding.django_settings.members` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret_iam_binding.django_settings.role` (CRITICAL/CLOSED:NC+REVIEW), `google_secret_manager_secret_version.django_settings.secret_data` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

#### `google_service_account.init`

- **Source:** `google_service_account` — iam.tf:61
- **Standing:** conditional — whether it exists is decided only when a plan runs; the class below is the one it would get, it is not counted in the totals and not automation-eligible.
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.service_account/service-account`
- **Semantic surface** (contract `gcp.service_account`): 3 of 12 semantics stated by the source, 3 accounted, 0 unaccounted — critical left for review/accepted loss: role-bindings, account-name (**not automation-eligible**: no property the unit sets is read by role-bindings)
  - `workload-identity` (critical): TRANSFORMED · the mapping rule for google_service_account (knowledge-base case service-account)
  - `role-bindings` (critical): REVIEW · the mapping rule for google_service_account (knowledge-base case service-account)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The grants of the estate that name the account: a grant on a project, a folder or an organisation is written as a STACKIT role assignment of the account when its role and members are visible statically and it has no condition, and a grant that lets another account act as it is written as an Act-As assignment. A Google role is written as a STACKIT role only where the mapping shows the STACKIT role holds the same permissions or fewer on a project; every other role is an input that names the candidates, and a person confirms each. A binding or a policy is authoritative (it removes the members of its role that it does not list) and a role assignment only adds, which the draft says on each: members that hold the role outside the configuration keep it on STACKIT until a person removes them.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `account-name` (critical): REVIEW · a check of the knowledge base (sa account id not visible) (knowledge-base check sa-account-id-not-visible)
    - why it is open: A check of the knowledge base (sa account id not visible) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). The account ID becomes the stackit_service_account name (shortened to the STACKIT name rules; pinned provider) — TRANSFORMED; the e-mail address changes. An ID not visible statically (or a repeated account) is named NOT CARRIED — REVIEW (check sa-account-id-not-visible).
    - what closes it: A person decides what this finding asks, and records the evidence or the decision. The finding says: The account ID is not visible statically; the STACKIT account is named after the source address. — a variable's default, not a fact.
- **Property accounting:** 2 of 2 meaningful properties accounted (not carried 2 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_service_account.init.account_id` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

### Messaging

#### `google_pubsub_topic.faux`

- **Source:** `google_pubsub_topic` — postdeployment.tf:32
- **Classification:** REPLATFORM · **Confidence:** MEDIUM · rule `gcp.pubsub_topic/pubsub`
- **Semantic surface** (contract `gcp.pubsub_topic`): 2 of 48 semantics stated by the source, 2 accounted, 0 unaccounted — critical left for review/accepted loss: tc-name
  - `messaging-model` (critical): TRANSFORMED · the mapping rule for google_pubsub_topic (knowledge-base case pubsub)
  - `tc-name` (critical): REVIEW · the mapping rule for google_pubsub_topic (knowledge-base case pubsub)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_pubsub_topic.name: The topic's own resource name, which publishers and subscribers address it by; access to it is controlled by IAM, not by the name string itself, and a changed name breaks every client that uses the old one.
    - what closes it: A person confirms the topic name the replacement messaging service carries against the publishers and subscribers that use it, or accepts the new name.
- **Property accounting:** 1 of 1 meaningful properties accounted (not carried 1 · contract 0 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_pubsub_topic.faux.name` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**

### Network

#### `google_firebase_hosting_site.client`

- **Source:** `google_firebase_hosting_site` — firebase.tf:24
- **Standing:** conditional — whether it exists is decided only when a plan runs; the class below is the one it would get, it is not counted in the totals and not automation-eligible.
- **Classification:** REDESIGN · **Confidence:** LOW · rule `gcp.firebase_hosting_site/web-hosting-site`
- **Semantic surface** (contract `gcp.firebase_hosting_site`): 3 of 5 semantics stated by the source, 3 accounted, 0 unaccounted — critical left for review/accepted loss: tc-firebase-hosting-site-project, tcr-firebase-hosting-site-site-id (**not automation-eligible**: no property the unit sets is read by linked-dependency:google_firebase_project)
  - `migration-decision`: REVIEW · the mapping rule for google_firebase_hosting_site (knowledge-base case web-hosting-site)
  - `tc-firebase-hosting-site-project` (critical): REVIEW · the mapping rule for google_firebase_hosting_site (knowledge-base case web-hosting-site)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_firebase_hosting_site.project (identity access): The Google Cloud project the resource is created in. IAM policy, organisation policy and audit configuration are inherited from the project, so it decides who can act on the resource and what it is isolated from. The unit names google_firebase_project.default (google_firebase_project) through this setting (the target does not carry it: it is MANUAL_REVIEW), so what the reference becomes is part of this setting.
    - what closes it: A person decides which STACKIT project, and with it which access rules, holds the replacement.
  - `tcr-firebase-hosting-site-site-id` (critical): REVIEW · the mapping rule for google_firebase_hosting_site (knowledge-base case web-hosting-site)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_firebase_hosting_site.site_id (workload compatibility): A globally unique identifier for the Hosting site; other settings, bindings and clients refer to the object by this id. Firebase Hosting has no STACKIT counterpart, so the site is rebuilt on Object Storage with a CDN.
    - what closes it: A person sets this up on the bucket, the CDN distribution and the domain that replace Firebase Hosting, or decides to drop it, and records the decision.
  - `linked-dependency:google_firebase_project` (critical): REVIEW · linked-dependency:google_firebase_project
- **Critical-property gate (not drafted — REDESIGN):** `google_firebase_hosting_site.client.project` (CRITICAL/CLOSED:REVIEW), `google_firebase_hosting_site.client.site_id` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

### Platform

#### `google_firebase_project.default`

- **Source:** `google_firebase_project` — firebase.tf:17
- **Classification:** MANUAL_REVIEW · **Confidence:** LOW · rule `gcp.firebase_project/app-platform-project`
- **Semantic surface** (contract `gcp.firebase_project`): 2 of 2 semantics stated by the source, 2 accounted, 0 unaccounted — critical left for review/accepted loss: tc-firebase-project-project
  - `migration-decision`: REVIEW · the mapping rule for google_firebase_project (knowledge-base case app-platform-project)
  - `tc-firebase-project-project` (critical): REVIEW · the mapping rule for google_firebase_project (knowledge-base case app-platform-project)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. google_firebase_project.project (identity access): The Google Cloud project the resource is created in. IAM policy, organisation policy and audit configuration are inherited from the project, so it decides who can act on the resource and what it is isolated from. Firebase has no STACKIT counterpart, so the registration of the app is not moved and the backend the app talks to is chosen by a person.
    - what closes it: A person decides which STACKIT project, and with it which access rules, holds the replacement.
- **Critical-property gate (not drafted — MANUAL_REVIEW):** `google_firebase_project.default.project` (CRITICAL/CLOSED:REVIEW) — **not automation-eligible**

### Storage

#### `google_storage_bucket.media`

- **Source:** `google_storage_bucket` — storage.tf:17
- **Classification:** RECONFIGURE · **Confidence:** MEDIUM · rule `gcp.storage_bucket/gcs`
- **Semantic surface** (contract `gcp.storage_bucket`): 7 of 63 semantics stated by the source, 7 accounted, 0 unaccounted — critical left for review/accepted loss: geo-replication, bucket-region, iam-access, iam-grant, public-access, force-destroy, tc-storage-bucket-name
  - `geo-replication` (critical): REVIEW · the value comes from a variable's default; the mapping rule for google_storage_bucket (knowledge-base case gcs)
    - why it is open: The value is read from a variable's default; that is not a fact of the source. A custom_placement_config not visible statically (a dynamic block over an unknown for_each, a whole value from a variable) may be absent: the facts state no replication, the ledger writes no line and a person decides (REVIEW by the case; 2026-09-25 unknown-value audit — it used to be claimed as replicated).
    - what closes it: The value is set where the module is called (a literal), the variable is given its value in a variable file of the scan (--var-file), or a person confirms the value production uses.
  - `bucket-region` (critical): REVIEW · the mapping rule for google_storage_bucket (knowledge-base case gcs)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. A single-region location (us-central1, europe-west3, ...), or one not visible statically: the draft sets no region on stackit_objectstorage_bucket (`region`: "if not defined, the provider region is used", pinned provider), so the bucket lands in the STACKIT region the user sets, not in the source's — a person confirms the residency — REVIEW.
    - what closes it: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
  - `iam-access` (critical): REVIEW · a check of the knowledge base (gcs iam) (knowledge-base check gcs-iam)
    - why it is open: A check of the knowledge base (gcs iam) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). The setting states who may access the bucket, granted with IAM bindings or ACL entries.
    - what closes it: A person decides it as that finding asks, and the finding's closing evidence or decision is recorded. A person creates the bucket policies and Object Storage credentials that give the same access on STACKIT.
  - `iam-grant` (critical): REVIEW · a check of the knowledge base (gcs iam) (knowledge-base check gcs-iam)
    - why it is open: A check of the knowledge base (gcs iam) fired on this unit and leaves the setting to a person: the target does not settle it by itself (a finding of this unit describes it). The value-level reader of who gets which role (`iam-access` above is the facet as a whole): role, member(s) and condition. A GCP principal (user:, group:, serviceAccount:, allUsers) and a predefined role have no STACKIT counterpart in a bucket policy, whose statements name principals and S3 actions (supported-permissions-in-bucket-policies docs; the draft writes no policy) — a person translates each grant — REVIEW for every value, allUsers included (that one is also public-access, TRANSFORMED).
    - what closes it: A person decides what this finding asks, and records the evidence or the decision. The finding says: Bucket access is granted with IAM bindings or ACL entries; on STACKIT it becomes bucket policies and Object Storage credentials.
  - `public-access` (critical): REVIEW · a check of the knowledge base that the source cannot settle (gcs public) (knowledge-base check gcs-public)
    - why it is open: A check of the knowledge base (gcs public) needs a value the scan cannot read statically, so it could not decide. The counterpart is a bucket policy with Principal "*" and s3:GetObject (documented sample), but stackit_objectstorage_bucket has no policy attribute and the provider no bucket-policy resource, so the draft writes none: REVIEW, as for the IP rules.
    - what closes it: A literal value or a resolved reference in the source lets the check decide, or a person verifies the value.
  - `force-destroy` (critical): UNSUPPORTED · a check of the knowledge base (gcs force destroy) (knowledge-base check gcs-force-destroy)
    - why it is open: A check of the knowledge base (gcs force destroy) found a setting the target has no counterpart for (a finding of this unit describes it). stackit_objectstorage_bucket (pinned provider) "cannot be destroyed if the bucket contains objects" (schema description): force_destroy = false — a destroy that stops at a non-empty bucket — is what STACKIT does, PRESERVED; true has no counterpart, UNSUPPORTED (check gcs-force-destroy).
    - what closes it: A person accepts the difference or the design changes: nothing in the source can make the target carry it.
  - `tc-storage-bucket-name` (critical): REVIEW · the mapping rule for google_storage_bucket (knowledge-base case gcs)
    - why it is open: The mapping rule for this kind of unit recognises the unit but only passes this setting to a person; it does not decide its value. The name of the Cloud Storage bucket, in lowercase and at most 63 characters per the provider documentation, by which applications address it.
    - what closes it: A person confirms the Object Storage bucket name against the applications and tools that use the source bucket name, or accepts the new name.
- **Property accounting:** 8 of 8 meaningful properties accounted (not carried 6 · contract 2 · consumed by the draft 0 · relation 0 · placement 0)
- **Critical-property gate:** `google_storage_bucket.media.force_destroy` (CRITICAL/CLOSED:NC+UNSUPPORTED), `google_storage_bucket.media.location` (CRITICAL/CLOSED:REVIEW), `google_storage_bucket.media.name` (CRITICAL/CLOSED:REVIEW), `google_storage_bucket_iam_member.automation.member` (CRITICAL/CLOSED:NC+REVIEW), `google_storage_bucket_iam_member.automation.role` (CRITICAL/CLOSED:NC+REVIEW), `google_storage_bucket_iam_member.server.member` (CRITICAL/CLOSED:NC+REVIEW), `google_storage_bucket_iam_member.server.role` (CRITICAL/CLOSED:NC+REVIEW) — **not automation-eligible**
