Follow-up to #420 / PR #433, split out rather than expanded into that PR. #433 closes the directory-shaped half of the leak; this is what is left, all measured through the built binary on that branch, not reasoned about.
1. The rules match NAMES, so these still upload
A synthetic project packaged with app submit --package-only on fix/420-dotenv-shaped-directories:
| planted |
in the bundle? |
db.env (project root) |
packaged — base name does not start with .env |
envs/prod.env |
packaged — neither name is .env-dotted |
env/local.env |
packaged — same |
.env-backup/db.env |
packaged — .env-backup is not .env.-dotted |
x.ZIP/a.txt |
packaged — the archive rule is case-sensitive |
.ENV.local/b.txt |
packaged — the dotenv rule is case-sensitive |
.env.d/should-drop.env |
correctly dropped (that is #420's fix working) |
envs/ and env/ are at least as conventional as .env.d/, and a bare db.env is what most tooling writes. The README on #433 now documents every row above, so this is a known gap rather than a surprise — but documenting a credential path is not closing it.
Worth considering, in rough order of value-per-risk:
- case-insensitive matching on both rules (cheap, no plausible collision);
- a
*.env suffix rule for files, which catches db.env / prod.env wherever they sit;
envs/ and env/ are NOT safe to add as fixed excludedDirs names — src/env/ is plausible app code. This one probably wants content-sniffing or a warning, not an exclusion.
2. A dropped subtree is invisible
internal/cmd/app_submit.go prints only Packaged %d file(s). isDotenvShaped's own comment names silent subtree removal as the failure mode it is trading against, and nothing mitigates it: measured 8 files → 6 with no message naming what went. A --verbose skipped-path list, or a one-line "skipped N path(s) (…)", would make an over-broad rule self-reporting instead of silent.
3. internal/antipattern keeps a rival exclusion list
internal/antipattern/antipattern.go:198-202 has its own 8-name skipDirs against excludedDirs' 18, and now also lacks the dotenv/archive directory rules — so validate can report findings in files the packager drops. Pre-existing divergence, marginally widened by #420; impact is limited by scannedExts. One predicate, one place.
Found by an adversarial audit of #433. Findings 1 and 2 there were fixed in-PR (7c833d2); these three were judged follow-ups rather than blockers.
Follow-up to #420 / PR #433, split out rather than expanded into that PR. #433 closes the directory-shaped half of the leak; this is what is left, all measured through the built binary on that branch, not reasoned about.
1. The rules match NAMES, so these still upload
A synthetic project packaged with
app submit --package-onlyonfix/420-dotenv-shaped-directories:db.env(project root).envenvs/prod.env.env-dottedenv/local.env.env-backup/db.env.env-backupis not.env.-dottedx.ZIP/a.txt.ENV.local/b.txt.env.d/should-drop.envenvs/andenv/are at least as conventional as.env.d/, and a baredb.envis what most tooling writes. The README on #433 now documents every row above, so this is a known gap rather than a surprise — but documenting a credential path is not closing it.Worth considering, in rough order of value-per-risk:
*.envsuffix rule for files, which catchesdb.env/prod.envwherever they sit;envs/andenv/are NOT safe to add as fixed excludedDirs names —src/env/is plausible app code. This one probably wants content-sniffing or a warning, not an exclusion.2. A dropped subtree is invisible
internal/cmd/app_submit.goprints onlyPackaged %d file(s).isDotenvShaped's own comment names silent subtree removal as the failure mode it is trading against, and nothing mitigates it: measured 8 files → 6 with no message naming what went. A--verboseskipped-path list, or a one-line "skipped N path(s) (…)", would make an over-broad rule self-reporting instead of silent.3.
internal/antipatternkeeps a rival exclusion listinternal/antipattern/antipattern.go:198-202has its own 8-nameskipDirsagainstexcludedDirs' 18, and now also lacks the dotenv/archive directory rules — sovalidatecan report findings in files the packager drops. Pre-existing divergence, marginally widened by #420; impact is limited byscannedExts. One predicate, one place.Found by an adversarial audit of #433. Findings 1 and 2 there were fixed in-PR (
7c833d2); these three were judged follow-ups rather than blockers.