← Google Cloud Dynamic Python Web AppExamplesLegal NoticePrivacy

StackToIT Migration Intelligence Workspace

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

Partially executable migration package · For review only · Not approved.

Technical details: run, versions, digest and evidence freshness

Assessment

Assessment
gcp-candidates/terraform-dynamic-python-webapp/infra (assessment format 0.24.0)
Assessment timestamp
Generated 2026-11-07 04:24 UTC by stacktoit 0.6.0-13076-ga19ea28c64 (a19ea28c64)
Run
6f8f72b2-1c34-4cfc-8483-344c41245364 · source digest sha256:19bfed642d5789ccada81b91d5c36e33175dcafd66dc46b1644ffa105d020000
Source snapshot
partly decided only at plan time · google not locked; google-beta not locked; http not locked; random not locked; time not locked
STACKIT target profile
Stable network model: the experimental STACKIT VPC resources are not used (STACKIT_STABLE)
STACKIT provider version
0.121.0
Knowledge base version
0.394.0
Evidence freshness
Not assessed — Evidence freshness as one measure is not assessed in this build. Dated evidence is shown where it is used: each STACKIT support option and each assurance row states when it was verified (verified_at, and recheck_after for support), in support_suitability and assurance. The date beside a readiness dimension is the assessment date, not a retrieval date.

Staleness: Not assessed — This build has no change detection, so there has been no re-check since the assessment was made (Generated 2026-11-07 04:24 UTC). The source may have changed since.

Source checks: Built-in source checks passed — OpenTofu validation of the source did not run (LOCK_FILE)

Run status: COMPLETE (report published). Source: partly decided only at plan time. Draft: GENERATED. The report was written whole; this is not a statement that the migration is ready.

Executive lens: the sections are in the order this reader usually wants, and Architecture and Engineering Evidence are put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Architect lens: the sections are in the order this reader usually wants, and Costs is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Platform lens: the sections are in the order this reader usually wants, and Costs is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Security lens: the sections are in the order this reader usually wants, and Costs and Migration Plan are put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Application owner lens: the sections are in the order this reader usually wants, and Engineering Evidence is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Programme lens: the sections are in the order this reader usually wants, and Engineering Evidence is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

FinOps lens: the sections are in the order this reader usually wants, and Architecture and Engineering Evidence are put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Engineering lens: the sections are in the order this reader usually wants, and Costs is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Evidence

The counts, versions and sources behind every statement in this workspace.

Evidence counts (over the 16 units listed on the Architecture page)
Units with at least one evidence reference16
Evidence references80
Findings41: 28 warning, 13 info
Units whose target is offered in a region by a catalogue snapshot7

Where each unit leads to

Every unit leads from its source through its intent and its plan to the blocks of the draft and the checks over them. A stage that reads unsupported is not produced by this build (the blocks of that family are written by a generator that records them without an intent or a plan); one that reads not available is produced by this build and made nothing in this run; none means nothing applies at the stage, and the reason is in workspace.json (units[].refs). None of these is a finding of no risk. A unit whose evidence coverage is not traced has no evidence drawer.

Units by family and state at each stage (16 units; 11 lead to a block of the draft, 10 blocks, 13 links)
FamilyUnitsEvidence drawerssourceintentplanhclvalidation
GCP_IDENTITY40 (this build does not trace it)ESTABLISHED 4
NOT AVAILABLE 4
OPEN 4
ESTABLISHED 4
ESTABLISHED 4
LEGACY_GENERATOR127ESTABLISHED 12
UNSUPPORTED 12
UNSUPPORTED 12
ESTABLISHED 7
NONE 5
UNSUPPORTED 12

The reverse table (which unit every block of the draft comes from, with its file and line) is evidence_index.targets in engineering/evidence-index.json; workspace.json states how many entries it has. A block written as a comment has a file and no line; no line is ever invented. A block that has a comment in the draft ends it with a # trace: TR-... line; the reverse table gives that id (trace_id, the anchor of the block's section) and its file (trace_file, engineering/trace/<draft file>.md, one for each file of the draft), the section holds the whole comment the generators wrote for the block, and engineering/trace-index.csv lists them all.

Findings that repeat on several units

41 finding records. 7 groups hold 31 of them: findings of the same check, severity, message and evidence on two or more units, shown once with every unit they concern. 10 are on one unit only. A group is a view: the records stay in assessment.json, a group has no status, and nothing in it is accepted. Findings that differ in wording or severity are never merged.

cloudbuild-source-event · info · 3 units, 3 records

This trigger starts its builds on a Pub/Sub message. The replacement workflow lists the events that start it in its own on: section; the pages of STACKIT read describe pipelines that run whenever changes are pushed to a repository, so a pull request, a schedule or a manual start is verified by a person against the Forgejo Actions reference.

Evidence: https://docs.stackit.cloud/products/developer-platform/git/basics/stackit-pipelines/

Units: google_cloudbuild_trigger.activategcb, google_cloudbuild_trigger.init, google_cloudbuild_trigger.placeholder

linked-dependency-unread · warning · 2 units, 2 records

This unit names google_firebase_hosting_site.client (google_firebase_hosting_site), whose own decision the target does not carry (it is REDESIGN), and the semantic contract of google_cloudbuild_trigger does not read google_firebase_hosting_site, so what the reference becomes is not assessed.

Units: google_cloudbuild_trigger.init, google_cloudbuild_trigger.placeholder

run-min-zero · info · 2 units, 2 records

The service can scale to zero; on SKE at least one replica runs unless an autoscaler with scale-to-zero (KEDA/Knative) is installed.

Units: google_cloud_run_v2_job.migrate, google_cloud_run_v2_service.server

run-unsupported-volume · warning · 2 units, 2 records

A container mounts a Cloud SQL connection, a Cloud Storage bucket (through Cloud Storage FUSE) or an NFS share. The draft writes no volume for these and holds the pods until a person decides: connect to the migrated database or object store over the network instead of the mount, or mount a share or a volume of the cluster yourself.

Evidence: https://registry.terraform.io/providers/hashicorp/google/8.4.0/docs/resources/cloud_run_v2_service

Units: google_cloud_run_v2_job.migrate, google_cloud_run_v2_service.server

sa-account-id-not-visible · info · 4 units, 4 records

The account ID is not visible statically; the STACKIT account is named after the source address. — a variable's default, not a fact

Evidence: https://registry.terraform.io/providers/stackitcloud/stackit/0.116.0/docs/resources/service_account

Units: google_service_account.automation, google_service_account.client, google_service_account.init, google_service_account.server

secret-iam-access · warning · 2 units, 2 records

The secret has grants for individual principals. Access on STACKIT Secrets Manager is coarser than a Secret Manager grant: a Secrets Manager user is read-only or read-write for the whole secrets engine of its instance, with no scope to one secret or path. Narrower access exists only as role bindings on the instance or on a secret group (a named list of secrets) in the alpha API of the service, and the pinned provider offers them as resources of its experimental IAM feature (stackit_secretsmanager_instance_role_binding_v1 and stackit_secretsmanager_secret_group_role_binding_v1), which its documentation says may change or be removed; the specification does not list the roles a secret group accepts. A grant of one Google principal on one secret therefore cannot be carried one to one: decide per principal whether it gets a user of the whole instance, a role binding on a secret group of the secrets it may read, or a separate Secrets Manager instance.

Evidence: https://github.com/stackitcloud/stackit-api-specifications/blob/main/services/secrets-manager/v1/secrets-manager.json, https://github.com/stackitcloud/stackit-api-specifications/blob/main/services/secrets-manager/v1alpha/secrets-manager.json, https://registry.terraform.io/providers/stackitcloud/stackit/0.121.0/docs/resources/secretsmanager_instance_role_binding_v1, https://registry.terraform.io/providers/stackitcloud/stackit/0.121.0/docs/resources/secretsmanager_secret_group_role_binding_v1, https://registry.terraform.io/providers/stackitcloud/stackit/0.121.0/docs/resources/secretsmanager_user

Units: google_secret_manager_secret.django_admin_password, google_secret_manager_secret.django_settings

source-provider-unverified · warning · 16 units, 16 records

no lock file records the version of registry.terraform.io/hashicorp/google, and the constraint ">= 6, < 8" excludes it (pinned 8.4.0) (stated once for the whole estate, with the units it covers and the rest of the words)

Units: google_cloud_run_v2_job.migrate, google_cloud_run_v2_service.server, google_cloudbuild_trigger.activategcb, google_cloudbuild_trigger.init, google_cloudbuild_trigger.placeholder, google_firebase_hosting_site.client, google_firebase_project.default, google_pubsub_topic.faux, google_secret_manager_secret.django_admin_password, google_secret_manager_secret.django_settings, google_service_account.automation, google_service_account.client, google_service_account.init, google_service_account.server, google_sql_database_instance.postgres, google_storage_bucket.media

Property accounting (every setting the source states, checked against the draft)
Units accounted11
Units without a draft block5
Meaningful settings69
Settings not accounted for0 in 0 units
Settings the draft names as not carried40
Global verification of the draft: twelve invariants: eight integrity invariants over the files the converter returns and the plans of every family, and four product invariants (the source providers, the application compatibility contracts, the emitted target types and the property accounting). A draft that fails one is not written. Pending is not a pass: it is decided later or not decidable here.
InvariantVerdictReadWhat it rests on
GLOBAL_RESOURCE_UNIQUENESSPASS5555 addressable blocks in the final files and 0 resources of the plans, every address once
NO_UNPLANNED_RESOURCEPASS1010 resource blocks: 0 resources of a plan, 10 written by a registered legacy generator, none unplanned
legacy.data-services: 2 resource(s) written by a registered legacy generator
legacy.identity: 4 resource(s) written by a registered legacy generator
legacy.kubernetes: 1 resource(s) written by a registered legacy generator
legacy.secrets-and-keys: 2 resource(s) written by a registered legacy generator
legacy.storage: 1 resource(s) written by a registered legacy generator
NO_UNPLANNED_REFERENCEPASS99 references between resources: every one is written, and the references of plan resources are stated by their plan (legacy to legacy: 9)
legacy to legacy: 9
NO_UNRESOLVED_REQUIRED_FIELDPASS2828 required arguments of the resources written: every one is written (a value, a reference or a declared variable) or declared as a target gap
NO_SECURITY_WIDENINGPASS00 grant-defining attributes of the rules and routes written, each equal to the plan, none added (files against the plan; whether the plan carries everything the source allows is said by the unit findings and the NOT CARRIED lines, not by this check)
ALL_OUTPUTS_SAME_RUNPASS4848 artefacts carry the run id that manifest.json carries
assurance/compliance-evidence.csv: carries no run id by design, bound to the run by its sha256 in the manifest
assurance/equivalence-ledger.csv: carries no run id by design, bound to the run by its sha256 in the manifest
assurance/evidence-ledger.csv: carries no run id by design, bound to the run by its sha256 in the manifest
engineering/not-carried-summary.csv: carries no run id by design, bound to the run by its sha256 in the manifest
engineering/not-carried.csv: carries no run id by design, bound to the run by its sha256 in the manifest
engineering/review-edges.csv: carries no run id by design, bound to the run by its sha256 in the manifest
engineering/review.csv: carries no run id by design, bound to the run by its sha256 in the manifest
financial/mapping.csv: carries no run id by design, bound to the run by its sha256 in the manifest
financial/priced-resources.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/actions.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/application-chain.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/applications.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/data-movement.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/decisions.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/source-target.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/waves.csv: carries no run id by design, bound to the run by its sha256 in the manifest
migration/work-board.csv: carries no run id by design, bound to the run by its sha256 in the manifest
VARIABLE_IDENTITY_PRESERVEDPASS00 variable references are exactly the variable the plan states, and the 0 variables read are declared as the plan declares them (type and description)
NO_ORPHAN_MANUAL_ACTIONPASS44 manual actions and decisions, each naming a unit of the assessment
SOURCE_PROVIDER_MATCHES_SCHEMA_OR_IS_UNVERIFIEDPASS1616 units of a source provider: 0 verified against a compatibility record, 16 explicitly not verified through a root record, 0 stated by their provider row
APPLICATION_READY_IMPLIES_REQUIRED_ENV_SECRETS_DEPENDENCIESPASS0the draft holds no application compatibility contract (no container service is drafted as Kubernetes manifests), so no workload is stated ready
ALL_EMITTED_TARGET_TYPES_CLASSIFIEDPASS1010 resource and data blocks of 7 type(s) in the final files, every STACKIT type classified by the target catalogue
resource stackit_objectstorage_bucket (1 block): RESOURCE_EXISTS_BUT_CAPABILITY_UNLINKED
ALL_UNACCOUNTED_PROPERTIES_EXPLICITPASS6969 meaningful properties of 11 generated units each end as accounted by a contract, consumed, a wired reference, a placement decision or named NOT CARRIED; none is UNACCOUNTED
Validation matrix: What has been established about this draft, row by row, and what has not. Nothing here approves the draft, asserts that it is equivalent to the source, or says it is safe to apply.
CheckStateWhat it rests onWhat it is aboutRecorded in
Source completenessPARTIALsource status RUNTIME_TOPOLOGY_PARTIALhow much of the source configuration StackToIT read; not whether what it read is correctassessment.json /summary/source_status
Draft generationGENERATEDthe draft is in terraform/whether a STACKIT draft was written for this runmanifest.json /draft
StackToIT draft checksPASSED20 checks, none found a violationStackToIT's own checks of the plan and the rendered text of the families it writes from a plan; not what OpenTofu or STACKIT would sayworkspace.json /units
Global invariantsPASSED12 of 12 invariants PASS; vacuous, they checked nothing: NO_SECURITY_WIDENING, VARIABLE_IDENTITY_PRESERVED, APPLICATION_READY_IMPLIES_REQUIRED_ENV_SECRETS_DEPENDENCIESeight consistency checks over the files of the draft and the plans, ALL_OUTPUTS_SAME_RUN among them, and one product check that no meaningful source property is left without a stated fate (ALL_UNACCOUNTED_PROPERTIES_EXPLICIT); not a check of target behaviourmanifest.json /verification
OpenTofu validationPASSEDtofu init -backend=false and tofu validate accepted the draft; tofu 1.13.1static validation of the draft against the pinned provider schema — not target behaviour, not approvalmanifest.json /validation/tofu_validate
Output schema validationPASSEDverified at publish: every JSON file that has a schema is validated against it (see run_verification in manifest.json)the machine-readable output files that have a schema, against the schemas recorded in manifest.jsonmanifest.json /run_verification
STACKIT planNOT RUNthis build runs no plan against a STACKIT projecta plan of the draft against a live STACKIT project: whether the provider accepts the values and what it would create not assessed in this build
Architect approvalNOT PROVIDEDno review decision is recorded for this runa named architect's decision on the draft; StackToIT records none not assessed in this build
Semantic equivalenceNOT ASSESSEDthis build has no measure for itwhether the target behaves like the source; StackToIT assesses units and settings one by one and makes no statement about the whole not assessed in this build
Safe to applyNOT ASSERTEDStackToIT never asserts itwhether the draft can be applied to a live project without harm; StackToIT never asserts this not assessed in this build

Identity transition

The direction from static long-lived secrets to short-lived workload identity is followed only where the evidence supports it. This table states the facts of the source and what stays open; it makes no statement about whether federation is an option for any workload. Privilege delta, break-glass access and human identity are not assessed for any row.

Workloads that run as an identity or are one (2)
UnitSource typeIdentities the source namesStatic credentialFederation factsTarget attachmentWorkload identity federationState
google_cloud_run_v2_job.migrate google_cloud_run_v2_job google_cloud_run_v2_job.migrate#template[0].template[0].service_account (runtime, service account, known)
not assessed none stated open not assessed Decision required
google_cloud_run_v2_service.server google_cloud_run_v2_service google_cloud_run_v2_service.server#template[0].service_account (runtime, service account, known)
not assessed none stated open not assessed Decision required
google_cloud_run_v2_job.migrate: what the row says

The identity plan states the attachment of this workload and writes none: whether STACKIT accepts the role assignments an attached account needs is not established. The plan holds manual actions or open decisions for it; they are listed as items. Privilege delta, break-glass access and human identity are not assessed.

Items: the step "Decide how google_cloud_run_v2_job.migrate gets its application identity on…"

google_cloud_run_v2_service.server: what the row says

The identity plan states the attachment of this workload and writes none: whether STACKIT accepts the role assignments an attached account needs is not established. The plan holds manual actions or open decisions for it; they are listed as items. Privilege delta, break-glass access and human identity are not assessed.

Items: the step "Decide how google_cloud_run_v2_service.server gets its application identity on…"

The two ledgers

Two files in this report folder hold the rows behind the statements of this workspace as a spreadsheet. A row never states more than the assessment, the plans or the knowledge base state.

Limits of the equivalence ledger:

Versions
Knowledge base0.394.0
STACKIT Terraform provider0.121.0
Assessment format0.24.0
Source providers read
ProviderLocked versionKnowledge base checked againstStateIdentity evidence
googlenot locked8.4.0not verifiedpinned registry (PINNED_REGISTRY)
google-betanot locked8.4.0not verifiedpinned registry (PINNED_REGISTRY)
httpnot lockednot verifiedidentity not established (UNVERIFIED)
randomnot lockednot verifiedidentity not established (UNVERIFIED)
timenot lockednot verifiedidentity not established (UNVERIFIED)

Source: partly decided only at plan time. 5 unit(s) have a count/for_each that is not known statically; whether and how often they exist is decided at plan time