You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gapp uses the "solution name" as the primary identifier in several
places that create persistent, hard-to-rename external state:
GCP project label (gapp-{solution_name}=default, applied by gapp setup) — used by gapp list --available and discover_project_from_label to locate which project a solution
is deployed to.
GCS bucket name (gapp-{solution_name}-{project_id}, created
by gapp setup) — the solution's data bucket.
Secret Manager IDs ({solution_name}-{secret_short_name}) —
every secret declared in the manifest is prefixed by the
solution name.
Local registry (~/.config/gapp/solutions.yaml) — keyed by
solution name.
GitHub topic — the gapp-solution topic itself is not
name-scoped, but the repo→name mapping is implicit.
The directory name is a poor default. A repo can live under
any folder — developers check repos out into directories named
after the repo, shortened, renamed, inside monorepos, etc. The
solution name deserves to be bound to something more intentional
than "whatever the user called their clone directory."
No first-class way to set the name on bootstrap. gapp init takes no --name flag today. Users who want a name
other than the directory name must hand-edit gapp.yaml after
init and hope nothing downstream has already captured the wrong
name.
Silent-rename footguns. Because name: is freely editable in
the yaml and get_solution_name re-reads it on every load, a
user who changes name: in the yaml (or renames the repo
directory pre-init) silently triggers:
A second gapp-{new_name} label on the GCP project, leaving
the old gapp-{old_name} label dangling.
A second GCS bucket (gapp-{new_name}-{project}) on next gapp setup, leaving the old bucket orphaned.
A new entry in solutions.yaml under the new name; the old
entry is never cleaned up.
Secret Manager IDs under a new prefix on next deploy; old
secrets orphaned.
None of these issues are detected or warned about. A user
discovers the breakage when gapp list --available starts
showing phantom duplicates or when lookups start failing.
No alternative sources for derivation. Python projects
already declare an authoritative name in pyproject.toml
([project].name), Node projects in package.json, etc. gapp
ignores all of them and falls back to the directory.
Scope of exploration
This issue does not prescribe a solution — it enumerates the
design space so a decision can be made with full context.
Candidate sources for the name
In order of explicitness:
Explicit CLI arg on bootstrap — gapp init --name <X>.
Writes name: into the newly-created gapp.yaml.
Explicit yaml name: — current primary source.
Project-manifest fallback — if name: is absent, read pyproject.toml[project].name (or package.jsonname,
etc.) as a more-intentional default than the directory name.
Directory-name fallback — current behavior. Candidate for
removal.
Candidate rules for the lifecycle
Locked after init. Once gapp init has run, the name is
committed to yaml and changing it requires gapp rename <new_name> which handles the cleanup: remove old label, old
bucket, old registry entry, old secrets. This is the safe
default and should probably be the rule regardless of other
decisions.
Schema validation warns on unregistered manifests. If the
repo has no entry in solutions.yaml and yaml name: differs
from what init would have derived, warn loudly.
Make name: advisory in yaml but canonical in solutions.yaml. The local registry becomes the source of
truth after init; yaml is merely informational. Any mismatch
triggers an error, not a silent rename.
Or keep name: canonical and enforce by validator. The
validator could refuse to load a manifest whose name: differs
from the registered name without an explicit gapp rename step.
Candidate commands/flows
gapp init --name <X> — set on bootstrap.
gapp rename <new> — explicit rename with cleanup of label,
bucket, registry, secrets.
Validator check: mismatch between yaml name: and solutions.yaml registered name → error with hint to run gapp rename.
Relationship to other issues
Companion to the gapp init / gapp manifest taxonomy issue.
That issue decides where name configuration lives in the CLI
(probably bootstrap-only). This issue decides how the name is
resolved from available sources and what happens when it changes.
Should pyproject.toml/package.json derivation be built into
gapp or left as "users who want it set name: explicitly"?
Should gapp rename exist? Or is the contract "you don't
rename — you re-init"? Re-init implies deleting the old
project state manually.
Should the validator refuse to load a manifest whose name:
has been edited after registration? If yes, with what escape
hatch?
Is the directory-name fallback worth keeping at all, given how
unreliable it is, or should a missing name: simply be an error
with a hint to run gapp init --name <X>?
Work breakdown
Enumerate every place the solution name is used for persistent
external state (labels, buckets, registry, secret prefixes,
anything else). Verify the list above is complete.
Decide which candidate sources gapp supports and in what order.
Decide the lifecycle rule (locked after init / advisory / etc).
Decide whether gapp rename is implemented; if yes, what
cleanup it performs.
Implement decisions. Each behavior change needs a code
comment or docstring at the point of use explaining the rule.
Add tests covering: init with --name flag, rename flow
(if implemented), validator behavior on name mismatch between
yaml and registry, fallback behavior when name: is absent.
Update CONTRIBUTING.md under design decisions with the
chosen rule, so future contributors don't re-introduce silent
rename paths.
Update README.md to show how to set the name intentionally
on bootstrap.
Problem
gapp uses the "solution name" as the primary identifier in several
places that create persistent, hard-to-rename external state:
gapp-{solution_name}=default, applied bygapp setup) — used bygapp list --availableanddiscover_project_from_labelto locate which project a solutionis deployed to.
gapp-{solution_name}-{project_id}, createdby
gapp setup) — the solution's data bucket.{solution_name}-{secret_short_name}) —every secret declared in the manifest is prefixed by the
solution name.
~/.config/gapp/solutions.yaml) — keyed bysolution name.
gapp-solutiontopic itself is notname-scoped, but the repo→name mapping is implicit.
Current resolution order
In
gapp/admin/sdk/manifest.py::get_solution_name:name:ingapp.yamlsolution.name:— removed as vestigial in Formal schema validation for gapp.yaml (fail fast with clear errors) #26)What's broken
any folder — developers check repos out into directories named
after the repo, shortened, renamed, inside monorepos, etc. The
solution name deserves to be bound to something more intentional
than "whatever the user called their clone directory."
gapp inittakes no--nameflag today. Users who want a nameother than the directory name must hand-edit
gapp.yamlafterinit and hope nothing downstream has already captured the wrong
name.
name:is freely editable inthe yaml and
get_solution_namere-reads it on every load, auser who changes
name:in the yaml (or renames the repodirectory pre-init) silently triggers:
gapp-{new_name}label on the GCP project, leavingthe old
gapp-{old_name}label dangling.gapp-{new_name}-{project}) on nextgapp setup, leaving the old bucket orphaned.solutions.yamlunder the new name; the oldentry is never cleaned up.
secrets orphaned.
None of these issues are detected or warned about. A user
discovers the breakage when
gapp list --availablestartsshowing phantom duplicates or when lookups start failing.
already declare an authoritative name in
pyproject.toml(
[project].name), Node projects inpackage.json, etc. gappignores all of them and falls back to the directory.
Scope of exploration
This issue does not prescribe a solution — it enumerates the
design space so a decision can be made with full context.
Candidate sources for the name
In order of explicitness:
gapp init --name <X>.Writes
name:into the newly-createdgapp.yaml.name:— current primary source.name:is absent, readpyproject.toml[project].name(orpackage.jsonname,etc.) as a more-intentional default than the directory name.
removal.
Candidate rules for the lifecycle
gapp inithas run, the name iscommitted to yaml and changing it requires
gapp rename <new_name>which handles the cleanup: remove old label, oldbucket, old registry entry, old secrets. This is the safe
default and should probably be the rule regardless of other
decisions.
repo has no entry in
solutions.yamland yamlname:differsfrom what init would have derived, warn loudly.
name:advisory in yaml but canonical insolutions.yaml. The local registry becomes the source oftruth after init; yaml is merely informational. Any mismatch
triggers an error, not a silent rename.
name:canonical and enforce by validator. Thevalidator could refuse to load a manifest whose
name:differsfrom the registered name without an explicit
gapp renamestep.Candidate commands/flows
gapp init --name <X>— set on bootstrap.gapp rename <new>— explicit rename with cleanup of label,bucket, registry, secrets.
name:andsolutions.yamlregistered name → error with hint to rungapp rename.Relationship to other issues
gapp init/gapp manifesttaxonomy issue.That issue decides where name configuration lives in the CLI
(probably bootstrap-only). This issue decides how the name is
resolved from available sources and what happens when it changes.
name:optional; this issue decides whether to keep it optional,deprecate it in favor of registry + fallbacks, or add validation
rules around it.
Open design questions
pyproject.toml/package.jsonderivation be built intogapp or left as "users who want it set
name:explicitly"?gapp renameexist? Or is the contract "you don'trename — you re-init"? Re-init implies deleting the old
project state manually.
name:has been edited after registration? If yes, with what escape
hatch?
unreliable it is, or should a missing
name:simply be an errorwith a hint to run
gapp init --name <X>?Work breakdown
external state (labels, buckets, registry, secret prefixes,
anything else). Verify the list above is complete.
gapp renameis implemented; if yes, whatcleanup it performs.
comment or docstring at the point of use explaining the rule.
--nameflag, rename flow(if implemented), validator behavior on name mismatch between
yaml and registry, fallback behavior when
name:is absent.CONTRIBUTING.mdunder design decisions with thechosen rule, so future contributors don't re-introduce silent
rename paths.
README.mdto show how to set the name intentionallyon bootstrap.