diff --git a/src/lock-ops.mjs b/src/lock-ops.mjs index 65a944e..405e483 100644 --- a/src/lock-ops.mjs +++ b/src/lock-ops.mjs @@ -60,6 +60,7 @@ function filterActiveLocks(locks) { return locks.filter((lock) => !lock.expiresAt || lock.expiresAt > now); } + /** * Queries relays for active lock events matching the criteria. * Uses a tiered approach: tries primary relays first, then falls back to others if needed. diff --git a/src/lock-publisher.mjs b/src/lock-publisher.mjs index a17d501..d706fde 100644 --- a/src/lock-publisher.mjs +++ b/src/lock-publisher.mjs @@ -6,19 +6,9 @@ import { getRelayFallbacks, getMinActiveRelayPool, } from './torch-config.mjs'; -import { randomInt } from 'node:crypto'; +import { mergeRelayList, relayListLabel } from './utils.mjs'; import { defaultHealthManager, buildRelayHealthConfig } from './relay-health-manager.mjs'; -import { relayListLabel, mergeRelayList } from './utils.mjs'; - -function withTimeout(promise, timeoutMs, timeoutMessage) { - let timeoutHandle; - const timeoutPromise = new Promise((_, reject) => { - timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs); - }); - return Promise.race([promise, timeoutPromise]).finally(() => { - if (timeoutHandle) clearTimeout(timeoutHandle); - }); -} +import { withTimeout, secureRandom } from './lock-utils.mjs'; const PUBLISH_ERROR_CODES = { TIMEOUT: 'publish_timeout', @@ -111,12 +101,6 @@ function isTransientPublishCategory(category) { ].includes(category); } -const MAX_RANDOM = 281474976710655; // 2**48 - 1 - -export function secureRandom() { - return randomInt(0, MAX_RANDOM) / MAX_RANDOM; -} - function calculateBackoffDelayMs(attemptNumber, baseMs, capMs, randomFn = secureRandom) { const maxDelay = Math.min(capMs, baseMs * (2 ** Math.max(0, attemptNumber - 1))); return Math.floor(randomFn() * maxDelay); diff --git a/src/lock-utils.mjs b/src/lock-utils.mjs index 293d5bb..974cc06 100644 --- a/src/lock-utils.mjs +++ b/src/lock-utils.mjs @@ -3,7 +3,7 @@ import path from 'node:path'; import { randomInt } from 'node:crypto'; import { todayDateStr, getIsoWeekStr } from './utils.mjs'; -export { relayListLabel, withTimeout, mergeRelayList } from './utils.mjs'; +export { relayListLabel, mergeRelayList } from './utils.mjs'; /** * Scans the local log directory to identify agents that have already completed their task @@ -61,10 +61,6 @@ export function withTimeout(promise, timeoutMs, timeoutMessage) { }); } -export function mergeRelayList(primaryRelays, fallbackRelays) { - return [...new Set([...primaryRelays, ...fallbackRelays])]; -} - const MAX_RANDOM = 281474976710655; // 2**48 - 1 export function secureRandom() { diff --git a/test/verify-example-config-security.test.mjs b/test/verify-example-config-security.test.mjs new file mode 100644 index 0000000..fffd5b2 --- /dev/null +++ b/test/verify-example-config-security.test.mjs @@ -0,0 +1,14 @@ +import test from 'node:test'; +import assert from 'node:assert'; +import fs from 'node:fs'; +import path from 'node:path'; + +test('torch-config.example.json Security', () => { + const configPath = path.resolve('torch-config.example.json'); + const content = fs.readFileSync(configPath, 'utf8'); + const config = JSON.parse(content); + + if (config.dashboard) { + assert.strictEqual(config.dashboard.auth, undefined, 'Example config should not contain auth field'); + } +}); diff --git a/torch-config.example.json b/torch-config.example.json index aafd0bf..df7ea44 100644 --- a/torch-config.example.json +++ b/torch-config.example.json @@ -18,8 +18,7 @@ }, "dashboard": { "defaultCadenceView": "daily", - "defaultStatusView": "active", - "auth": "admin:password" + "defaultStatusView": "active" }, "scheduler": { "firstPromptByCadence": {