bridge-index-kickoff-response.mjs
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠ breaking
1 day ago
| 1 | /** |
| 2 | * Validate that an HTTP response from the `bridge-index-background` Netlify |
| 3 | * Function actually came back with the only status it can legitimately produce |
| 4 | * on a successful kickoff: 202. |
| 5 | * |
| 6 | * Why this exists (May 2026 hotfix): the catch-all redirect in |
| 7 | * `deploy/bridge/netlify.toml` (`from = "/*" force = true`) was intercepting |
| 8 | * `/.netlify/functions/bridge-index-background` requests because Netlify's |
| 9 | * normal exemption for `/.netlify/...` paths is BYPASSED when `force = true`. |
| 10 | * The redirect rewrote the URL to the regular `bridge` function, which had no |
| 11 | * matching Express route and returned 404. `await fetch(url)` resolves |
| 12 | * successfully on a 404 (since 404 is a valid HTTP response, not a network |
| 13 | * error), so the kickoff caller silently believed the background job started |
| 14 | * and returned `202 status:"background"` to the browser. The actual indexing |
| 15 | * never ran. The job lock then sat for its full 16-min TTL blocking any retry. |
| 16 | * |
| 17 | * This helper is deliberately a tiny pure function so it stays trivially |
| 18 | * unit-testable without spinning up Express, Netlify, or fetch mocks. |
| 19 | * |
| 20 | * @param {{ status?: number } | null | undefined} response - The fetch Response |
| 21 | * (or compatible shape with a numeric `status`). |
| 22 | * @param {string | null | undefined} body - The response body text (already |
| 23 | * read by the caller via `response.text()`). Used only for diagnostic logs. |
| 24 | * @throws {Error} when `response` is missing/malformed or `response.status !== 202`. |
| 25 | */ |
| 26 | export function assertBackgroundKickoffOk(response, body) { |
| 27 | if (!response || typeof response.status !== 'number') { |
| 28 | throw new Error( |
| 29 | 'background kickoff: invalid response from /.netlify/functions/bridge-index-background', |
| 30 | ); |
| 31 | } |
| 32 | if (response.status !== 202) { |
| 33 | const snippet = typeof body === 'string' ? body.slice(0, KICKOFF_BODY_SNIPPET_MAX) : ''; |
| 34 | const tail = snippet ? ` — body: ${snippet}` : ''; |
| 35 | throw new Error( |
| 36 | `background kickoff: expected HTTP 202 from /.netlify/functions/bridge-index-background, got HTTP ${response.status}${tail}`, |
| 37 | ); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Cap the diagnostic body snippet length to keep Lambda log lines bounded |
| 43 | * (Netlify charges by GB-seconds and CloudWatch enforces a 256 KB/event cap). |
| 44 | * 500 chars is enough to identify any reasonable error response without |
| 45 | * dumping multi-KB HTML error pages. |
| 46 | */ |
| 47 | export const KICKOFF_BODY_SNIPPET_MAX = 500; |
File History
2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠
1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6
docs: accept Calendar Events v0 spec with Phase 0 security …
Human
1 day ago