Skip to content

docs(selfhost): document every docker-compose.yml var in .env.example - #6118

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
luciferlive112116:docs/env-example-missing-vars
Jul 15, 2026
Merged

docs(selfhost): document every docker-compose.yml var in .env.example#6118
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
luciferlive112116:docs/env-example-missing-vars

Conversation

@luciferlive112116

Copy link
Copy Markdown
Contributor

Summary

Closes #5814

docker-compose.yml's own header calls .env.example "the exhaustive reference" an operator copies to .env before running the stack. It wasn't. Cross-referencing every ${VAR} interpolation compose actually uses against every name the sample file documents (live NAME= and commented # NAME= alike) found 18 real gaps — knobs the stack reads that an operator could only discover by reading docker-compose.yml itself:

Area Undocumented vars
--profile backup (entirely undocumented) BACKUP_RETAIN, BACKUP_INTERVAL_SECONDS, and the opt-in restore-drill pair VERIFY_RESTORE_SCRATCH + LOOPOVER_VERIFY_SCRATCH_DATABASE_URL
AMS reporting-exporter paths the four LOOPOVER_AMS_*_SOURCE_DB / *_REPORTING_DB overrides
Core reporting-exporter LOOPOVER_REPORTING_DB (the documented LOOPOVER_REPORTING_SOURCE_DB's output sibling)
Always-on loopover service LOOPOVER_REPO_CONFIG_DIR
OTEL metrics side OTEL_METRICS_EXPORTER, OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
Misc PROMETHEUS_RETENTION_TIME, REES_MEM_LIMIT, INSTALL_VISUAL_REVIEW
Compose/system COMPOSE_PROJECT_NAME, TZ

Each is added in the file's existing # NAME=default # explanation, --profile X style, grouped under the section it belongs to (a new "Snapshot backups" block under the existing backup section, the OTEL metrics vars beside their traces siblings, REES_MEM_LIMIT in the *_MEM_LIMIT block, etc.). No default or behavior is invented — every documented value is the one docker-compose.yml already uses (BACKUP_RETAIN=7, PROMETHEUS_RETENTION_TIME=90d, …), and PROMETHEUS_RETENTION_TIME's note summarizes compose's own stated rationale rather than inventing one.

Two deviations from the issue's list, both deliberate

  1. COMPOSE_PROJECT_NAME and TZ are included though the issue's enumeration omits them. They are real compose interpolations (${COMPOSE_PROJECT_NAME:-loopover} in promtail, ${TZ:-UTC} in n8n), so the drift guard this issue requires fails unless they're documented too. Documenting them is what makes the file exhaustive — the issue's own Expected Outcome.
  2. GF_SECURITY_ADMIN_PASSWORD / N8N_BASIC_AUTH_PASSWORD are not included, though a naive grep suggests they're missing. They appear as $${VAR} — compose escapes a literal $ as $$, so those reach the container's shell and are resolved there. They are not compose variables, and documenting them as .env knobs would be wrong. The guard's regex encodes this (see below).

Scope

Validation

  • git diff --check clean.
  • New drift guard green (5 tests), plus the sibling .env.example metric-name guard — 6 tests passed.
  • Verified the gap list independently rather than trusting the issue: parsed all 97 compose interpolations and diffed against the documented set. Re-ran after the edit → zero remaining gaps.
  • Proved the guard catches the real bug: reverted only .env.example and the invariant reports exactly the 18 pre-fix gaps ([ 'BACKUP_INTERVAL_SECONDS', …(17) ]); restored → green.
  • Rebased onto current main (which already carries fix(selfhost): correct stale gittensory_ metric names in .env.example #6079's .env.example change — no conflict).

The guard (test/unit/docker-compose-env-example-parity.test.ts) is a distinct check from npm run selfhost:env-reference, which scans process.env reads under src/selfhost/** and never looks at docker-compose.yml or .env.example. It covers, per the issue's requirement of both a pass and a fail case:

  • Pass: every compose var is documented in .env.example or secrets/README.md.
  • Fail (fixture): a variable stripped from .env.example is reported — proving it catches drift, not just that it passes today.
  • $$-escape: $${FOO} is ignored, ${BAR} is not.
  • Secrets path: a *_FILE var counts as documented via secrets/README.md, and is reported when documented in neither.
  • Parser self-guard: asserts it found >50 compose vars and >50 documented names, so a regex regression can't make the invariant pass vacuously.

If any required check was skipped, explain why:

  • Full test:ci not run end-to-end locally (Linux-only steps on Windows).
  • Codecov: .env.example is a config file outside coverage.include, so the patch gate does not apply to the documentation edit; the new guard lives under test/unit/**. The guard's own logic is fully exercised by the five cases above (both sides of every branch: documented/undocumented, escaped/unescaped, secrets/not-secrets).

Safety

  • No secrets, wallets, hotkeys, trust scores, rewards, private rankings, or private maintainer evidence. Every added line is a commented sample; no real value is committed, and the two password vars that look missing are deliberately excluded (see above) rather than documented with invented values.
  • No auth/cookie/CORS/GitHub App/session change; no application runtime code touched.
  • No API/OpenAPI/MCP change; no schema change; no generated artifact affected.
  • Every added var is commented out, so copying .env.example.env yields byte-identical runtime behavior to today — the defaults documented are the ones compose already applies.
  • No UI changes; no changelog edit.

docker-compose.yml's header calls .env.example "the exhaustive reference"
an operator copies to .env before running the stack. Cross-referencing
every ${VAR} interpolation against every name the sample file documents
found 18 real gaps -- knobs the stack reads that an operator could only
discover by reading docker-compose.yml itself:

- --profile backup, entirely undocumented: BACKUP_RETAIN,
  BACKUP_INTERVAL_SECONDS, and the opt-in restore-drill pair
  VERIFY_RESTORE_SCRATCH + LOOPOVER_VERIFY_SCRATCH_DATABASE_URL.
- The four AMS exporter source/reporting DB path overrides, and the
  core exporter's LOOPOVER_REPORTING_DB output path.
- LOOPOVER_REPO_CONFIG_DIR, read by the always-on loopover service.
- The OTEL metrics-side siblings of the documented traces vars:
  OTEL_METRICS_EXPORTER, OTEL_EXPORTER_OTLP_PROTOCOL,
  OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE.
- PROMETHEUS_RETENTION_TIME, REES_MEM_LIMIT (the one omission from the
  otherwise-exhaustive *_MEM_LIMIT block), INSTALL_VISUAL_REVIEW.
- COMPOSE_PROJECT_NAME and TZ, which the drift guard below also requires
  and which the issue's own "exhaustive" outcome covers.

Every documented default is the one docker-compose.yml already uses; no
default or behavior is invented, and each var is grouped under the
section it belongs to in the file's existing comment style.

The guard parses compose's interpolations and both reference files, then
asserts none is undocumented. Its negative lookbehind is load-bearing:
compose escapes a literal $ as $$, so $${GF_SECURITY_ADMIN_PASSWORD:-} is
resolved by the container's shell and is not a compose variable --
demanding .env.example document it would be wrong. Covers the pass case,
a stripped-fixture fail case, the $$-escape case, and the secrets/
README.md path, so this gap class cannot silently reopen.

Closes JSONbored#5814
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.31%. Comparing base (d7b0810) to head (7ce3966).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6118      +/-   ##
==========================================
+ Coverage   86.41%   95.31%   +8.89%     
==========================================
  Files         595      595              
  Lines       47083    47097      +14     
  Branches    15022    15030       +8     
==========================================
+ Hits        40688    44890    +4202     
+ Misses       4972     1476    -3496     
+ Partials     1423      731     -692     
Flag Coverage Δ
shard-1 43.56% <ø> (?)
shard-2 36.76% <ø> (+0.13%) ⬆️
shard-3 32.05% <ø> (-0.02%) ⬇️
shard-4 34.02% <ø> (+0.26%) ⬆️
shard-5 31.47% <ø> (-0.19%) ⬇️
shard-6 44.87% <ø> (+0.33%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 115 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 15, 2026
@loopover-orb

loopover-orb Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-15 10:14:06 UTC

2 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This is a pure documentation PR that adds 18 previously-undocumented docker-compose.yml variables to .env.example in the file's existing commented-reference style, and backs the change with a new drift-guard test that regex-parses docker-compose.yml's `${VAR}` interpolations against .env.example and secrets/README.md to prevent future gaps. The values documented (BACKUP_RETAIN=7, PROMETHEUS_RETENTION_TIME=90d, etc.) are claimed to match compose's actual defaults, which is plausible and low-risk to verify by eye. The added test is real, drives an actual invariant against the live docker-compose.yml/.env.example files rather than a fabricated payload, and includes negative-path checks (escaped `$$` vars, a deliberately-broken case) that guard the parser itself.

Nits — 4 non-blocking
  • The regex `documentedInEnvExample` in test/unit/docker-compose-env-example-parity.test.ts:23 treats any `# NAME=` comment line as documentation, so a stray comment mentioning `# FOO=bar` in prose (not an actual var reference) would silently count as documenting FOO; worth a comment noting this is a known looseness.
  • The PR trusts that every added default (e.g. BACKUP_RETAIN=7, OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative) exactly matches docker-compose.yml's current defaults, but the diff doesn't show docker-compose.yml itself, so this can't be independently verified from the diff alone.
  • Consider having the new test also assert that documented .env.example values (not just names) match the compose defaults, to catch future drift where a var is documented but with a stale default.
  • The secrets_FILE detection in documentedInSecretsReadme (test file, line ~35) matches any `_FILE` suffixed identifier anywhere in secrets/README.md prose, not just the table — a tightened anchor to the table rows would reduce false-negatives risk if the README's prose ever changes.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #5814
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 113 registered-repo PR(s), 57 merged, 35 issue(s).
Contributor context ✅ Confirmed Gittensor contributor luciferlive112116; Gittensor profile; 113 PR(s), 35 issue(s).
Gate result ✅ Passing No configured blocker found.
Improvement ℹ️ Insufficient signal risk: clean · value: insufficient-signal · LLM: moderate
Linked issue satisfaction

Addressed
The diff adds all ~15 variables listed in the issue (backup profile vars, AMS exporter path overrides, LOOPOVER_REPORTING_DB, LOOPOVER_REPO_CONFIG_DIR, OTEL metrics siblings, PROMETHEUS_RETENTION_TIME, REES_MEM_LIMIT, INSTALL_VISUAL_REVIEW) in the file's existing comment convention and correct sections, and includes a new drift-guard test that parses docker-compose.yml interpolations against .env.

Review context
  • Author: luciferlive112116
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, JavaScript, MDX, Rust, TypeScript
  • Official Gittensor activity: 113 PR(s), 35 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 5a3eb32 into JSONbored:main Jul 15, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(selfhost): .env.example is missing ~15 vars docker-compose.yml actually reads (backup, AMS exporter paths, OTEL metrics, retention)

1 participant