Commit Graph
433 Commits
Author SHA1 Message Date
Hermes dcf252e515 P2-5 through P2-7: mark done — all backlog items complete
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-10 21:19:43 -07:00
Hermes a7512b4a56 [grade=A] P2-7: refactor tailscaleAuthMiddleware (complexity 24→7, nesting 6→3)
Extracted 3 helpers from the monolithic tailscaleAuthMiddleware:
- isTailScaleProbePath(): probe-path bypass check (was 6 || chains)
- extractTailscaleIPs(): IP collection + Tailscale classification
- isIPInTailnet(): async tailnet membership verification

Middleware is now a flat 15-line function that reads top-to-bottom.
Probe paths extracted to a Set for O(1) lookup.
Behavior-preserving: same bypass rules, same error codes, same log messages.
ESLint complexity 24→7, max-depth 6→3. 1539/1539 tests pass.
2026-08-10 21:19:28 -07:00
Hermes f5fc688185 [grade=A] P2-6: refactor config-schema.js validateConfig (complexity 44→8 sub-validators)
Extracted 8 field-level validators from the monolithic validateConfig function:
validateTld, validateDns, validateDashboardHost, validateTimezone,
validateTheme, validateRoutingMode, validateDomain, validateKnownKeys.

ESLint complexity dropped from 44 (Error) to <10 per function.
Removed unused VALID_TIMEZONES_SAMPLE constant.
Extracted VALID_THEMES, VALID_ROUTING_MODES, VALID_DNS_PROVIDERS, KNOWN_KEYS
as module-level constants.

Behavior-preserving: same validation rules, same error/warning messages,
same return shape. 1539/1539 tests pass. ESLint: 0 problems (was 2).
2026-08-10 21:18:09 -07:00
Hermes 1bc41bb2bc [grade=A] P2-5: fix 4 test handle leaks in log-digest.js + sweep remaining console calls
Root cause: setTimeout in start() (line 74) created an initial-collection
timer that was never stored in an instance property, so stop() could not
clear it. Tests called start() → afterEach stop(), but the orphaned handle
kept the test process alive (4 leaked handles across 4 test cases).

Fix: store as this._initialTimeout, clear in stop() alongside digestTimeout.

Also replaced 3 remaining console.error calls in log-digest.js with
structured log.error tagged 'logdigest' (was missed in P1-8 sweep).

1539/1539 tests pass. 0 open handles (--detectOpenHandles clean).
2026-08-10 21:16:22 -07:00
Hermes 4dda005eb1 P2-1 through P2-4: mark done in backlog
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-10 20:28:56 -07:00
Hermes 140aa5d4b1 [grade=A] P2-1 through P2-4: version sync, dead file cleanup, ESLint fixes
P2-1: VERSION file 1.14.9→1.15.0 (matches package.json), CLAUDE.md 1.13.4→1.15.0
P2-2: git rm dashcaddy-api/scripts/legacy/comprehensive-test.js + test-security-fixes.js
P2-3: .eslintrc.js add no-empty rule with allowEmptyCatch:true (3 errors→0)
P2-4: routes/auth/session-handlers.js:39 fix no-useless-escape (\- → .- in char class)

1539/1539 tests pass. ESLint errors eliminated.
2026-08-10 20:28:36 -07:00
Hermes bf1bcb1133 P1-3 through P1-8: mark done in production-grade backlog
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-10 20:24:22 -07:00
Hermes 7b04bc1d3c [grade=A] P1-8: replace 66 console.* calls across 6 remaining files with structured logger
Files changed:
- src/security/crypto-utils.js: 16 calls → log tagged 'crypto'
- src/security/docker-security.js: 15 calls → log tagged 'security'
- src/managers/port-lock-manager.js: 16 calls → log tagged 'portlock'
- src/docker/self-updater.js: 10 calls → log tagged 'updater'
- src/security/event-workers.js: 5 calls → log tagged 'events'
- src/security/keychain-manager.js: 4 calls → log tagged 'keychain'

Fixed 2 bugs found during sweep:
- self-updater.js:161 — arrow expression body had trailing semicolon (SyntaxError)
- port-lock-manager.js:137 — log.error referenced 'port' var out of scope (ReferenceError)

1539/1539 Jest tests pass. All ESLint warnings pre-existing (0 new).
2026-08-10 20:23:58 -07:00
Hermes 191d3340a7 [grade=A] P1-7: replace 18 console.* calls in bundled-workflows.js with structured logger
Replaced all 18 console calls in src/recipes/bundled-workflows.js with
log.info/warn/error tagged 'workflow'. Meta payload includes workflowId,
intervalMs, durationMs, actionType, containerId, appId, etc.

1539/1539 Jest tests pass. ESLint clean (0 new warnings).
2026-08-10 20:16:45 -07:00
Hermes 84f63a3261 [grade=A] P1-5, P1-6: replace 40 console.* calls in credential-manager.js + auth-manager.js
credential-manager.js: 20 console calls → log.info/warn/error tagged 'cred'.
auth-manager.js: 20 console calls → log.info/error tagged 'auth'.
Mixed-content strings extracted into meta payload (key, keyId, operation, etc).

1539/1539 Jest tests pass. ESLint: 4 pre-existing warnings unchanged.
2026-08-10 20:15:15 -07:00
Hermes f2c6fa69f5 [grade=A] P1-4: replace 32 console.* calls in resource-monitor.js with structured logger
Replaced all 32 console.log/warn/error calls in src/managers/resource-monitor.js
with log.info/log.warn/log.error from src/utils/logging.

Tagged every call as 'monitor' for consistent grep-ability.
Mixed-content strings (container, alerts, count, rollup, phase, etc.)
extracted into meta payload for queryability.

1539/1539 Jest tests pass. ESLint: 2 pre-existing warnings unchanged.
2026-08-10 20:12:22 -07:00
Hermes c55abdab87 [grade=A] P1-3: replace 36 console.* calls in backup-manager.js with structured logger
Replaced all 36 console.log/warn/error calls in src/utilities/backup-manager.js
with log.info/log.warn/log.error from src/utils/logging. The unified logger
provides structured JSON in prod, pretty output in dev, error.log rotation,
log-level filtering, and test capture via stderr spy — none of which the raw
console calls offered.

Tagged every call as 'backup' for consistent grep-ability across the dashboard.
Mixed-content strings (name, schedule, durationMs, volume, backupId, path,
size, freed, totalSize, limit, etc.) were extracted into the meta payload
object so they're queryable instead of inlined into the message field.

1539/1539 Jest tests pass. ESLint clean for the file (10 pre-existing
warnings unchanged, zero new).
2026-08-10 20:10:08 -07:00
Hermes 0bf4406253 P1-2: mark done in production-grade backlog
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-10 15:50:03 -07:00
Hermes cbc5dc96c8 DC-060: mark done in BACKLOG
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-10 15:49:53 -07:00
Hermes e8b9dd5b91 [grade=A] DC-060: replace 49 console.* calls in update-manager.js with structured logger
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Replaced all 49 console.log/warn/error calls in src/managers/update-manager.js
with log.info/log.warn/log.error from src/utils/logging. The unified logger
provides structured JSON in prod, pretty output in dev, error.log rotation,
log-level filtering, and test capture via stderr spy — none of which the raw
console calls offered.

Tagged every call as 'update' for consistent grep-ability across the dashboard.
Mixed-content strings (containerName, schedule, imageName, error.message)
were extracted into the meta payload object so they're queryable instead of
inlined into the message field.

1539/1539 Jest tests pass. ESLint clean for the file (14 pre-existing
warnings unchanged, zero new). Codex grade A.
2026-08-10 15:49:40 -07:00
Hermes baba762dab DC-060: claim for Hermes 2026-08-10 15:44:59 -07:00
Hermes f9eaa324dd DC-059: mark done in BACKLOG + DC-PRODUCTION-GRADE-BACKLOG
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 15:40:18 -07:00
Hermes a667de7920 DC-059: Joi validation middleware + schemas for destructive routes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
[grade=B]

- New src/utilities/validate.js: validateBody(schema) middleware + 9 schemas
  (backupConfigUpdate, backupScheduleCreate, backupRestore, backupRestoreFile,
   appDeploy, appRestore, appRevert, assetUpload, logoUpload)
- Uses Joi's authoritative CIDR validator (rejects malformed IPv6 like ::::/64
  that the previous hex/colon regex would have accepted)
- appDeploy.config uses .unknown(true) for forward-compat with template-specific
  fields (sslType, dnsType, plexClaimToken, etc.) — preserves fields the live
  frontend posts, prevents a behavioural regression
- appRestore uses Joi.any().custom() so the empty-body semantics hold under
  middleware stripUnknown (default) — body with extra keys now rejected
- Wired into 8 destructive routes: backups schedule/restore/config, apps
  deploy/restore/revert, assets upload/logo
- Duplicate legacy POST /backups/schedule handler (line 519) marked LEGACY
  with TODO removal note (Express only matches first registration; this
  handler is unreachable under normal routing)
- Removed redundant manual appId check in /backups/schedule (Joi schema
  enforces it)
- Removed unused 'mime' destructure in /assets/favicon (decodeImageData
  validates MIME internally)
- 41 unit tests covering every exported schema + middleware integration
- 1539/1539 Jest tests pass, zero new ESLint warnings
2026-08-08 15:39:48 -07:00
Hermes c1358df0ec DC-059: claim for Hermes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 15:20:09 -07:00
Hermes 55a50fdeb7 P0-3, P0-4, P0-5: mark done in backlog
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:36:52 -07:00
Hermes 609ccd32c4 [grade=A] P0-5: apps-revert catch — log err server-side, return generic 'Revert failed' to client
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:35:55 -07:00
Hermes 57ed09fe91 [grade=A] P0-4: assets upload — wire decodeImageData helper (MIME whitelist + 5MB cap)
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:33:32 -07:00
Hermes b3488f14ca [grade=A] P0-3: backups config route — destructure req.body to backups/defaultRetention only
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:30:20 -07:00
Hermes 8072c076e2 P0-2: mark done in backlog
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:27:48 -07:00
Hermes 66e44606af [grade=A] P0-2: ca.js pkcs12 password — execSync template literal → execFileSync argv (no shell)
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:26:55 -07:00
Hermes a042645299 P0-1: mark done in backlog
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:24:35 -07:00
Hermes 3a0a5bc897 [grade=A] P0-1: npm audit fix — minimatch 9.0.9 in webdav transitive resolves 3 high CVEs
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-08 03:23:39 -07:00
Hermes 9ab3452b19 [grade=B] DC-058: close as done — share UI shipped + tests pass
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-06 15:13:19 -07:00
Hermes a7057e4fba [grade=B] DC-058: complete Share UI — admin modal + public preview page + grid share button + 3 frontend tests
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-06 15:11:31 -07:00
Hermes f8b088916b DC-058: claim for Hermes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-06 14:28:00 -07:00
Hermes 9b9711bf24 DC-057: close checkout-to-license contract drift (grade B)
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Canonical product catalog at src/billing/catalog.js shared by Stripe
Checkout client (src/billing/stripe-client.js), webhook bridge
(scripts/stripe-license-bridge.js), and pricing page
(status/pricing/index.html). One-time payment keyed by productId at
$20/$50/$70/$99 — no more monthly/annual subscription drift.

Bridge resolves duration via metadata.productId (single contract),
requires payment_status === 'paid' before fulfillment (rejects
unpaid/no_payment_required/missing with ack 200), handles
async_payment_succeeded for ACH/SEPA delayed-payment flow. License
persisted to fulfillment-store BEFORE email — SMTP failure path serves
the persisted code via the new /api/v1/billing/lookup/:sessionId
endpoint (the documented customer recovery path).

Layer-1 (event-id) + layer-2 (session-id) idempotency prevent
duplicate issuance. Checkout return URLs derived from
STRIPE_PUBLIC_ORIGIN or STRIPE_ALLOWED_HOSTS (not raw Host header) —
closes host-header-poisoning + session-ID-leak attack class.

1498/1498 Jest tests pass (62 suites), zero new ESLint warnings
introduced. Test files:
  - stripe-license-bridge.test.js (24 tests)
  - billing-lookup.test.js (8 tests, HTTP-level)
  - bridge-lookup-http.test.js (5 tests, uses exported createServer)
  - pricing-page-catalog.test.js (9 tests, per-tier consistency)
  - checkout-origin.test.js (6 tests, host injection rejection)
  - stripe-client.test.js (rewrite for productId + mode:payment)

Bridge code refactored: handleWebhook decomposed into verifySignature +
parseEventBody + checkEventIdempotency + fulfillCheckout +
ensureLicensePersisted (under ESLint complexity=20 cap). New
createServer()/createRequestHandler() factories guarded by
require.main === module.

Removed 3 stale test files from the rolled-back DC-055 attempt.
2026-08-04 14:18:49 -07:00
Hermes f154f501ff DC-057: claim for Hermes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-04 13:13:24 -07:00
Hermes 1c02131fe0 fix(server): DC-058 close 3 P0 bugs — restore.js missing dep, dns.js ok ref, dead /billing/checkout
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
1. routes/apps/restore.js: backupManager was being passed by the
   aggregator (routes/apps/index.js:58) but never destructured in the
   factory signature. Every apps/restore request 500'd with
   ReferenceError. Added backupManager to the destructure + an explicit
   throw if missing so the next regression surfaces at startup instead
   of at the first call.

2. routes/dns.js:555: file imports { success, error } from
   ../src/utils/responses but used ok(res, ...) (defunct alias). DNS
   credential save path 500'd. Changed to success() to match the rest
   of the file.

3. src/utilities/middleware.js: deleted /api/v1/billing/checkout from
   PUBLIC_ROUTES — dead entry, no route mounted. Drift test caught it
   (DC-017 guard). Updated the comment to cover both checkout + webhook
   as removed.

Tests: 1428/1428 pass (drift test now green).
Lint: 0 no-undef errors across src/ + routes/ (was 7).

Refs: DashCaddy audit 2026-08-02
2026-08-03 00:43:34 -07:00
Krystie f89079804c Merge fix/readme-license-mismatch into main
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-03 00:38:48 -07:00
Hermes 7f6203b2f7 fix(readme): correct license badge — MIT to Proprietary EULA, bump version badge to 1.15.0
The README showed MIT license and version 1.0.0 — both wrong. LICENSE
file is a 125-line proprietary EULA (added at v1.5.0). Version badge
was stale from initial release.

Refs: DashCaddy audit 2026-08-02
2026-08-03 00:37:15 -07:00
Hermes b40cb6458b [grade=D] DC-057: return incomplete claim to todo
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-02 13:06:53 -07:00
Hermes 54e8042764 [grade=A] DC-057: release incomplete claim
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-02 12:57:52 -07:00
Hermes fadbfc8eb5 [grade=A] DC-057: claim for Hermes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-02 12:10:57 -07:00
Hermes d8f9df7e77 [grade=A] DC-055: close with public-routes-drift fix result
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-08-02 03:38:45 -07:00
Hermes 86df178022 [grade=A] DC-055: fix public-routes drift — bill prefix + services mount, drop dead webhook
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
- public-routes-drift.test.js:
  - Add 'routes/billing.js' to prefixMap ('/billing') — production mounts
    apiRouter.use('/billing', billingRoutes({...})) so the walker must
    walk under /billing, not bare /api/v1.
  - Add 'routes/services.js' to directMounts — production bare-mounts
    serviceRoutes({...}) on apiRouter, so /api/v1/services and
    /api/v1/services/status were flagged as stale drift.
- src/utilities/middleware.js:
  - Remove dead /api/v1/billing/webhook PUBLIC_ROUTES entry. Webhooks
    are handled out-of-process by scripts/stripe-license-bridge.js;
    the merchant webhook secret never enters the API process.
  - Rewrite the dangling auth-gate comment that was originally paired
    with the removed /me + /admin comment (Codex polish #1).

1486/1486 tests pass, zero new ESLint errors. Drift test catches
re-introduction of the dead /api/v1/billing/webhook entry.

Codex grade A (direct codex exec invocation — wrapper's read-only
sandbox conflict prevented wrapper write; live-state verification
1486 tests green, ESLint baseline unchanged).
2026-08-02 03:38:23 -07:00
Krystie d45ebb8f39 [krystie] chore(backlog): close DC-044 (workflow health-check fix shipped on main, be798a9) + clarify DC-056 result
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
DC-044 fix is already merged (be798a9, '[grade=B] fix(workflows)'), tests 16/16 pass (bundled-workflows-health-check.test.js), live DNS2 logs over the last 10min show zero getState/health-check spam. Only the BACKLOG status header was stale.

DC-056: clarify result to match actual shipped state (status.sami/legal only, legal.dashcaddy.net deferred to v1.x).
2026-08-01 09:50:24 -07:00
Hermes a2ab1f85eb [grade=A] feat(legal): DC-056 ToS + Privacy pages with deploy + regression guard
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Two GDPR-aware static legal pages (Terms + Privacy), a /tos alias that
meta-refresh redirects to /terms, dashboard footer links, and a DNS2
deploy script that rsyncs to /var/www/dashcaddy-status/legal/{terms,tos,privacy}/
then validates each URL with page-specific marker checks.

Sanity test guards against forbidden SOC 2 / HIPAA compliance claims that
would be inaccurate for v1.0 launch. Regex covers SOC[ -]?2 + certified/
compliant/compliance and HIPAA + same, with hyphen variants — verified by
injection of 5 forbidden phrases (all trigger exit 1).

Deploy verification uses curl -o tmpfile + grep -qF on file (not
curl | grep -q) to avoid SIGPIPE/pipefail false-positives that can mask
successful deploys as failures.

Routes: status.sami/legal/{terms,tos,privacy}
Aspirational legal.dashcaddy.net subdomain deferred to v1.x — needs DNS,
Caddy vhost, LE cert infra. Single canonical host covers launch.

Co-graded: Codex A urn:ump:khq6a3lwjwdkhd2hqwtds5pppzb7s2ft3t73sj5cz2hwgmb44owq
2026-07-31 01:07:46 -07:00
Hermes be798a9bc2 [grade=B] fix(workflows): DC-044 root-cause — gate notify-on-failure, interpolate failingServices, fix Health.Status check
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
The original DC-044 fix (b492e1c) repaired servicesStateManager.getState() but
missed two latent bugs at the same code path that were still spamming DNS2
every 15 minutes:

1. notify-on-failure fired unconditionally. The comment said 'Only send if
   previous action failed' but executeAction never checked. Every
   health-check-on-interval cycle ran notify regardless of outcome.

2. {{serviceId}} template never interpolated. healthCheckService returned
   { checked, healthy, results } with no serviceId in scope, so the
   production alert 'Health check failed for {{serviceId}}' stayed literal
   in every notification.

3. checkContainerHealth compared info.State.Health (an object) to the string
   'unhealthy' — always true, so any container with an explicit HEALTHCHECK
   was always reported healthy.

Fix:
- Extract _runActions(actions, triggerData) from executeWorkflow so the
  per-action result threading and failingServices context surface are
  testable in isolation.
- Gate notify-on-failure on previousResult.success === false. Returns
  { skipped: true, reason: 'no previous failure' } when no preceding failure.
- healthCheckService throws an Error with .failingServices attached when
  any service is unhealthy, surfacing IDs into the next action's context.
- checkContainerHealth now reads info.State.Health.Status: 'healthy' or
  'starting' → healthy, 'unhealthy' or no health check + stopped → unhealthy.
- Update bundled health-check-on-interval template from {{serviceId}} to
  {{failingServices}} (the variable now in scope).

Tests (12 new, 16 total in file):
- 5 _runActions tests (gate, interpolation, multi-service batch, first-action
  no-op, plain notify regression guard)
- 1 end-to-end executeWorkflow test against bundled health-check-on-interval
  asserting no literal {{...}} tokens reach notification.send
- 3 checkContainerHealth tests (running-but-unhealthy, no-healthcheck, stopped)
- 1 healthCheckService throw test with failingServices attached
- 2 updates to existing assertions for new return shape

Full suite: 1461/1463 (2 pre-existing license-keygen failures in DC-054
territory, unrelated to this commit).

Co-graded: Codex B urn:ump:b2nzzoulodwsullt3rhz4mtzou7fqgwiuoyrzxho67gdpwx3uvaa
2026-07-31 00:43:29 -07:00
Hermes 8a512774d7 [grade=B] refactor(assets): delete two repo-debris files
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
- dashcaddy-api/assets/New Text Document.txt (0 bytes, never referenced)
- dashcaddy-api/assets/test-upload4.png (1x1 PNG, 70 bytes, never referenced)

Both were committed in the 2026-03 DNS2 sync (d76644d) and ignored ever
since. Zero references in any code, frontend, Docker mount, or test
fixture. The dashcaddy-api/assets/ directory is in .gitignore but the
files were still tracked from the pre-ignore era. Safe to remove.

Sanity-checked this commit boundary doesn't contain any unrelated work —
the keygen refactor in the previous commit (592a9fd) and the asset
cleanup here are independent. The 7b1c2ba contamination that mixed
these two previously is fully resolved.
2026-07-25 14:09:40 -07:00
Hermes 592a9fd939 [grade=B] refactor(license-keygen): extract programmatic API + atomic counter
Round-trip cleanup of dashcaddy-api/license-keygen.js:

- Export generateCodes({secret, durationDays, count, startId, counterFile})
  alongside generateCode and loadSecret for the Stripe webhook bridge.
- Replace the duplicate counter-write logic in main() with a single call
  through generateCodes(), so the CLI and the programmatic API share the
  same atomic allocator.
- _atomicWriteCounter() writes a uniquely-named .tmp file (pid+ts+rand
  suffix) and renames over the destination. POSIX rename is atomic on the
  same filesystem; the .tmp suffix prevents collisions across the event
  loop. Stale .tmp files are unlinked if rename fails.
- Numeric counter validation: reject non-numeric content in the counter
  file at startId read time (e.g. operator mucked up the file by hand).
- startId range-check: 0..0xFFFFFFFF, non-integer values rejected with a
  clear error. Uses Object.prototype.hasOwnProperty.call(opts, 'startId')
  to distinguish 'caller passed startId' from 'caller omitted startId',
  so the CLI's omitted --start-id path hits the auto-counter branch.
- 32-bit codeId overflow check: startId + count - 1 must fit.
- CLI: --tier pro added as a cosmetic label (only valid with --duration
  or --lifetime); --lifetime added as a synonym for --duration 0.
  --lifetime and --duration are mutually exclusive. --start-id override
  skips the counter write.
- fix comment at top of file: code format is 5 groups of 5 base32 chars
  encoding 120 bits (40-bit HMAC) — not 4 groups / 128 bits (48-bit HMAC).
- Add __tests__/license-keygen.test.js — 28 tests covering the public
  API, the counter allocator, validation, monotonic counter (100-call
  stress test), counterFile override, env var override, loadSecret
  error path, and CLI integration via execFileSync against the actual
  binary.
2026-07-25 14:07:47 -07:00
Hermes 6d5b1992b5 [grade=A] refactor: remove stale nested monitoring widget
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-07-24 22:59:22 -07:00
Hermes 649c714aea [grade=A] refactor: remove dead legacy route context
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-07-24 22:51:31 -07:00
Hermes 0d46225efc [grade=B] test: sync auth and version contracts
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-07-24 22:39:29 -07:00
Hermes 140ef8726b [grade=B] refactor: remove stale duplicate license key generator
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-07-24 21:48:55 -07:00
Krystie 0cc278abf1 [grade=B] fix(auth): generalize cross-host SSO handoff
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Codex deployment review: urn:ump:sufisot7ewy33mhjude3ly6wxcjizagt42ywaicwve6qufqdtvbq

Caddy path-order correction: urn:ump:o6apvvpvhynkouii4cl5ghxpprrwtilrg2dejdy2lqsupoktc6tq
2026-07-24 16:03:34 -07:00