feat(canary): ship Node helper with wheel + install-toolchain CLI

The fingerprint canaries' obfuscator shells out to a Node helper that
require()s javascript-obfuscator. Without this commit, a fresh
pip install decnet would land the .py modules but not the .js helper /
package.json, and there'd be no documented way to provision Node side.

* pyproject.toml - extend tool.setuptools.package-data to ship
  canary/_obfuscate_helper.js, canary/fingerprint_payload.js, and
  canary/package.json with the wheel.
* decnet/cli/canary.py - new "decnet canary-install-toolchain"
  subcommand. Resolves decnet.canary.__file__'s dir, runs
  npm install --omit=dev there, exits non-zero with a clear message
  if npm is missing or install fails. Idempotent - safe to call
  every API service start.
* deploy/decnet-api.service.j2 - non-fatal ExecStartPre that calls
  the new subcommand. Leading '-' so a missing Node toolchain only
  degrades fingerprint canaries (loud at mint time) without keeping
  the API from booting.
* tests/canary/test_cli.py - registration smoke test, missing-npm
  exit path, and a mocked-subprocess test asserting the right argv
  and cwd land on npm.

Realism cultivator already has a broad except Exception around
cultivate() in scheduler.py:195-211, so a missing toolchain on a
host running the realism tick degrades to an inert noise file with
no extra plumbing.
This commit is contained in:
2026-04-29 16:53:27 -04:00
parent 907ade9142
commit f86dc79990
4 changed files with 123 additions and 5 deletions

View File

@@ -21,6 +21,10 @@ Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.api.log
# hardening stays on without crippling the build path.
Environment=DOCKER_CONFIG={{ install_dir }}/.docker
Environment=BUILDX_CONFIG={{ install_dir }}/.docker/buildx
# Provision the Node toolchain used by fingerprint canaries. Non-fatal
# (leading '-'): if Node is missing the API still boots; minting a
# fingerprint canary returns a clear error at request time. Idempotent.
ExecStartPre=-{{ venv_dir }}/bin/decnet canary-install-toolchain
ExecStart={{ venv_dir }}/bin/decnet api
StandardOutput=append:/var/log/decnet/decnet.api.log
StandardError=append:/var/log/decnet/decnet.api.log
@@ -32,7 +36,7 @@ AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
# Security Hardening
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=read-only
#ProtectHome=read-only
PrivateTmp=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes