Bug Description
Two shared modules build their resource IDs by truncating to 30 characters instead of failing:
# modules/project/main.tf:64
project_id = trimsuffix(replace(substr("${local.prefix}${var.name}", 0, 30), "_", "-"), "-")
# modules/iam-service-account/main.tf:49
account_id = trimsuffix(replace(substr("${local.prefix}${local.name}", 0, 30), "_", "-"), "-")
An input that overruns the limit does not produce an error. It produces a different resource than
the operator asked for, with a silently shortened ID, and terraform apply reports success. For a
project this is not recoverable by editing the tfvars afterwards: project IDs can never be reused, so
the shortened ID is permanent for the life of that project.
Today nothing in the shipped configuration overruns, but the margin is exactly zero, and the
documentation that tells operators how much room they have is no longer self-consistent.
The margin is zero
The longest project ID the FAST stages generate is the tenant IaC core project,
<prefix>-<env>-<tenant>-iac-core-0. With the maximum values the stages themselves validate:
| Input |
Validated by |
Max |
Chars |
prefix |
0-bootstrap/variables.tf:334 (<= 7), 1-resman/variables.tf:287 (< 8) |
7 |
7 |
-<env>- |
envs_folders keys, longest shipped is Test |
— |
6 |
<tenant> |
1-resman/variables.tf:346 (alltrue([for k, _ in var.tenants : length(k) < 7])) |
6 |
6 |
-iac-core-0 |
fixed |
— |
11 |
|
|
|
30 |
30 is exactly the Google Cloud project ID ceiling. Every one of those inputs is at its documented
maximum, so the configuration is legal — but there is no headroom at all, and the mechanism that
would catch the next increment is a substr, not a validation.
The documented limit no longer agrees with itself
v3.0.0 and PR #213 moved most of the prefix guidance to 7. One document did not move:
| Source |
States |
fast/stages-aw/0-bootstrap/variables.tf:331 and :335 |
"Use 7 characters or less" / "Use a maximum of 7 characters for prefix." |
fast/stages-aw/0-bootstrap/README.md:133, :383 |
7 |
fast/stages-aw/0-bootstrap/terraform.tfvars.sample:30 |
"Use something unique and no longer than 7 characters" |
docs/ddg.md:75, :221 |
7 (changed from 6 by PR #213) |
docs/naming-convention.md:31 |
"A short prefix of no more than 6 characters" |
An operator following naming-convention.md and an operator following the DDG will size their prefix
differently, and only one of them is at the ceiling.
Environment and Deployment Context
Steps to Reproduce
- Set
prefix to any 7-character value in fast/stages-aw/0-bootstrap/terraform.tfvars.
- In
1-resman, declare a tenant whose key is 6 characters (for example report) with envs_folders including Test.
terraform plan Stage 1 and read the planned tenant IaC core project ID: it is exactly 30 characters.
- Now shorten nothing and lengthen one fixed part — for example add any suffix to
var.name for that project in modules/project, or imagine a future context token. The plan does not fail; it plans a shortened project ID.
Expected Behavior
An ID that does not fit should stop the plan with a message naming the input that is too long, the same way prefix and tenants already do. Where truncation is deliberate, the documented limits should leave enough room that it cannot be reached by a legal combination of inputs. docs/naming-convention.md should state the same prefix limit as the DDG, the variable description and the sample.
Actual Behavior
substr(..., 0, 30) shortens the ID silently, trimsuffix(..., "-") can shorten it by one more, and the apply succeeds with a resource the operator did not name. The only guard is that today's longest legal combination happens to land on exactly 30.
Relevant Logs and Errors
None — the absence of an error is the defect.
Additional Context
- Suggested fix, in order of value: (1) replace the
substr in both modules with a precondition (or a validation on the composed name) that fails with the offending value; (2) if truncation must stay for backward compatibility, log it via a check block; (3) correct docs/naming-convention.md to 7 so all five sources agree.
- Related: the
prefix validations at 0-bootstrap/variables.tf:334 and 1-resman/variables.tf:287 disagree in form (<= 7 vs < 8) though not in effect; 2-networking-* and 3-security both allow < 10, which is looser than either and would truncate.
Bug Description
Two shared modules build their resource IDs by truncating to 30 characters instead of failing:
An input that overruns the limit does not produce an error. It produces a different resource than
the operator asked for, with a silently shortened ID, and
terraform applyreports success. For aproject this is not recoverable by editing the tfvars afterwards: project IDs can never be reused, so
the shortened ID is permanent for the life of that project.
Today nothing in the shipped configuration overruns, but the margin is exactly zero, and the
documentation that tells operators how much room they have is no longer self-consistent.
The margin is zero
The longest project ID the FAST stages generate is the tenant IaC core project,
<prefix>-<env>-<tenant>-iac-core-0. With the maximum values the stages themselves validate:prefix0-bootstrap/variables.tf:334(<= 7),1-resman/variables.tf:287(< 8)-<env>-envs_folderskeys, longest shipped isTest<tenant>1-resman/variables.tf:346(alltrue([for k, _ in var.tenants : length(k) < 7]))-iac-core-030 is exactly the Google Cloud project ID ceiling. Every one of those inputs is at its documented
maximum, so the configuration is legal — but there is no headroom at all, and the mechanism that
would catch the next increment is a
substr, not a validation.The documented limit no longer agrees with itself
v3.0.0and PR #213 moved most of the prefix guidance to 7. One document did not move:fast/stages-aw/0-bootstrap/variables.tf:331and:335fast/stages-aw/0-bootstrap/README.md:133,:383fast/stages-aw/0-bootstrap/terraform.tfvars.sample:30docs/ddg.md:75,:221docs/naming-convention.md:31An operator following
naming-convention.mdand an operator following the DDG will size their prefixdifferently, and only one of them is at the ceiling.
Environment and Deployment Context
main@6d7d08c0(2026-09-09). The truncation in both modules is unchanged atv2.13.0(8f5b67a6) andv3.0.0(f64ce6cd); the documentation split is new since PR fix(0-bootstrap): declare billing_override, fix the assured_workload output, align the prefix limit #213 (1ce9c3f3, merged 2026-09-05).Steps to Reproduce
prefixto any 7-character value infast/stages-aw/0-bootstrap/terraform.tfvars.1-resman, declare a tenant whose key is 6 characters (for examplereport) withenvs_foldersincludingTest.terraform planStage 1 and read the planned tenant IaC core project ID: it is exactly 30 characters.var.namefor that project inmodules/project, or imagine a future context token. The plan does not fail; it plans a shortened project ID.Expected Behavior
An ID that does not fit should stop the plan with a message naming the input that is too long, the same way
prefixandtenantsalready do. Where truncation is deliberate, the documented limits should leave enough room that it cannot be reached by a legal combination of inputs.docs/naming-convention.mdshould state the same prefix limit as the DDG, the variable description and the sample.Actual Behavior
substr(..., 0, 30)shortens the ID silently,trimsuffix(..., "-")can shorten it by one more, and the apply succeeds with a resource the operator did not name. The only guard is that today's longest legal combination happens to land on exactly 30.Relevant Logs and Errors
None — the absence of an error is the defect.
Additional Context
substrin both modules with aprecondition(or avalidationon the composed name) that fails with the offending value; (2) if truncation must stay for backward compatibility, log it via acheckblock; (3) correctdocs/naming-convention.mdto 7 so all five sources agree.prefixvalidations at0-bootstrap/variables.tf:334and1-resman/variables.tf:287disagree in form (<= 7vs< 8) though not in effect;2-networking-*and3-securityboth allow< 10, which is looser than either and would truncate.