Commit Graph
460 Commits
Author SHA1 Message Date
Hermes Agent 88c9a3e4b6 [pending-judge] fix(r4/polish1): server-assigned port — no freePort release-rebind race
The e2e child now calls app.listen(0) and reports the OS-assigned port on
stdout (PORT:<n>); the parent reads it. The probe-then-release helper is
deleted, so no other process can take the port between probe and bind.
2026-10-07 04:23:00 -07:00
Hermes Agent 5cf5dac281 [pending-judge] fix(r4): audit contract, subdomain forwarding, timeout kill (judge r3 blockers)
BLOCK0: catalog deploy audit now uses the REAL AuditLogger contract
(auditLogger.log({action,resource,details,outcome,ip})) fire-and-forget
via Promise.resolve().catch — async audit failures can never fail the
deploy response (tested with a throwing audit backend).
BLOCK1: verify.sh targeted-jest block captures jest exit code explicitly
(set +e / rc / loud FAIL) — no silent termination under set -e.
BLOCK2: subdomain advertised by the App Selector modal is now FORWARDED
end-to-end (selector -> /deploys/catalog/deploy validated charset ->
bridge --subdomain -> CLI CatalogInstallOptions, implemented in
dc-catalog-2 r3); invalid subdomains 400 before the bridge (4 cases).
POLISH: boot-timeout SIGKILLs the child (no leaked process).
New r4 suite: 7 tests (audit shape success/failure, subdomain forward +
4 rejections). Full suite 157 suites / 3519 tests green.
2026-10-07 03:59:30 -07:00
Hermes Agent 5bd5345469 [pending-judge] test(e2e): authenticated composition-root probes (r2 C blockers)
Judge r2 blockers addressed:
- MOUNTED vs UNKNOWN: probes now carry a REAL JWT minted by the same
  authManager the app wires (sub claim; generated in the boot child,
  emitted on READY). Every mounted-route assertion is compared against a
  live notFoundHandler-404 baseline for a known-nonexistent route on the
  same instance — a fall-through can no longer pass as mounted.
- Route-level behavior asserted with real payloads: /catalog/plex 200
  must contain plexinc/pms-docker AND {{PORT}}:32400; /security/shield 200
  must be success:true.
- OS-assigned ephemeral port (net server listen(0)) replaces the random
  30000-49999 guess; boot-timeout cleared on readiness; SIGTERM+SIGKILL
  shutdown with bounded wait.
- 7 tests (was 5). Suite: 156 suites / 3512 tests green.
2026-10-07 03:09:14 -07:00
Hermes Agent 0704676741 [pending-judge] feat(deploys): catalog deploy via shipdeck bridge (DC-CATALOG-3)
GET /deploys/catalog/apps -> bridge /api/catalog/apps (73 embedded apps,
single source of truth). POST /deploys/catalog/deploy {app,port,env} ->
validated (service-id charset, port 1024-65535, env name/value rules) then
proxied to bridge /api/catalog/deploy which runs the shipdeck CLI catalog
deploy (OCI image -> hardened systemd service; NO Docker daemon). Audited
as deploy.catalog with ok/seconds. 11 table-driven route tests incl.
validation rejections never reaching the bridge + bridge-failure 502 shape.
App Selector submit rewired from /apps/deploy (Docker chain) to
/deploys/catalog/deploy — same modal, same fields (port, mediaPath, plex
claim token as env), no new UI screens. Full suite 3510/3510 (156 suites).
2026-10-07 02:08:32 -07:00
Hermes Agent 8744609887 [pending-judge] fix(integration): catalog detail reads app.docker.* (DC-160); Shield committed; composition-root e2e
- DC-160: /catalog/:appId read app.image/ports/env/volumes which live under
  app.docker.* — every detail response was empty. Now reads docker.* and
  surfaces defaultPort/subdomain/healthCheck/mediaMount/claimToken/difficulty/
  setupInstructions for the deploy form. List/search use the templates own
  category field (old hand-rolled CATEGORY_MAP mis-categorized apps).
- Shield (routes/shield.js + 5-line app.js mount) committed to source after
  weeks as prod-only drift; regression test asserts the mount exists.
- New composition-root e2e suite: boots REAL createApp() on an ephemeral
  port, probes the historically-broken routes through the REAL mount table
  (wizard wiring, shield, catalog detail, deploys bridge) — the class of bug
  all 3 P7 dogfood findings belonged to. 5 tests.
- Full suite 3499/3499 (155 suites); table-driven DC-160 test covers all 73
  image templates.
2026-10-07 00:58:03 -07:00
Hermes Agent c430e02117 [grade=B urn:ump:bbfbsfru4nizg75wcxum7mwzhie6txhr22hw6jvz36wiihmgzmlq] P7 people store: dedupe upsert by providerUserId
CI / Test & Lint (pull_request) Canceled after 0s
CI / Security audit (pull_request) Canceled after 0s
Dogfood finding #3: upsertPerson resolved existing records by id only.
The wizard upserts a bootstrap admin AFTER a provider sync has already
created a person for the same Tailscale user (no id passed), so the same
providerUserId was duplicated into two records. Resolve existing by
providerUserId when no id is given; bootstrap Admin group + protectedAt are
preserved on the merge. New regression test; full suite 3414/3414.
2026-10-04 03:12:23 -07:00
Hermes Agent 5b3e637423 [grade=B urn:ump:mao7vadnesmquhmgr4oeg554edt6fn3ykxyiydtfs2psoekd4s7q] P7 tailscale provider: wire coord client via ctx delegation
CI / Test & Lint (pull_request) Canceled after 0s
CI / Security audit (pull_request) Canceled after 0s
Dogfood finding #2: createTailscaleProvider() built with coordClient=null;
nothing in prod ever called attachCoordClient() (the wiring the provider
docblock promised never landed), so wizard credential validation always
failed not_configured even with a valid stored token. Pass a delegating
proxy that fetches a fresh coord client per call via the sanctioned
ctx.tailscaleCoord.getClient pattern (token re-read from credentialManager
each call). Full suite 3413/3413.
2026-10-04 02:51:18 -07:00
Hermes Agent f7d6fe4a8a [grade=B urn:ump:2swys44kxvulm5flu4skibjq3yfvtnzrsbgkvm2g65ht55i4jtoa] P7 wizard prod wiring: pass provider instances (dogfood finding)
CI / Test & Lint (pull_request) Canceled after 0s
CI / Security audit (pull_request) Canceled after 0s
The /network/wizard mount in app.js omitted providers, so the wizard built
with providers={} and every mode selection returned 503 provider_unavailable
in production. Unit tests never caught it because they inject their own
provider map. Pass built tailscale + wireguard instances.

Full suite: 3413/3413 (152 suites).
2026-10-04 02:41:31 -07:00
sami7777 e04787477a P7 Private Network [grade=A] (PR #1)
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s
Judge A r18 urn:ump:rgxdivsp2xf6zy5lsdoclvdgb7cuqd3qpwlszt2p7fu7xwa3zkkq. 3,399/3,399 tests.
2026-10-04 11:04:23 +02:00
Hermes 75a0385c38 P7 r10: probes assert expected head + every outcome (nonzero exit on mismatch); phase-2 rejection-path cleanup guaranteed
CI / Test & Lint (pull_request) Canceled after 0s
CI / Security audit (pull_request) Canceled after 0s
2026-10-04 00:07:56 -07:00
Hermes 51ba85fc69 P7 r9: probes isolated (DATA_DIR tmp), self-authenticating (git stamp + asserts), try/finally cleanup, explicit exit 2026-10-03 23:47:43 -07:00
Hermes af0d6b2fe5 P7 live probes: real-HTTP transcripts for forward_auth (inactive 503; active: allow/deny/unknown-device/step-up) via seeded real stores + registry stub provider 2026-10-03 23:39:01 -07:00
Hermes 2e651bd84e P7 r8 fixes: lazy mounts catch ProviderNotActiveError (503 not 500), wg redeem added to PUBLIC_ROUTES (redemption is sessionless), live-curl probe script 2026-10-03 23:34:00 -07:00
Hermes d4973f3af3 P7 r8 fix: forward_auth trust boundary (XFF/XFH honored only from trusted proxy; direct/spoofed requests use socket identity) + adversarial tests 2026-10-03 23:25:23 -07:00
Hermes 1e606bf0f3 P7 r3 fix: single-preview contract (syncAccess delegates drift-check+preview+push to pushIfNoDrift; acl_preview_failed mapped non-retryable) + test updates 2026-10-03 22:55:22 -07:00
Hermes d2d0d73477 P7 r2 fixes: drift guard wired through pushIfNoDrift (acl_drift_detected ProviderError, never overwrites drifted remote) + unknown-device forward_auth audit + drift regression tests 2026-10-03 22:47:27 -07:00
Hermes a5ef5b345e merge dc/DC-153 into p7-wave1 2026-10-03 22:34:32 -07:00
Hermes 44567031eb DC-153: provider.syncAccess enforcement wiring (tailscale ACL push + wireguard nftables apply) + contract tests 2026-10-03 22:34:02 -07:00
Hermes aac2343df3 DC-154: forward_auth enforcement endpoint (whois + access map + sensitive step-up) + tests 2026-10-03 22:30:23 -07:00
Hermes 88f7600693 P7: mount public WG invite redemption route (lazy provider, 503 when not wireguard) 2026-10-03 22:08:52 -07:00
Hermes 2f14936970 merge dc/mount (network router mounts) into p7-wave1 2026-10-03 22:08:44 -07:00
Hermes 5bcf4e99ee merge dc/DC-150 into p7-wave1 2026-10-03 22:05:39 -07:00
Hermes a443f030c0 P7 integration: mount network routers (people/access/invites/lifecycle/groups/resources/wizard) with shared stores + lazy lifecycle proxy 2026-10-03 21:52:14 -07:00
Hermes ae78e2e318 merge dc/DC-152 into p7-wave1 2026-10-03 21:49:08 -07:00
Hermes 178a2fbb9f merge dc/DC-147 into p7-wave1 2026-10-03 21:48:27 -07:00
Hermes 38af7ba224 DC-152: Private Network setup wizard (mode/domain/connect/dns/ca/admin steps) + status API + tests 2026-10-03 21:47:34 -07:00
Hermes c12bff597b merge dc/DC-146 into p7-wave1 2026-10-03 21:47:32 -07:00
Hermes d224a24566 DC-147: named root CA with critical name constraints, leaf compliance assertions, install-page hardening, encrypted backup + tests 2026-10-03 21:43:11 -07:00
Hermes b4e683a7fc DC-150: WG invite redemption page (browser X25519 keygen, client-side config+QR) + public redeem API + tests 2026-10-03 21:40:09 -07:00
Hermes 9215037553 DC-146: Technitium zone/record sync (idempotent upserts) + split-DNS gate + setup check + tests 2026-10-03 21:39:33 -07:00
Hermes de6a2fa4ae merge dc/DC-144 into p7-wave1 2026-10-03 21:38:34 -07:00
Hermes 3291f80d0c merge dc/DC-151 into p7-wave1 2026-10-03 21:37:39 -07:00
Hermes 695794987b DC-144: DashCaddy-side groups + resources model/routes with cascade delete + tests 2026-10-03 21:37:13 -07:00
Hermes 24ec88a30d DC-151: WG nftables matrix compiler + transactional apply/rollback + tests 2026-10-03 21:35:15 -07:00
Hermes f7c5ff1d0b merge dc/DC-142 into p7-wave1 2026-10-03 21:34:22 -07:00
Hermes 151b42e0ea merge dc/DC-149 into p7-wave1 2026-10-03 21:33:37 -07:00
Hermes b7d9e2b983 merge dc/DC-143 into p7-wave1 2026-10-03 21:32:45 -07:00
Hermes 88d34c6d7e DC-142: link-first invites routes via network provider + tests 2026-10-03 21:31:57 -07:00
Hermes fcfe5dff1b DC-149: WireGuard hub provider (peer store, pool allocator, hub lifecycle) + tests 2026-10-03 21:31:09 -07:00
Hermes 4e4306b00f DC-143: block/unblock/remove person + revoke device orchestration + tests 2026-10-03 21:29:41 -07:00
Hermes 486d0e8d11 DC-148: Tailscale ACL compiler + lockout guard + preview/push/rollback + drift detection + tests 2026-10-03 21:26:29 -07:00
Hermes a78d0ef857 Merge branch 'dc/DC-145' into dc/DC-142 2026-10-03 21:23:43 -07:00
Hermes b2c70a0323 Merge branch 'dc/DC-141' into dc/DC-142 2026-10-03 21:23:42 -07:00
Hermes c09fc7b1ef Merge branch 'dc/DC-145' into dc/DC-143 2026-10-03 21:23:14 -07:00
Hermes 5d786afcce Merge branch 'dc/DC-141' into dc/DC-143 2026-10-03 21:23:14 -07:00
Hermes 26f4aa8ad0 merge dc/DC-145 into p7-wave1 2026-10-03 21:20:41 -07:00
Hermes d3c1dfd996 merge dc/DC-141 into p7-wave1 2026-10-03 21:20:40 -07:00
Hermes b7df8f5fe0 Merge branch 'dc/DC-140' into dc/DC-148 2026-10-03 21:20:01 -07:00
Hermes 5e03f120b4 Merge branch 'dc/DC-141' into dc/DC-148 2026-10-03 21:20:00 -07:00
Hermes 7ef3914730 DC-140: network provider abstraction (src/network/) + tailscale provider + registry + tests 2026-10-03 21:16:20 -07:00