Evidence
The counts, versions and sources behind every statement in this workspace.
| Units with at least one evidence reference | 16 |
|---|---|
| Evidence references | 80 |
| Findings | 41: 28 warning, 13 info |
| Units whose target is offered in a region by a catalogue snapshot | 7 |
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.
| Family | Units | Evidence drawers | source | intent | plan | hcl | validation |
|---|---|---|---|---|---|---|---|
GCP_IDENTITY | 4 | 0 (this build does not trace it) | ESTABLISHED 4 | NOT AVAILABLE 4 | OPEN 4 | ESTABLISHED 4 | ESTABLISHED 4 |
LEGACY_GENERATOR | 12 | 7 | ESTABLISHED 12 | UNSUPPORTED 12 | UNSUPPORTED 12 | ESTABLISHED 7 NONE 5 | UNSUPPORTED 12 |
- A unit id is its Terraform address: renaming a resource in the source is a new unit. Continuity of a unit across a rename is not built (a semantic fingerprint is a later item).
- An id names an object and holds no run: the same estate gives the same ids in every run. The JSON pointer into a file of the report is valid for the run named in header.run.
- A line is given only for a block of the draft that parses as HCL. A block the draft writes as a comment has a file and no line, and a block the report could not place has neither.
- A hop that reads UNSUPPORTED is not produced by this build; one that reads NOT_AVAILABLE is produced by this build and made nothing in this run. Neither is a finding of no risk.
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
| Units accounted | 11 |
|---|---|
| Units without a draft block | 5 |
| Meaningful settings | 69 |
| Settings not accounted for | 0 in 0 units |
| Settings the draft names as not carried | 40 |
| Invariant | Verdict | Read | What it rests on |
|---|---|---|---|
GLOBAL_RESOURCE_UNIQUENESS | PASS | 55 | 55 addressable blocks in the final files and 0 resources of the plans, every address once |
NO_UNPLANNED_RESOURCE | PASS | 10 | 10 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_REFERENCE | PASS | 9 | 9 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_FIELD | PASS | 28 | 28 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_WIDENING | PASS | 0 | 0 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_RUN | PASS | 48 | 48 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_PRESERVED | PASS | 0 | 0 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_ACTION | PASS | 4 | 4 manual actions and decisions, each naming a unit of the assessment |
SOURCE_PROVIDER_MATCHES_SCHEMA_OR_IS_UNVERIFIED | PASS | 16 | 16 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_DEPENDENCIES | PASS | 0 | the draft holds no application compatibility contract (no container service is drafted as Kubernetes manifests), so no workload is stated ready |
ALL_EMITTED_TARGET_TYPES_CLASSIFIED | PASS | 10 | 10 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_EXPLICIT | PASS | 69 | 69 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 |
| Check | State | What it rests on | What it is about | Recorded in |
|---|---|---|---|---|
| Source completeness | PARTIAL | source status RUNTIME_TOPOLOGY_PARTIAL | how much of the source configuration StackToIT read; not whether what it read is correct | assessment.json /summary/source_status |
| Draft generation | GENERATED | the draft is in terraform/ | whether a STACKIT draft was written for this run | manifest.json /draft |
| StackToIT draft checks | PASSED | 20 checks, none found a violation | StackToIT's own checks of the plan and the rendered text of the families it writes from a plan; not what OpenTofu or STACKIT would say | workspace.json /units |
| Global invariants | PASSED | 12 of 12 invariants PASS; vacuous, they checked nothing: NO_SECURITY_WIDENING, VARIABLE_IDENTITY_PRESERVED, APPLICATION_READY_IMPLIES_REQUIRED_ENV_SECRETS_DEPENDENCIES | eight 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 behaviour | manifest.json /verification |
| OpenTofu validation | PASSED | tofu init -backend=false and tofu validate accepted the draft; tofu 1.13.1 | static validation of the draft against the pinned provider schema — not target behaviour, not approval | manifest.json /validation/tofu_validate |
| Output schema validation | PASSED | verified 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.json | manifest.json /run_verification |
| STACKIT plan | NOT RUN | this build runs no plan against a STACKIT project | a 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 approval | NOT PROVIDED | no review decision is recorded for this run | a named architect's decision on the draft; StackToIT records none | not assessed in this build |
| Semantic equivalence | NOT ASSESSED | this build has no measure for it | whether 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 apply | NOT ASSERTED | StackToIT never asserts it | whether 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.
| Unit | Source type | Identities the source names | Static credential | Federation facts | Target attachment | Workload identity federation | State |
|---|---|---|---|---|---|---|---|
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…"
- Workload identity federation is not assessed as an option for any workload. A row states an OIDC issuer where the source names one, as a fact of the source, and never that federation can replace a key.
- A static credential is named only where the knowledge base reads a machine user with access keys on the unit. A scan that finds no key cannot say a workload has none, so the absence of a credential is never written.
- Privilege delta, break-glass access and human identity are not assessed for any row.
- A workload that names no identity in the source has no row, and a run whose draft held no identity intents lists only the units that are an identity themselves.
- The block states what the identity plan holds open. It does not attach, grant or federate anything.
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.
assurance/equivalence-ledger.csv: the equivalence ledger, 201 rows, one per unit and semantic that the source states and one per unit and property for the properties the draft does not carry, no semantic accounts for or that are critical and still open.assurance/evidence-ledger.csv: the evidence ledger, 72 rows, one per document the other blocks cite, with the date it was checked and the date after which it is to be checked again. Evidence that states no such dates is undated, never current.
Limits of the equivalence ledger:
- Grain: one row per source unit and semantic of the assessment that the source states or may state (UNIT_SEMANTIC), plus one row per source unit and property for each of three lists the assessment names: properties the draft does not carry, properties no semantic accounts for, and critical properties still open (UNIT_PROPERTY). A property named by more than one list has one row per list. A row for every source property is not possible yet: the assessment does not record which properties a generator reads.
- Vocabulary v1: the disposition column prints the words the contracts and the property accounting use today. LEDGER means the contract hands the semantic to the semantic ledger of the draft; PRESERVED and TRANSFORMED appear only where the contract result or the draft's plan ledger states them.
- intent_id, target_capability and target_resource are stated only for a semantic that a family written from a plan (security groups, routing tables) carries through the plan's own ledger; for every other row they are not recorded.
- target_effective_behavior is NOT_ASSESSED on every row: the behaviour of the target is evidenced per field of a plan resource (units[].behavior_evidence), and a semantic is not a field.
- residual_risk, required_action and decision_id are stated only for a critical semantic that is open; they are the sentences and the record that the Decisions section already shows, quoted whole. A sentence that names a record internal to the product is not quoted, and its column is not recorded.
- invalidated_by names the inputs of the whole run (manifest.json invalidation) that, when they change, invalidate the row; no row has an invalidation of its own.
- evidence_refs name rows of evidence_ledger. Evidence that names a record internal to the product is not listed, and evidence that states no check date and no date to check it again is listed UNDATED, never CURRENT.
- 504 semantics of the contracts that the source does not state (it observed no) are not listed: the source has nothing there to carry. The kernel claims of assessment.json count them the same way (absent_claims).
| Knowledge base | 0.394.0 |
|---|---|
| STACKIT Terraform provider | 0.121.0 |
| Assessment format | 0.24.0 |
| Provider | Locked version | Knowledge base checked against | State | Identity evidence |
|---|---|---|---|---|
| not locked | 8.4.0 | not verified | pinned registry (PINNED_REGISTRY) | |
| google-beta | not locked | 8.4.0 | not verified | pinned registry (PINNED_REGISTRY) |
| http | not locked | not verified | identity not established (UNVERIFIED) | |
| random | not locked | not verified | identity not established (UNVERIFIED) | |
| time | not locked | not verified | identity 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