Skip to content

fix(connectors): derive the connect-code shape beside the minter (TASK-159) - #1937

Merged
lilyshen0722 merged 1 commit into
mainfrom
kai/task159-connect-code-shape
Sep 27, 2026
Merged

lilyshen0722 merged 1 commit into
mainfrom
kai/task159-connect-code-shape

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

Ties the Telegram route's connect-code shape to the minter, so the two cannot answer the shape question differently. Row TASK-159, moved out of TASK-156 by wren (its build, #1935, never touches the enable path).

The failure path the row names

backend/routes/webhooks/telegram.ts:40 carried its own CONNECT_CODE_SHAPE = /^[0-9a-f]{32}$/, linked to mintConnectCode (backend/services/telegramConnectCode.ts:17, crypto.randomBytes(16).toString('hex')) by a comment and nothing else.

  1. Widen the minter to randomBytes(20). The seven pins on minted output go red.
  2. Update those pins to {40}. The suite is green again.
  3. Every real code is now refused with "That doesn't look like a connect code" — and no test catches it, because every webhook fixture is a 32-hex literal.

The change

  • CONNECT_CODE_BYTES = 16 is the one number. The minter draws from it (crypto.randomBytes(CONNECT_CODE_BYTES)) and the predicate is built from it (new RegExp(\^[0-9a-f]{${CONNECT_CODE_BYTES * 2}}$`)`), so neither side can move without the other. This is wren's shape from 74639 rather than the row's two-constant version, per vera's 74633 ruling on the tension between the row's mutation and the better implementation.
  • isConnectCodeShape is exported beside mintConnectCode and added to module.exports; the route calls it and its local regex — plus the comment that tied the two together — is gone.
  • The predicate's comment says what a second answer costs, so the next person reaching for a local regex sees the failure it invites.

Witnesses

claim witness
the predicate accepts what the minter produces, and refuses one character either side telegramConnectCode.test.js (width derived from the same call, not a literal)
it refuses non-hex and uppercase — the caller lowercases first (vera 74615) telegramConnectCode.test.js
the code's width comes from CONNECT_CODE_BYTES telegramConnectCode.test.js
the route ASKS the service for the shape telegram.webhook.connectCode.test.js, asserting isConnectCodeShape was called with the normalised JOINED_CODE
a malformed code still spends no attempt and is refused with the shape copy the existing route-tier it.each, four inputs (the negative half of the pair)

The route-side witness is wren's 74639 point: the row's witness as written proves only that the service is self-consistent, while re-adding a local regex to the route tomorrow keeps every suite green. The service mock in that suite already spreads jest.requireActual, so wrapping isConnectCodeShape with a recording jest.fn is additive — it reddens on a local copy and changes nothing else.

Ledger — 5 mutations, baseline and restore 24/24

mutation red
the minter widens to 20 bytes, the predicate derives with it 12 — every route fixture is a 32-hex literal, so the derived predicate stops matching them (non-surgical by construction; disclosed)
the route answers the shape question itself again 1 — the new route witness, alone
the predicate accepts everything 6 — 2 service arms + the 4 route malformed arms (the positive/negative pair)
the predicate stops deriving and hardcodes {32} 0 — SURVIVOR, exit 0. See below.
the drift itself: minter widens AND the predicate hardcodes {32} 2 — including accepts what the minter produces…

Two disclosures rather than tidying:

  • M4 is a survivor and is kept as a tripwire. At the current width {32} and {CONNECT_CODE_BYTES * 2} are the same regex, so hardcoding the width is behaviourally invisible — the derivation is a property of the pair, not of either half. M5 is the row's mutation implemented as the drift actually happens (minter widened, predicate stale) and it reddens the derived witness, which is what the row's one-edit mutation could not do.
  • M1 is non-surgical for the same reason in reverse: derived from the constant, the predicate moves with the minter, so all twelve 32-hex fixtures stop matching. That is the expected blast radius of a width change, not a defect in the fix — the point is that the predicate can no longer disagree with the minter, and the fixtures noticing is the tripwire working.

Scope

  • No behaviour change at the current width: {16 * 2} is {32}. Two files of source, two suites of tests.
  • The seven pins on minted output (telegramConnectCode.test.js:14, integrations.linkedUserId.test.js:381, installableInstallationService.test.js ×5) are untouched: they are 32-hex literals and stay correct, and under this change they are what reddens if the width ever moves.
  • Verified: 5 suites / 126 tests green (the two changed suites plus telegram.webhook.test.js, installableInstallationService.test.js, integrations.linkedUserId.test.js). .ts lint 0 errors; the four max-len warnings in the route file are pre-existing at the same lines minus two (measured against HEAD~1 via --stdin). No diagnostic on any added .js line.

Gate: Vera.

…K-159)

The route carried its own `CONNECT_CODE_SHAPE = /^[0-9a-f]{32}$/`, tied to
`mintConnectCode` by a comment only. Widen the minter, update the seven pins on
minted output, and every real code is refused with the shape message while the
suite stays green — no fixture is a minted code.

- `CONNECT_CODE_BYTES = 16` is now the one number: the minter draws from it and
  the predicate is built from it (`{CONNECT_CODE_BYTES * 2}`), so neither can be
  changed without the other.
- `isConnectCodeShape` is exported beside `mintConnectCode`; the route calls it
  and its local regex (and the comment that tied them) is gone.
- Witnesses: the predicate accepts what the minter produces and refuses one
  character either side, refusing non-hex and uppercase (the caller lowercases
  first); the route asserts it ASKED the service for the shape, so re-adding a
  local copy reddens instead of drifting; the existing route-tier `it.each` of
  four malformed inputs stays the negative side.
@lilyshen0722
lilyshen0722 added this pull request to the merge queue Sep 27, 2026
Merged via the queue into main with commit 1defa90 Sep 27, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant