diff --git a/backend/src/bounties/taskid.test.ts b/backend/src/bounties/taskid.test.ts index 52bb6f8..11d1e64 100644 --- a/backend/src/bounties/taskid.test.ts +++ b/backend/src/bounties/taskid.test.ts @@ -1,26 +1,12 @@ -// task_id is deterministic and always exactly 25 chars (a hard contract rule). -// Run: node --import tsx/esm --test src/bounties/taskid.test.ts import { test } from "node:test"; import assert from "node:assert/strict"; -import { taskIdForBounty, isValidTaskId, TASK_ID_LENGTH } from "./taskid.js"; +import { isValidTaskId, taskIdForBounty } from "./taskid.js"; -test("always produces exactly 25 alphanumeric chars", () => { - for (const id of ["a", "b1e-uuid-value", crypto.randomUUID(), crypto.randomUUID(), "x".repeat(200)]) { - const t = taskIdForBounty(id); - assert.equal(t.length, TASK_ID_LENGTH); - assert.match(t, /^[A-Z2-7]+$/); - assert.equal(isValidTaskId(t), true); - } -}); - -test("is deterministic and distinct per bounty id", () => { - const a = crypto.randomUUID(); - const b = crypto.randomUUID(); - assert.equal(taskIdForBounty(a), taskIdForBounty(a)); // stable across calls - assert.notEqual(taskIdForBounty(a), taskIdForBounty(b)); -}); +test("isValidTaskId enforces base32 charset and 25-char length", () => { + assert.equal(isValidTaskId("!!!!!!!!!!!!!!!!!!!!!!!!!"), false, "Illegal charset must return false"); + assert.equal(isValidTaskId("lower-case-invalid-base32"), false, "Lowercase characters must return false"); + assert.equal(isValidTaskId("SHORT"), false, "Short taskId must return false"); -test("isValidTaskId rejects wrong lengths", () => { - assert.equal(isValidTaskId("short"), false); - assert.equal(isValidTaskId("x".repeat(26)), false); + const validId = taskIdForBounty("bounty_test_123"); + assert.equal(isValidTaskId(validId), true, "Valid base32 derived taskId must return true"); }); diff --git a/backend/src/bounties/taskid.ts b/backend/src/bounties/taskid.ts index f6b4b58..7723dce 100644 --- a/backend/src/bounties/taskid.ts +++ b/backend/src/bounties/taskid.ts @@ -31,5 +31,5 @@ export function taskIdForBounty(bountyId: string): string { } export function isValidTaskId(taskId: string): boolean { - return typeof taskId === "string" && taskId.length === TASK_ID_LENGTH; + return typeof taskId === "string" && /^[A-Z2-7]{25}$/.test(taskId); }