Skip to content

fix(pkg): ship a sanitized default config instead of the maintainer's live one - #5

Merged
minglong51 merged 1 commit into
mainfrom
prelaunch/0.2.6-packaging
Aug 21, 2026
Merged

fix(pkg): ship a sanitized default config instead of the maintainer's live one#5
minglong51 merged 1 commit into
mainfrom
prelaunch/0.2.6-packaging

Conversation

@minglong51

Copy link
Copy Markdown
Owner

Why

agent_usage_manager/agents.yaml is doing two incompatible jobs at once. It is the live config on this machine — the launchd job passes it explicitly:

--config /Users/oclaw/projects/agent-usage-manager/agent_usage_manager/agents.yaml

and it is also the fallback the wheel ships, because _resolve_config() ended at BASE / "agents.yaml".

So the published 0.2.5 wheel carries an active alerts block pointing at a private path:

alerts:
  command: '"$HOME/workspace/founder-agent-os/bin/attention" add --level fyi ...'

I confirmed this by unzipping the wheel straight from PyPI, then reproduced the user-facing result with an empty $HOME:

agent-usage-manager test-alert on a clean machine
0.2.5 FAILED: exit 127 — /bin/sh: ~/workspace/founder-agent-os/bin/attention: No such file or directory
this PR no alerts.command configured in .../agents.default.yaml — nothing to test

test-alert is a documented, advertised command, so this is on a path users are told to walk. README:70-89 presents alerts: as something the user adds, with a terminal-notifier example — the shipped default contradicted the docs and named private infrastructure in a public package.

What changed

  • agents.default.yaml (new) — same agents: / protect: / ignore: rules and explanatory comments; launchd_labels, tmux_labels, idle_ok and alerts all commented out as generic examples. Nothing wired by default.
  • _resolve_config() falls through to agents.default.yaml only when agents.yaml is absent. Source checkouts resolve exactly as before.
  • agents.yaml excluded from the wheel and sdist targets.

Pre-launch packaging polish in the same pass:

  • README's two images used relative paths, so both were broken on the PyPI project page. Now absolute raw URLs — unchanged on GitHub.
  • 14 trove classifiers added; there were zero, which is the standard "unfinished package" tell.
  • Issues and Newsletter project URLs. Newsletter puts the waitlist in PyPI's permanent sidebar, where it wasn't present at all.
  • Second waitlist mention after Quick start. The only one sat at 99.5% README depth, below Troubleshooting.

Your live setup is untouched

agent_usage_manager/agents.yaml is not modified or deleted by this PR — it stays in the repo exactly as it is. The launchd job keeps reading the same path and your bin/attention alert wiring keeps working. Merging this changes nothing about the running instance on this host.

The only behavioural difference is for someone who installs from PyPI and has no config of their own.

Verification

  • 74 passed (uv run --extra dev pytest)
  • wheel contains agents.default.yaml only; grep -r founder-agent-os over the extracted wheel returns nothing
  • built METADATA carries 14 Classifier: lines, 4 Project-URL: lines, and absolute image URLs
  • fresh uvx --from <wheel> on an empty $HOME: test-alert reports no alert configured, and list still works out of the box against the shipped default

Not done here

Version is bumped to 0.2.6 but nothing is published — releasing still needs a tag and your approval of the pypi environment gate.

Opened as a draft deliberately: this touches the artifact that a Show HN audience will install, so it should get your eyes before it ships.

… live one

agent_usage_manager/agents.yaml served two masters: it is the maintainer's live
config (launchd points at it directly) AND the fallback the wheel ships. So every
`pip install` / `uvx` user received a default whose alerts.command shells out to
"$HOME/workspace/founder-agent-os/bin/attention" — a private repo path that
exits 127 on any other machine, while README documents alerts as something the
user adds with a terminal-notifier example. The shipped default contradicted the
docs and leaked private infrastructure naming into a public package.

Before, on a clean machine:
  $ agent-usage-manager test-alert
  FAILED: exit 127 - /bin/sh: ~/workspace/founder-agent-os/bin/attention: No such file
After:
  no alerts.command configured in .../agents.default.yaml - nothing to test

- add agent_usage_manager/agents.default.yaml: same agents/protect/ignore rules
  and docs, with launchd_labels, tmux_labels, idle_ok and alerts commented out as
  generic examples. Nothing is wired by default.
- _resolve_config() falls back to agents.default.yaml only when agents.yaml is
  absent, so source checkouts (and the maintainer's launchd job) are unchanged.
- exclude agents.yaml from both wheel and sdist targets.

Also, pre-launch packaging polish:
- absolute raw.githubusercontent URLs for the two README images, which were
  relative and therefore broken on the PyPI project page.
- 14 trove classifiers (there were none - the standard unfinished-package tell).
- Issues and Newsletter project URLs; Newsletter puts the waitlist in PyPI's
  permanent sidebar.
- second waitlist mention after Quick start; the only one sat at 99.5% README
  depth, below Troubleshooting.

74 tests pass. Wheel verified to contain agents.default.yaml only, with no
occurrence of the private path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015swHyENHGowhH1cwMXxiE2
@minglong51
minglong51 marked this pull request as ready for review August 21, 2026 23:40
@minglong51
minglong51 merged commit 5727f00 into main Aug 21, 2026
4 checks passed
minglong51 added a commit that referenced this pull request Aug 22, 2026
…lowlist (#6)

_LOCAL_HOSTS carried "minglongs-mac-mini.tailab5be0.ts.net" as a literal, and it
ships in the published 0.2.5 wheel on PyPI (verified by unzipping the artifact
from the index). Two problems, and the second is the reason this is worth fixing
before a security-framed launch:

1. It publishes the maintainer's machine name and tailnet ID to everyone who
   installs the package.
2. It puts a hardcoded exception inside the DNS-rebinding guard. The guard's
   whole claim is "requests whose Host is a non-local DNS name are refused" —
   and the shipped source shows one specific non-local DNS name that is not.
   Anyone reading app.py while evaluating the kill-switch story finds it.

For every other user the entry was also dead weight: an allowlisted hostname
they do not control and cannot use.

Replaced with AUM_TRUSTED_HOSTS, a comma-separated opt-in read at import:

    _LOCAL_HOSTS = {"localhost", "127.0.0.1", "::1"} | _configured_trusted_hosts()

Empty by default, so out of the box only loopback names are accepted. This also
turns a maintainer-specific hack into the general feature the README already
described — anyone fronting the app with a reverse proxy or tailnet serve needs
exactly this, and previously had no way to get it.

Verified:
- 74 tests pass
- default: _LOCAL_HOSTS == {127.0.0.1, ::1, localhost}; the tailnet FQDN is
  refused; localhost still allowed
- with AUM_TRUSTED_HOSTS set: that FQDN allowed, an unrelated host still refused
- rebuilt wheel greps clean for tailab5be0 / minglongs / oclaw / founder-agent-os;
  the only remaining "ts.net" is the generic README placeholder

Rides the unreleased 0.2.6, so one release fixes both this and the shipped
config leak from #5.


Claude-Session: https://claude.ai/code/session_015swHyENHGowhH1cwMXxiE2

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@minglong51
minglong51 deleted the prelaunch/0.2.6-packaging branch August 22, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant