diff --git a/decnet/web/router/swarm_mgmt/api_enroll_bundle.py b/decnet/web/router/swarm_mgmt/api_enroll_bundle.py index c099515..15c3f34 100644 --- a/decnet/web/router/swarm_mgmt/api_enroll_bundle.py +++ b/decnet/web/router/swarm_mgmt/api_enroll_bundle.py @@ -61,8 +61,12 @@ _EXCLUDES: tuple[str, ...] = ( "tests", "tests/*", "development", "development/*", "wiki-checkout", "wiki-checkout/*", - "decnet_web/node_modules", "decnet_web/node_modules/*", - "decnet_web/src", "decnet_web/src/*", + # Frontend is master-only; agents never serve UI. + "decnet_web", "decnet_web/*", "decnet_web/**", + # Master FastAPI app (API, routers, master-side DB) is not run on agents. + # The `agent` / `updater` / `forwarder` commands have their own apps under + # decnet/agent, decnet/updater — they don't import decnet.web. + "decnet/web", "decnet/web/*", "decnet/web/**", "decnet-state.json", "master.log", "master.json", "decnet.tar", diff --git a/tests/api/swarm_mgmt/test_enroll_bundle.py b/tests/api/swarm_mgmt/test_enroll_bundle.py index ee5b10d..d3a085f 100644 --- a/tests/api/swarm_mgmt/test_enroll_bundle.py +++ b/tests/api/swarm_mgmt/test_enroll_bundle.py @@ -297,6 +297,11 @@ async def test_get_tgz_contents(client, auth_token, tmp_path): assert not bad.endswith(".env"), f"leaked env file: {bad}" assert ".env.local" not in bad, f"leaked env file: {bad}" assert ".env.example" not in bad, f"leaked env file: {bad}" + # Master-only trees: agents don't run the FastAPI master app or the + # React frontend, so shipping them bloats the tarball and widens the + # worker's attack surface for no benefit. + assert not bad.startswith("decnet_web/"), f"leaked frontend: {bad}" + assert not bad.startswith("decnet/web/"), f"leaked master-api: {bad}" # INI content is correct ini = tf.extractfile("etc/decnet/decnet.ini").read().decode()