Config & docs hygiene sweep: remove dead config and fix misleading docs#165
Merged
Conversation
The CONFIG env var is a leftover of the gconf loader that e2c06a7 replaced with pydantic-settings. Nothing reads it: config.toml is always loaded and local_config.toml overlays it whenever the file is present in the working directory. The justfile and CI values were doubly misleading because they named .yml files that have not existed since the TOML migration. Drop it from both run-dev recipes, the test workflow, and tests/conftest.py, and describe the actual loading mechanism in the README.
…ntroller pydantic-settings uses "__" as the nested delimiter, so FREESHARD_FREESHARD_CONTROLLER_BASE_URL never matched and was silently ignored: the recipe fell back to config.toml and talked to the production controller at https://controller.freeshard.net. Same bug class as 5de2998. Verified with: FREESHARD_FREESHARD_CONTROLLER__BASE_URL=http://127.0.0.1:8080 \ python -c "from shard_core.settings import Settings; \ print(Settings().freeshard_controller.base_url)" which prints the production URL before the change and the local one after.
DISABLE_SSL was interpolated without a default or a :? guard, so a self-hoster who omits the line from .env passed an empty string to FREESHARD_TRAEFIK__DISABLE_SSL, and Settings() failed at startup with "Input should be a valid boolean ... input_value=''". false matches both the field default and the documented .env.template value, so an unset var now behaves like an absent one. Verified with docker compose config: the var renders as "false" when unset and still honours an explicit DISABLE_SSL=true.
Both parse fine and do nothing, which makes them look load-bearing: - [portal_controller] base_url survived the portal -> freeshard-controller migration; service/portal_controller.py reads freeshard_controller.base_url, and nothing reads settings().portal_controller. - services.backup.included_globs was never wired into the rclone command; service/backup.py syncs the directories list only. Removing them keeps the config surface honest about what actually changes behavior. Settings() still loads and backup keeps syncing core and user_data.
The shard has never used Ed25519. service/crypto.py generates RSA-4096 keys and signs with PSS padding, and both peer auth (service/peer.py) and controller calls (service/signed_call.py) use HTTP Message Signatures with RSA_PSS_SHA512.
…own docs The link advertised "the latest stable release" but pointed at the abandoned GitLab pages of the pre-rename portal_core project, which still serve a 0.30.6 spec titled "Portal Core" while the repo is at 0.40.0. The app already serves Redoc at /redoc, Swagger at /docs and the schema at /openapi.json, so pointing there always matches the running version and cannot go stale again.
The skill library documented all six items as live problems, in some places
with a recorded reproduction. Left alone it would now teach the opposite of
the truth: nine SKILL.md files told agents that CONFIG is set-but-dead, that
the justfile recipe silently talks to production, that an unset DISABLE_SSL
crashes boot, that two dead config options are still parsed, and that
agents.md claims Ed25519.
Two rows carried their own retirement condition and had met it:
docs-and-positioning said "empty means FIXED; delete row 1", and
config-and-flags recommended exactly the ${DISABLE_SSL:-false} this PR wrote.
Where the finding taught something durable, the lesson is kept and the
specifics moved to history: the env-delimiter trap now leads with the
verify-one-liner, the compose trap generalises to any unguarded ${VAR}, and
the dead-config table becomes a record of what was removed plus the rule that
an option is only real if something reads it.
Line-number drift in file:line references is deliberately not chased; each
skill's drift table already says to re-verify those by grep, and much of the
drift predates this branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #128.
One mechanical sweep removing dead config and correcting docs that contradict the code. Each item was verified against the code before being touched, and the two runtime bugs were reproduced before and after the fix.
What changed
Dead
CONFIGenv var removed (README, both justfile run-dev recipes, CItest.yml,tests/conftest.py). Nothing has read it since e2c06a7 swapped gconf for pydantic-settings; the justfile/CI values additionally named.ymlfiles that no longer exist. The README now describes the real mechanism (config.toml+ optionallocal_config.tomloverlay +FREESHARD_*env, CWD-relative).justfile
run-dev-for-freeshard-controllerpointed at production.FREESHARD_FREESHARD_CONTROLLER_BASE_URLis one underscore short of the__nested delimiter, so pydantic-settings silently ignored it and the recipe talked tohttps://controller.freeshard.net. Same bug class as the 5de2998 incident. Reproduced both ways:DISABLE_SSLcould crash boot. It was interpolated bare, so a self-hoster omitting the line from.envpassed an empty string andSettings()raisedbool_parsingat startup. Now${DISABLE_SSL:-false};docker compose configrendersfalsewhen unset and still honours an explicittrue.Two dead config options removed:
services.backup.included_globs(never wired into the rclone command) and the[portal_controller]section (zero consumers —portal_controller.pyreadsfreeshard_controller.base_url). Note the naming trap survives deliberately: theportal_controller.pymodule is live.agents.md said Ed25519; the code is RSA-4096 with PSS padding (
service/crypto.py), and both peer auth and controller calls use HTTP Message Signatures withRSA_PSS_SHA512. Three claims corrected; zeroEd25519left in the repo.README's API-doc link. Worth a note: the issue called it dead, but it still returns HTTP 200 — it serves a Redoc render of a 0.30.6 spec titled "Portal Core" while the repo is at 0.40.0. So the falsehood was "of the latest stable release", not a 404. Replaced with a pointer to
/redoc,/docsand/openapi.json, which always match the running version.Skill library de-staled (last commit). Nine
SKILL.mdfiles documented these as live findings; left alone they would now teach the opposite of the truth. Two rows even carried their own retirement condition and had met it (docs-and-positioningsaid "empty means FIXED; delete row 1";config-and-flagsrecommended exactly the${DISABLE_SSL:-false}written here). Durable lessons are kept and reframed as history; the specific "still broken" claims are gone.Verification
173 passed(full suite),just cleanupclean,ruffclean.test_app_lifecycle.py::test_app_starts_and_stopsneeds to bind host port 80, which this dev VM's own Traefik holds (Bind for 0.0.0.0:80 failed: port is already allocated). It fails identically on unmodified main — I confirmed that in a clean worktree at the branch point, so it is environmental and not a regression from this PR. CI has port 80 free.Deliberately not done (two findings for you, not fixed here)
uv.lockis drifted on main: it pinsshard-core==0.39.5whilepyproject.tomlsays0.40.0, so anyuv runrewrites the lock and dirties the tree.uv sync --frozendoes not fail on it, so CI is unaffected. It predates this branch and looks like a 0.40.0 bump that landed before 2f4e134 taughtset-versionto keep the lock in sync. Left out of this PR as unrelated — worth its own one-line commit..serena/is untracked and not gitignored. The serena MCP writes it into the repo, and my firstgit add -Aswept it into a commit; I stripped it back out of history. Any bulk-commit recipe will sweep it again. A.gitignoreline would fix it, but that's your tooling choice, so I've only flagged it.Recommended reading order
shard_core/settings.py,config.toml— the dead optionsdocker-compose.yml,justfile,.github/workflows/test.yml,tests/conftest.py— the env-var fixesREADME.md,agents.md— the doc corrections.claude/skills/**— the de-staling sweep (largest diff, lowest risk; read last)🤖 Generated with Claude Code