Files
dashcaddy/dashcaddy-api
Hermes c721956a32 [pending-judge] feat(DC-164): operator env overrides in start.sh + lifetime-license wiring (rev2)
Operator requirement (Sami Ahmed, in-thread 2026-10-08): premium becomes a
creator-only LIFETIME license on his host, surviving BOTH failure domains
(license server down; machine/container rebuild).

Design: a safe, ENFORCED mechanism to turn on the pre-existing
ALLOW_LIFETIME_LICENSE gate (license-manager, DC-85) on exactly one host —
the flag lives OUTSIDE the repo in a root-owned file, so shipping start.sh
to customers cannot hand them a lifetime bypass.

- dashcaddy-api/scripts/operator-flags.sh: pure translator from
  /etc/dashcaddy/operator.env to docker -e flag material. It ENFORCES the
  operator-file security contract: regular file (not symlink), owner uid
  matches the reading identity (root => uid 0), mode grants neither group
  nor other access and no setuid/sticky bits. Violation => exit 3 + FATAL
  stderr and start.sh forwards NOTHING (fail closed). Never sources or
  executes file content: keys validated against [A-Za-z_][A-Za-z0-9_]*=,
  values pass through verbatim; missing file => silent exit 0 (normal
  customer case).
- start.sh: single helper execution, explicit exit-code inspection, flags
  expanded into docker run via the set-u-safe array construct. Without the
  file, docker args are byte-identical to before. Boot log prints KEY names
  only, never values.
- __tests__/scripts/operator-flags.test.js: 14 EXECUTED tests (8 behavior
  incl. an injection probe asserting command-substitution values stay inert
  text, + 6 security-contract: 0644/04600/symlink/foreign-owner/directory
  all => exit 3; root-0600 => emit).

Offline-mode resilience (ops-verified on DNS2, unchanged in code): with no
LICENSE_SERVER_URL the activation verifies by HMAC against the bind-mounted
.license-secret and persists in the mounted credential store; the lifetime
code (minted offline, keygen-verified LIFETIME, durationDays 0) re-activates
on rebuild. His premium is live: tier premium, lifetime true.

No runtime logic touched: license-manager, routes, app.js, Dockerfile
unchanged; 76+21 existing license tests stay green.
2026-10-08 22:29:49 -07:00
..
2026-03-05 02:26:12 -08:00