chore: sync with upstream 2026-08-05 - #95
Conversation
## Summary - normalize current Sentry issue.created custom-integration webhooks separately from legacy event alerts - route normalization using the Sentry-Hook-Resource header while preserving legacy event_alert and metric_alert behavior - emit a structured sentry.webhook_skipped warning with safe diagnostic metadata when normalization rejects a signed delivery - add unit and integration coverage proving issue.created deliveries create automation runs and skipped payload contents are not logged ## Root cause The webhook handler acknowledged unsupported payloads with HTTP 200 and skipped=true. Its only issue schema required alert-only data.event and data.triggered_rule fields, so current issue.created deliveries were rejected before SchedulerDO and no invocation, run, or session was created. ## Impact Current Sentry issue.created webhooks now reach SchedulerDO and launch their configured automation. Future normalization skips are visible in Worker logs through the sentry.webhook_skipped event without logging webhook payloads or secrets. ## Validation - shared unit tests: 531 passed - control-plane unit tests: 2,254 passed - focused webhook integration tests: 16 passed - full control-plane integration suite passed - shared and control-plane typechecks passed - ESLint, Prettier, and git diff checks passed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added support for current Sentry `issue.created` webhooks, including issue details and context in automation runs. - Sentry webhook types are now identified using resource headers, supporting issue, event-alert, and metric-alert payloads. - **Bug Fixes** - Invalid, unsupported, or mismatched payloads are safely skipped with clear classifications. - Improved structured logging for skipped and processed webhook events without exposing sensitive payload data. - Preserved compatibility with legacy Sentry event-alert and metric-alert integrations. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary - accept string and numeric identifiers in Sentry metric alert webhooks - normalize both metric alert and alert rule identifiers to strings at the schema boundary - verify trigger, concurrency, and metadata keys use the canonical parsed alert rule identifier ## Context Follow-up to ColeMurray#1264. Sentry's documented metric alert payload represents both `metric_alert.id` and `metric_alert.alert_rule.id` as strings, while the merged schema only accepted numbers. Documentation: https://docs.sentry.io/organization/integrations/integration-platform/webhooks/metric-alerts/ ## Validation - `npm test -w @open-inspect/shared` (39 files, 533 tests) - `npm run typecheck -w @open-inspect/shared` - `npm run build -w @open-inspect/shared` - `npm run test:integration -w @open-inspect/control-plane -- test/integration/webhooks.test.ts` (18 tests) - `npm run typecheck -w @open-inspect/control-plane` - `npm run format:check` - focused ESLint and `git diff --check` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Sentry metric alert handling for identifiers provided as either text or numbers. * Standardized alert rule identifiers to consistent string values in normalized metadata. * **Tests** * Expanded coverage to verify normalization across both supported identifier formats. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…rn group across 1 directory (ColeMurray#1268) Bumps the npm_and_yarn group with 1 update in the / directory: [postcss](https://github.com/postcss/postcss). Updates `postcss` from 8.5.18 to 8.5.23 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/postcss/postcss/releases">postcss's releases</a>.</em></p> <blockquote> <h2>8.5.23</h2> <ul> <li>Do not load source map without <code>opts.from</code> for security reasons.</li> </ul> <h2>8.5.22</h2> <ul> <li>Fixed custom property losing semicolon before a comment (by <a href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li> </ul> <h2>8.5.21</h2> <ul> <li>Fixed childless at-rule losing semicolon before comment (by <a href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li> <li>Fixed docs (by <a href="https://github.com/isker"><code>@isker</code></a>).</li> </ul> <h2>8.5.20</h2> <ul> <li>Fixed missing space if <code>AtRule#params</code> is set after (by <a href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li> <li>Fixed mixing AST error on warnings (by <a href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li> </ul> <h2>8.5.19</h2> <ul> <li>Fixed cleaning <code>before</code> for new nodes inserted to <code>Root</code> (by <a href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's changelog</a>.</em></p> <blockquote> <h2>8.5.23</h2> <ul> <li>Do not load source map without <code>opts.from</code> for security reasons.</li> </ul> <h2>8.5.22</h2> <ul> <li>Fixed custom property losing semicolon before a comment (by <a href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li> </ul> <h2>8.5.21</h2> <ul> <li>Fixed childless at-rule losing semicolon before comment (by <a href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li> <li>Fixed docs (by <a href="https://github.com/isker"><code>@isker</code></a>).</li> </ul> <h2>8.5.20</h2> <ul> <li>Fixed missing space if <code>AtRule#params</code> is set after (by <a href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li> <li>Fixed mixing AST error on warnings (by <a href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li> </ul> <h2>8.5.19</h2> <ul> <li>Fixed cleaning <code>before</code> for new nodes inserted to <code>Root</code> (by <a href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/postcss/postcss/commit/eb9e1fe793740bb3280bdf5bf98147f857f011bd"><code>eb9e1fe</code></a> Release 8.5.23 version</li> <li><a href="https://github.com/postcss/postcss/commit/9d19c78ac91108b3f7d7130e55c6fa806c0efb84"><code>9d19c78</code></a> Update dependencies</li> <li><a href="https://github.com/postcss/postcss/commit/7beca139e70f9075c6b19700fcb00dd8033e5da8"><code>7beca13</code></a> Does no load source map file without opts.from</li> <li><a href="https://github.com/postcss/postcss/commit/decea51421682341401575b3740709fda0e12930"><code>decea51</code></a> Typo</li> <li><a href="https://github.com/postcss/postcss/commit/c18e30d126395d42a0726aa00e03a8f1088985ae"><code>c18e30d</code></a> Update EM banner</li> <li><a href="https://github.com/postcss/postcss/commit/98a39ad73d163a90be924d5126c771262110f1fc"><code>98a39ad</code></a> Update EM banner</li> <li><a href="https://github.com/postcss/postcss/commit/a3e48c492ddec0e4879d513b8b995fee887af352"><code>a3e48c4</code></a> Release 8.5.22 version</li> <li><a href="https://github.com/postcss/postcss/commit/f49d6911795f53b2cfe023bb686bf1144ec30618"><code>f49d691</code></a> Fix custom property losing its semicolon before a comment (<a href="https://redirect.github.com/postcss/postcss/issues/2117">#2117</a>)</li> <li><a href="https://github.com/postcss/postcss/commit/28e0daf8f2fe5ba9e19ea3f8c27c8fe176f9419e"><code>28e0daf</code></a> Release 8.5.21 version</li> <li><a href="https://github.com/postcss/postcss/commit/3d2b4e43e38274f233b5609d09687cadad8215d9"><code>3d2b4e4</code></a> Update dependencies</li> <li>Additional commits viewable in <a href="https://github.com/postcss/postcss/compare/8.5.18...8.5.23">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ColeMurray/background-agents/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…up across 1 directory (ColeMurray#1272) Bumps the npm_and_yarn group with 1 update in the / directory: [hono](https://github.com/honojs/hono). Updates `hono` from 4.12.31 to 4.13.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/honojs/hono/releases">hono's releases</a>.</em></p> <blockquote> <h2>v4.13.0</h2> <p>Hono v4.13.0 is now available!</p> <p>The highlight of this release is performance: a batch of low-level optimizations makes the core request/response path significantly faster — up to 1.25x on common routes in our benchmark. This release also adds first-class support for the HTTP QUERY method, defined in <a href="https://www.rfc-editor.org/rfc/rfc10008.html">RFC 10008</a>, a new Method Not Allowed middleware, and more.</p> <h2>Performance improvements</h2> <p>This release includes a series of small optimizations: skipping unnecessary <code>Headers</code> allocations, replacing regex tests with <code>indexOf</code>, allocating internal state lazily, and more.</p> <p>Here is <a href="https://github.com/honojs/hono/tree/main/benchmarks/fetch"><code>benchmarks/fetch</code></a> comparing v4.12 and v4.13 (<code>ROUNDS=5 ./compare.sh</code>, Bun 1.4.0, Apple Silicon — each measurement runs in a fresh process, and the variant order is reversed every round to avoid warm-up bias):</p> <table> <thead> <tr> <th>Benchmark</th> <th align="right">v4.12</th> <th align="right">v4.13</th> <th align="right">Speedup</th> </tr> </thead> <tbody> <tr> <td><code>ping</code> — <code>GET /</code></td> <td align="right">165.83 ns</td> <td align="right">163.99 ns</td> <td align="right">1.01x</td> </tr> <tr> <td><code>query</code> — <code>GET /id/1?name=bun</code></td> <td align="right">674.40 ns</td> <td align="right">616.99 ns</td> <td align="right"><strong>1.09x</strong></td> </tr> <tr> <td><code>json</code> — <code>GET /user</code></td> <td align="right">528.99 ns</td> <td align="right">422.44 ns</td> <td align="right"><strong>1.25x</strong></td> </tr> <tr> <td><code>body</code> — <code>POST /json</code></td> <td align="right">1.16 µs</td> <td align="right">1.00 µs</td> <td align="right"><strong>1.15x</strong></td> </tr> </tbody> </table> <p>The individual changes:</p> <ul> <li>perf(context): iterate the header record with <code>for..in</code> <a href="https://redirect.github.com/honojs/hono/pull/5118">honojs/hono#5118</a></li> <li>perf(url): replace regex tests with <code>indexOf</code> <a href="https://redirect.github.com/honojs/hono/pull/5121">honojs/hono#5121</a></li> <li>perf(context): skip <code>Headers</code> creation when there are no headers to merge <a href="https://redirect.github.com/honojs/hono/pull/5122">honojs/hono#5122</a></li> <li>perf(urls): refactor <code>tryDecodeURIComponent</code> <a href="https://redirect.github.com/honojs/hono/pull/5158">honojs/hono#5158</a></li> <li>perf(request): allocate <code>#validatedData</code> lazily <a href="https://redirect.github.com/honojs/hono/pull/5175">honojs/hono#5175</a></li> <li>perf(request): probe the body cache without allocating <a href="https://redirect.github.com/honojs/hono/pull/5176">honojs/hono#5176</a></li> </ul> <p>In addition, the RegExpRouter rewrite described below makes route registration plus the first match roughly 20% faster.</p> <p>Thanks <a href="https://github.com/kibertoad"><code>@kibertoad</code></a> for the contributions!</p> <h2>First-class QUERY method support</h2> <p>The QUERY method — a safe, idempotent method that carries a request body — is now a first-class citizen in Hono. You can define QUERY handlers with <code>app.query()</code>:</p> <pre lang="ts"><code>const app = new Hono() <p>app.query('/search', async (c) => {<br /> const conditions = await c.req.json()<br /> return c.json(await search(conditions))<br /> })<br /> </code></pre></p> <p>Thanks <a href="https://github.com/shellhaki"><code>@shellhaki</code></a>!</p> <h2>QUERY support across built-in middleware</h2> <p>The built-in middleware has been updated to handle QUERY requests properly:</p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/honojs/hono/commit/192768fbaf9aa99a45404dc2f171541227c11d20"><code>192768f</code></a> 4.13.0</li> <li><a href="https://github.com/honojs/hono/commit/b0c2d90eb07fefa6c06dc556c97ed8ecffc8b2c0"><code>b0c2d90</code></a> Merge pull request <a href="https://redirect.github.com/honojs/hono/issues/5154">#5154</a> from honojs/next</li> <li><a href="https://github.com/honojs/hono/commit/8f0702827002f0ada02434d908853458c17f862d"><code>8f07028</code></a> fix(compress): set Vary: Accept-Encoding on negotiated responses (<a href="https://redirect.github.com/honojs/hono/issues/5137">#5137</a>)</li> <li><a href="https://github.com/honojs/hono/commit/8a0b18fd9b4d64dd2eb1d7f18e3536fc06cb54b2"><code>8a0b18f</code></a> feat(reg-exp-router): throw UnsupportedPathError during route registration (#...</li> <li><a href="https://github.com/honojs/hono/commit/3feb3551d46de1f633e82253f12cf1117316be93"><code>3feb355</code></a> fix(jsx): allow a function component to return an array (<a href="https://redirect.github.com/honojs/hono/issues/5179">#5179</a>)</li> <li><a href="https://github.com/honojs/hono/commit/5d911d2ab7bcb2adb2e974ddd5b17742fb5a0bca"><code>5d911d2</code></a> feat(utils/headers): add HTTP fields newly registered with IANA (<a href="https://redirect.github.com/honojs/hono/issues/5153">#5153</a>)</li> <li><a href="https://github.com/honojs/hono/commit/30277aee0ddd96b643a4958d6102abe6e54d9a29"><code>30277ae</code></a> feat(jwt,jwk): add a configurable WWW-Authenticate realm (<a href="https://redirect.github.com/honojs/hono/issues/5141">#5141</a>)</li> <li><a href="https://github.com/honojs/hono/commit/1f707c56378a4497bc0a6a44fef5f5a8517fdf6b"><code>1f707c5</code></a> feat(middleware): add method-not-allowed middleware (<a href="https://redirect.github.com/honojs/hono/issues/5132">#5132</a>)</li> <li><a href="https://github.com/honojs/hono/commit/2df0b47659165c6403abda5512ecf21541409a62"><code>2df0b47</code></a> feat(jsx): add React-compatible overloads to useRef (<a href="https://redirect.github.com/honojs/hono/issues/5063">#5063</a>)</li> <li><a href="https://github.com/honojs/hono/commit/3bc96ba915bf8d5b25430c955aec8f7df500ff21"><code>3bc96ba</code></a> feat(cache): add first-class support for QUERY requests (<a href="https://redirect.github.com/honojs/hono/issues/5119">#5119</a>)</li> <li>Additional commits viewable in <a href="https://github.com/honojs/hono/compare/v4.12.31...v4.13.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ColeMurray/background-agents/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary - render every parent `task` tool call through the Task-specific timeline presentation, even when no correlated child events exist - preserve child correlation behavior while leaving missing-correlation child events at the top level - omit the Task activity heading and container when there is no displayable child activity - exclude correlated `step_start` and `step_finish` lifecycle envelopes from displayable Task activity ## Bug The Task details UI introduced in `6860660` was only reached when `buildTimelineItems` found correlated child activity. Completed Tasks without child events, early failures, and historical Tasks missing correlation metadata remained generic tool groups and exposed raw Arguments/Output instead of Instructions/Result disclosures. ## TDD Coverage Focused regression tests were added first and confirmed red with three failures: no Task groups for missing correlation, no Instructions/Result for completed Tasks without children, and no cleaned Result for failed Tasks without children. Coverage now verifies: - completed Tasks with prompt/output and no child events use Instructions/Result rather than Arguments/Output - failed Tasks containing only a `task_error` envelope show the cleaned Result - absent and lifecycle-only child activity does not render an empty Task activity section - uncorrelated child events remain outside Task groups ## Verification - `npm test -w @open-inspect/web -- --run src/components/session-timeline.test.tsx` (17 passed) - `npm test -w @open-inspect/web` (879 passed) - `npm run typecheck -w @open-inspect/web` - `npx eslint "packages/web/src/lib/timeline-items.ts" "packages/web/src/components/task-activity-item.tsx" "packages/web/src/components/session-timeline.test.tsx"` - `npx prettier --check "packages/web/src/lib/timeline-items.ts" "packages/web/src/components/task-activity-item.tsx" "packages/web/src/components/session-timeline.test.tsx"` - `git diff --check origin/main...HEAD` --- *Created with [Open-Inspect](https://open-inspect-prod.vercel.app/session/36598812f19ff6ff3e7d8aab662133b6)* --------- Co-authored-by: waclaude <colemurray.cs+ghwaclaude@gmail.com>
## Summary - persist the session sidebar `All`/`Mine` owner filter in local storage - hydrate the saved preference before enabling session fetching to avoid an incorrect initial request or selection - keep the sidebar in a loading state during preference hydration and degrade safely when storage is unavailable - add coverage for persistence, refresh restoration, invalid values, and unavailable storage ## Testing - `npm test -w @open-inspect/web -- --run src/components/session-sidebar.test.tsx` - `npm test -w @open-inspect/web -- --run src/lib/client-auth-boundary-eslint.test.ts` - `npm run lint -w @open-inspect/web` - `npm run typecheck -w @open-inspect/web` - `git diff --check` The full web suite passed 878/879 tests; the remaining client-auth boundary test exceeded its 5-second timeout under full-suite load and passed when rerun in isolation. --- *Created with [Open-Inspect](https://open-inspect-prod.vercel.app/session/88733b8ca9717598e792a0a6b5367cca)* <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a persistent session creator filter with “All” and “Mine” options. * Restores the selected filter when returning to or refreshing the app. * Safely defaults to showing all sessions when saved preferences are invalid or unavailable. * **Bug Fixes** * Prevented the sidebar from displaying an incorrect filter before preferences finish loading. * Kept session filtering functional when browser storage access fails. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cole Murray <2492022+ColeMurray@users.noreply.github.com>
…oleMurray#1273) ## Summary - On a cache miss, `GET /repos` fetches from the SCM provider, enriches from D1, and writes KV inline with the response. If the caller gives up before that finishes, the Worker is cancelled before the KV write — so the cache stays empty and the next request repeats the same slow path. - The stale-while-revalidate branch can't rescue it, because that path requires an existing entry. Once the KV entry expires (`REPOS_CACHE_KV_TTL_SECONDS`, 1h), a deployment whose repo listing is slower than the caller's timeout gets stuck: every request races the timeout and none ever repopulates the cache, so the repository picker never loads. - The web app makes this reachable by default: `packages/web/src/lib/control-plane-transport.ts` aborts control-plane requests at `CONTROL_PLANE_FETCH_TIMEOUT_MS` (15s) via `AbortSignal.timeout`. - Fix: register the refresh with `waitUntil` so it outlives the response, and reuse `refreshReposCache` for the miss path instead of duplicating the fetch/enrich/write logic in the handler. We hit this on a deployment with ~100 repositories, where the listing plus metadata batch exceeded 15s. Symptom was `GET /repos` repeatedly ending in `canceled` at ~15.0s while every other route stayed sub-200ms, with the KV key absent throughout. ## Notes `refreshReposCache` now returns a small result type so the miss path can distinguish "provider not configured" (500 `SCM provider not configured`) from a fetch failure (500 `Failed to fetch repositories`), preserving the previous responses. It takes an optional timer so the miss path keeps recording the `scm_api` metric; the background path passes nothing and behaves as before. This makes the miss path resilient rather than fast — the first request can still exceed a caller's timeout. It no longer poisons every subsequent one, since the write now lands and the next request is served from cache. ## Test plan - [x] `npm test -w @open-inspect/control-plane` (2255 tests pass) - [x] `npm run typecheck -w @open-inspect/control-plane` - [x] New test in `src/routes/repos.test.ts` asserts the miss path registers the refresh with `waitUntil` and still writes the cache — it fails on `main` (`waitUntil` called 0 times) and passes with this change <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved repository listing reliability when cached data is unavailable. * Repository information now refreshes successfully in the background, including when a connection closes early. * Added clearer handling for refresh failures so users receive more meaningful errors. * Improved timing visibility for source-control requests, supporting better monitoring of repository loading performance. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…eMurray#1275) Bumps the uv group with 2 updates in the /packages/modal-infra directory: [aiohttp](https://github.com/aio-libs/aiohttp) and [cryptography](https://github.com/pyca/cryptography). Updates `aiohttp` from 3.14.1 to 3.14.3 <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst">aiohttp's changelog</a>.</em></p> <blockquote> <h1>3.14.3 (2026-07-22)</h1> <h2>Bug fixes</h2> <ul> <li> <p>Fixed the client dropping only the first <code>Authorization</code>, <code>Cookie</code> and <code>Proxy-Authorization</code> header when a redirect crossed an origin -- by :user:<code>arshsmith1</code>.</p> <p><em>Related issues and pull requests on GitHub:</em> :issue:<code>13180</code>.</p> </li> <li> <p>Fixed error message construction in the C HTTP parser -- by :user:<code>bdraco</code>.</p> <p><em>Related issues and pull requests on GitHub:</em> :issue:<code>13222</code>.</p> </li> </ul> <hr /> <h1>3.14.2 (2026-07-20)</h1> <h2>Bug fixes</h2> <ul> <li> <p>Fixed :py:attr:<code>~aiohttp.web.StreamResponse.last_modified</code> rounding a :class:<code>datetime.datetime</code> with a fractional second down.</p> <p><em>Related issues and pull requests on GitHub:</em> :issue:<code>5303</code>.</p> </li> <li> <p>Fixed resolving <code>localhost</code> on Windows to fall back without <code>AI_ADDRCONFIG</code> when the first lookup fails, so <code>localhost</code> still works without an active network.</p> <p><em>Related issues and pull requests on GitHub:</em> :issue:<code>5357</code>.</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/aio-libs/aiohttp/commit/5e392ce0456f5235a4ee6ad46f0e806df2f15873"><code>5e392ce</code></a> Release v3.14.3 (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/13225">#13225</a>)</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/49f65d54150397892f7bcc4aae887767d51c322d"><code>49f65d5</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/13222">#13222</a>/f4866933 backport][3.14] Build C parser error message from bounded...</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/240099e5216a01b32919dcd8dd5c6c0b1bf83671"><code>240099e</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/13180">#13180</a>/ee53d655 backport][3.14] drop every copy of credential headers on ...</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/d93f30a302f8b930074fe14a2be7b2088ba28111"><code>d93f30a</code></a> Bump version (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/13202">#13202</a>)</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/c1b9212ad3d93c24b5fc66ad0849597166bc816e"><code>c1b9212</code></a> Release v3.14.2 (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/13201">#13201</a>)</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/380d4b55e8df48dfd62f1addfb530426f6bc4106"><code>380d4b5</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/13054">#13054</a>/ed8b040c backport][3.14] escape backslashes in digest auth quoted-...</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/e1e1bee363dfba04a9a75c8801717da2ed5bdcb9"><code>e1e1bee</code></a> Make llhttp method array size dynamic (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/13174">#13174</a>) (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/13196">#13196</a>)</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/aa4cf29b6a5ad6f4d21fa1dd3f69193dc2f5d505"><code>aa4cf29</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/13170">#13170</a>/2b906869 backport][3.14] Fix StreamResponse.last_modified rounding...</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/71b57b40d85a0723c92b0a5a37ebdf518210d2ea"><code>71b57b4</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/13172">#13172</a>/a57747ed backport][3.14] Fix C parser folding fragment into query_...</li> <li><a href="https://github.com/aio-libs/aiohttp/commit/64a03fb620b623e5a5a1b7103c07ae3e536a0d40"><code>64a03fb</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/13169">#13169</a>/1adc0cd7 backport][3.14] Upgrade http:// to https:// in README.rst...</li> <li>Additional commits viewable in <a href="https://github.com/aio-libs/aiohttp/compare/v3.14.1...v3.14.3">compare view</a></li> </ul> </details> <br /> Updates `cryptography` from 48.0.1 to 50.0.0 <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst">cryptography's changelog</a>.</em></p> <blockquote> <p>50.0.0 - 2026-07-31</p> <pre><code> * **SECURITY ISSUE**: :func:`~cryptography.hazmat.primitives.serialization.pkcs7.pkcs7_decrypt_der` and its PEM and S/MIME variants no longer expose distinguishable errors or timing when unwrapping a ``RecipientInfo``'s ``encryptedKey``, which could act as a Bleichenbacher oracle for callers that decrypt untrusted messages. A random key is now substituted on failure, as described in :rfc:`3218`. Credit to **@X1AOxiang** for reporting the issue. **CVE-2026-69247** * Deprecated Diffie-Hellman key exchange over finite fields (FFDH). Everything FFDH is deprecated, including the types in ``cryptography.hazmat.primitives.asymmetric.dh`` and loading FFDH keys or parameters with the key loading APIs. Users should migrate to a more modern key exchange algorithm. * Added ``xof()`` class methods to :class:`~cryptography.hazmat.primitives.hashes.SHAKE128` and :class:`~cryptography.hazmat.primitives.hashes.SHAKE256` for constructing algorithm instances configured for use with :class:`~cryptography.hazmat.primitives.hashes.XOFHash`. * The :mod:`X.509 verification <cryptography.x509.verification>` APIs are now considered stable and are subject to our API stability policy. * Added the :doc:`/cobblestone` recipe, an implementation of the Cobblestone-128 and Cobblestone-256 instantiations of the `C2SP chunked-encryption specification <https://c2sp.org/chunked-encryption>`_ for streaming authenticated encryption of large messages. * Parsing a Signed Certificate Timestamp list now rejects encodings that carry trailing bytes after the list or after an individual SCT, instead of silently ignoring them. * Added support for using :class:`~cryptography.x509.Name` as a field type in the :doc:`/hazmat/asn1/index` module. * Loading a public key or an EC private key now rejects DER where the ``subjectPublicKey`` (or EC ``publicKey``) ``BIT STRING`` declares a non-zero number of unused bits, instead of silently ignoring it. * Parsing a CRL entry's ``InvalidityDate`` extension now rejects a ``GeneralizedTime`` that carries fractional seconds or another non-DER form, matching the strict encoding already required for every other X.509 time field. * :func:`~cryptography.x509.ocsp.load_der_ocsp_request` and :func:`~cryptography.x509.ocsp.load_der_ocsp_response` now reject a request or response whose ``version`` field is not ``v1``, the only version defined by RFC 6960, matching the version validation already performed when loading certificates, CSRs and CRLs. * :class:`~cryptography.hazmat.primitives.hashes.XOFHash` is now supported when building against AWS-LC. * HMAC (and therefore PBKDF2-HMAC) with SHA-3 hashes is now supported when building against AWS-LC. * Diffie-Hellman (:doc:`/hazmat/primitives/asymmetric/dh`) is now supported when building against AWS-LC. </tr></table> </code></pre> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/pyca/cryptography/commit/dcb7050b807b00392fa9fe2eac7cb362fcf355cc"><code>dcb7050</code></a> Prepare for 50.0.0 release (<a href="https://redirect.github.com/pyca/cryptography/issues/15372">#15372</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f"><code>53fccd9</code></a> Don't leak how PKCS#7 encryptedKey decryption failed (<a href="https://redirect.github.com/pyca/cryptography/issues/15369">#15369</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/d472f978470fbefa521b86d98b2ecccbbb4d1dd8"><code>d472f97</code></a> Add <code>from __future__ import annotations</code> to all src/ Python files (<a href="https://redirect.github.com/pyca/cryptography/issues/15371">#15371</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/908773d53829fb1466c6db364b31321c3cd8eb9a"><code>908773d</code></a> Bump downstream dependencies in CI (<a href="https://redirect.github.com/pyca/cryptography/issues/15368">#15368</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/2cc07cc948948211899bcb0cddd1fddf86e95812"><code>2cc07cc</code></a> Bump BoringSSL, OpenSSL, AWS-LC in CI (<a href="https://redirect.github.com/pyca/cryptography/issues/15367">#15367</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/c94ede9f040fa44942f7139772603419000acf66"><code>c94ede9</code></a> chore(deps): bump ruff from 0.16.0 to 0.16.1 (<a href="https://redirect.github.com/pyca/cryptography/issues/15366">#15366</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/67a8308dc9ea4cce6056e0f1438f903c208c3f35"><code>67a8308</code></a> chore(deps): bump virtualenv from 21.7.0 to 21.7.1 (<a href="https://redirect.github.com/pyca/cryptography/issues/15365">#15365</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/95018ffcdbbc510fd92fc872e3a3e80aa6e58596"><code>95018ff</code></a> Release the GIL in one-shot AEAD encrypt/decrypt (<a href="https://redirect.github.com/pyca/cryptography/issues/15361">#15361</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/6954733eaf55a0074abf88f06f7242dfca3a5d02"><code>6954733</code></a> Release the GIL during DH and DSA parameter generation (<a href="https://redirect.github.com/pyca/cryptography/issues/15364">#15364</a>)</li> <li><a href="https://github.com/pyca/cryptography/commit/6893b94c33e948f6240082461424cfb5da2dacc6"><code>6893b94</code></a> Import _serialization instead of serialization in x509/extensions (<a href="https://redirect.github.com/pyca/cryptography/issues/15363">#15363</a>)</li> <li>Additional commits viewable in <a href="https://github.com/pyca/cryptography/compare/48.0.1...50.0.0">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ColeMurray/background-agents/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Terraform Validation Results
Pushed by: @NicolasWalter, Action: |
📝 WalkthroughWalkthroughThe PR updates repository cache refresh handling, adds resource-aware Sentry webhook normalization and logging, persists the session creator filter, refines task activity rendering, expands tests, and updates package dependency constraints. ChangesRepository cache refresh
Sentry webhook normalization
Session sidebar and timeline
Package version updates
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Sentry
participant WebhookHandler
participant normalizeSentryEvent
participant AutomationRuns
Sentry->>WebhookHandler: send signed webhook
WebhookHandler->>normalizeSentryEvent: payload and resource header
normalizeSentryEvent-->>WebhookHandler: normalized event or skip result
WebhookHandler->>AutomationRuns: create run for normalized event
sequenceDiagram
participant SessionSidebar
participant useSidebarSessions
participant LocalStorage
participant SessionAPI
SessionSidebar->>useSidebarSessions: set creator filter
useSidebarSessions->>LocalStorage: persist filter
useSidebarSessions->>SessionAPI: fetch filtered sessions
SessionAPI-->>SessionSidebar: return session list
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Comment |
Terraform Plan ResultsStatus: ✅ Success Show Planterraform_data.cloudflare_custom_domain_gate: Refreshing state... [id=fa456fac-6c14-16e4-a484-3338d1a3718d]
terraform_data.sign_in_provider_gate: Refreshing state... [id=7f4a67d1-6978-0b23-899d-c2a9004643bd]
terraform_data.access_control_gate: Refreshing state... [id=841ab6bc-98a7-018c-1031-ebad4f8b62bc]
local_file.web_app_wrangler_production[0]: Refreshing state... [id=4fd11b54fb693eced4839d030233ab1911f26ea1]
null_resource.github_bot_build[0]: Refreshing state... [id=7294943583288896375]
module.modal_app[0].null_resource.modal_secrets[0]: Refreshing state... [id=8757687985279342629]
data.external.modal_source_hash[0]: Reading...
random_password.image_callback_token_pepper: Refreshing state... [id=none]
null_resource.web_app_cloudflare_build[0]: Refreshing state... [id=7599918834973972838]
null_resource.slack_bot_build[0]: Refreshing state... [id=3517235685678107646]
null_resource.linear_bot_build[0]: Refreshing state... [id=8131685489368025167]
module.session_index_kv.cloudflare_workers_kv_namespace.this: Refreshing state... [id=7f18644fbed34121bbe3a196f373ea93]
cloudflare_r2_bucket.media: Refreshing state... [id=open-inspect-media-primo]
module.linear_kv[0].cloudflare_workers_kv_namespace.this: Refreshing state... [id=d003f1ad81384910a1f48a0a33f18c09]
random_password.service_auth_secret_github_bot: Refreshing state... [id=none]
random_password.service_auth_secret_slack_bot: Refreshing state... [id=none]
random_password.service_auth_secret_web: Refreshing state... [id=none]
cloudflare_queue.image_build_finalization_dlq: Refreshing state... [id=cbbc2d8794c04396a550996e7f0cc129]
module.github_kv[0].cloudflare_workers_kv_namespace.this: Refreshing state... [id=87dbfaa1d9ce4a37a42e04c57c434a72]
cloudflare_queue.image_build_finalization: Refreshing state... [id=1ca823a150c54578a9ad1814325147a3]
null_resource.control_plane_build: Refreshing state... [id=712263983139718104]
cloudflare_queue.slack_completion_delivery_dlq[0]: Refreshing state... [id=06ce03d2663f4aea937b0c0c1c379c17]
cloudflare_d1_database.main: Refreshing state... [id=dba95b03-ace9-47a8-81e9-6e39d8d694c5]
cloudflare_queue.slack_completion_delivery[0]: Refreshing state... [id=56ef0f3e13bd46a3a39f30c79ec547fa]
data.external.modal_source_hash[0]: Read complete after 1s [id=-]
random_password.service_auth_secret_linear_bot: Refreshing state... [id=none]
module.slack_kv[0].cloudflare_workers_kv_namespace.this: Refreshing state... [id=729b357dbb5e4c9d99ec9212cc45766e]
module.modal_app[0].null_resource.modal_deploy: Refreshing state... [id=1192764756692112984]
module.linear_bot_worker[0].cloudflare_worker.this: Refreshing state... [id=33782d80e8ff4af9b30b92870084b674]
module.slack_bot_worker[0].cloudflare_worker.this: Refreshing state... [id=5200e96d69804ea296e1f3a6b39e4243]
null_resource.d1_migrations: Refreshing state... [id=1394827775839141124]
module.slack_bot_worker[0].cloudflare_worker_version.this: Refreshing state... [id=6b9fbaec-16ec-4a30-89ad-cc60fb5348b8]
module.linear_bot_worker[0].cloudflare_worker_version.this: Refreshing state... [id=8cf30ae8-a5dd-4214-ba14-7f922310794b]
module.slack_bot_worker[0].cloudflare_workers_deployment.this: Refreshing state... [id=ee7c9fc3-dff3-48b9-85c4-d4579ba23ca7]
module.linear_bot_worker[0].cloudflare_workers_deployment.this: Refreshing state... [id=9c108f32-d908-4b59-9574-175c0a90ad89]
cloudflare_queue_consumer.slack_completion_delivery[0]: Refreshing state...
module.control_plane_worker.cloudflare_worker.this: Refreshing state... [id=c208a60c393e45e38eb502346bb7ce1e]
module.control_plane_worker.cloudflare_workers_cron_trigger.this[0]: Refreshing state... [id=open-inspect-control-plane-primo]
module.github_bot_worker[0].cloudflare_worker.this: Refreshing state... [id=4b5e2696491a41eaaa124f4e2a9855f2]
null_resource.web_app_cloudflare_secrets[0]: Refreshing state... [id=8867783181576424643]
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
~ update in-place
-/+ destroy and then create replacement
Terraform will perform the following actions:
# cloudflare_queue_consumer.image_build_finalization will be created
+ resource "cloudflare_queue_consumer" "image_build_finalization" {
+ account_id = "bf66240843ed90d19b82e4b90916d29a"
+ consumer_id = (known after apply)
+ created_on = (known after apply)
+ dead_letter_queue = "open-inspect-image-build-finalization-dlq-primo"
+ queue_id = "1ca823a150c54578a9ad1814325147a3"
+ queue_name = (known after apply)
+ script_name = "open-inspect-control-plane-primo"
+ settings = {
+ batch_size = 1
+ max_concurrency = 5
+ max_retries = 12
+ max_wait_time_ms = 1000
+ retry_delay = 15
+ visibility_timeout_ms = (known after apply)
}
+ type = "worker"
}
# local_file.web_app_wrangler_production[0] will be created
+ resource "local_file" "web_app_wrangler_production" {
+ content = <<-EOT
name = "open-inspect-web-primo"
main = ".open-next/worker.js"
compatibility_date = "2025-08-15"
compatibility_flags = ["nodejs_compat", "global_fetch_strictly_public"]
# A custom-domain deployment has one canonical browser origin.
workers_dev = true
[vars]
CONTROL_PLANE_URL = "https://open-inspect-control-plane-primo.primo-bf6.workers.dev"
NEXT_PUBLIC_WS_URL = "wss://open-inspect-control-plane-primo.primo-bf6.workers.dev"
NEXT_PUBLIC_SANDBOX_PROVIDER = "modal"
NEXT_PUBLIC_APP_NAME = "Primo"
NEXT_PUBLIC_APP_SHORT_NAME = "Primo"
NEXT_PUBLIC_APP_ICON_URL = ""
[assets]
directory = ".open-next/assets"
binding = "ASSETS"
[[services]]
binding = "CONTROL_PLANE_WORKER"
service = "open-inspect-control-plane-primo"
EOT
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "../../..//packages/web/wrangler.production.toml"
+ id = (known after apply)
}
# null_resource.control_plane_build must be replaced
-/+ resource "null_resource" "control_plane_build" {
~ id = "712263983139718104" -> (known after apply)
~ triggers = { # forces replacement
~ "always_run" = "2026-08-04T12:35:31Z" -> (known after apply)
}
}
# null_resource.github_bot_build[0] must be replaced
-/+ resource "null_resource" "github_bot_build" {
~ id = "7294943583288896375" -> (known after apply)
~ triggers = { # forces replacement
~ "always_run" = "2026-08-04T12:35:31Z" -> (known after apply)
}
}
# null_resource.linear_bot_build[0] must be replaced
-/+ resource "null_resource" "linear_bot_build" {
~ id = "8131685489368025167" -> (known after apply)
~ triggers = { # forces replacement
~ "always_run" = "2026-08-04T12:35:31Z" -> (known after apply)
}
}
# null_resource.slack_bot_build[0] must be replaced
-/+ resource "null_resource" "slack_bot_build" {
~ id = "3517235685678107646" -> (known after apply)
~ triggers = { # forces replacement
~ "always_run" = "2026-08-04T12:35:31Z" -> (known after apply)
}
}
# null_resource.web_app_cloudflare_build[0] must be replaced
-/+ resource "null_resource" "web_app_cloudflare_build" {
~ id = "7599918834973972838" -> (known after apply)
~ triggers = { # forces replacement
~ "always_run" = "2026-08-04T12:35:31Z" -> (known after apply)
}
}
# null_resource.web_app_cloudflare_deploy[0] will be created
+ resource "null_resource" "web_app_cloudflare_deploy" {
+ id = (known after apply)
+ triggers = {
+ "always_run" = (known after apply)
}
}
# module.control_plane_worker.cloudflare_worker.this will be updated in-place
~ resource "cloudflare_worker" "this" {
id = "c208a60c393e45e38eb502346bb7ce1e"
name = "open-inspect-control-plane-primo"
~ observability = {
~ logs = {
+ destinations = (known after apply)
# (4 unchanged attributes hidden)
}
~ traces = {
+ destinations = (known after apply)
# (3 unchanged attributes hidden)
}
# (2 unchanged attributes hidden)
}
~ references = {
~ dispatch_namespace_outbounds = [] -> (known after apply)
~ domains = [] -> (known after apply)
~ durable_objects = [
- {
- namespace_id = "4c77239db3614a6aac69a90e1fbd8955" -> null
- namespace_name = "open-inspect-control-plane-primo_SessionDO" -> null
- worker_id = "c208a60c393e45e38eb502346bb7ce1e" -> null
- worker_name = "open-inspect-control-plane-primo" -> null
},
- {
- namespace_id = "bf3328c8ebcb4039855ed7fcca6eb7e9" -> null
- namespace_name = "open-inspect-control-plane-primo_SchedulerDO" -> null
- worker_id = "c208a60c393e45e38eb502346bb7ce1e" -> null
- worker_name = "open-inspect-control-plane-primo" -> null
},
] -> (known after apply)
~ queues = [] -> (known after apply)
~ workers = [
- {
- id = "33782d80e8ff4af9b30b92870084b674" -> null
- name = "open-inspect-linear-bot-primo" -> null
},
- {
- id = "ac07332f8b0f4cdfa4ca04f966a9fa61" -> null
- name = "open-inspect-web-primo" -> null
},
- {
- id = "4b5e2696491a41eaaa124f4e2a9855f2" -> null
- name = "open-inspect-github-bot-primo" -> null
},
- {
- id = "5200e96d69804ea296e1f3a6b39e4243" -> null
- name = "open-inspect-slack-bot-primo" -> null
},
] -> (known after apply)
} -> (known after apply)
tags = []
~ updated_on = "2026-07-30T19:37:01Z" -> (known after apply)
# (6 unchanged attributes hidden)
}
# module.control_plane_worker.cloudflare_worker_version.this will be created
+ resource "cloudflare_worker_version" "this" {
+ account_id = "bf66240843ed90d19b82e4b90916d29a"
+ annotations = (known after apply)
+ bindings = (sensitive value)
+ compatibility_date = "2024-09-23"
+ compatibility_flags = [
+ "nodejs_compat",
]
+ created_on = (known after apply)
+ id = (known after apply)
+ limits = (known after apply)
+ main_module = "index.js"
+ main_script_base64 = (known after apply)
+ migration_tag = (known after apply)
+ modules = [
+ {
+ content_file = "../../..//packages/control-plane/dist/index.js"
+ content_sha256 = "b6a5fbfa0f6c78c14fb30f8dcd6c835a666500803bf4b2ce27a38403d8d40dff"
+ content_type = "application/javascript+module"
+ name = "index.js"
},
]
+ number = (known after apply)
+ source = (known after apply)
+ startup_time_ms = (known after apply)
+ urls = (known after apply)
+ usage_model = "standard"
+ worker_id = "c208a60c393e45e38eb502346bb7ce1e"
}
# module.control_plane_worker.cloudflare_workers_cron_trigger.this[0] will be updated in-place
~ resource "cloudflare_workers_cron_trigger" "this" {
id = "open-inspect-control-plane-primo"
~ schedules = [
~ {
~ created_on = "2026-05-22T19:51:30.060015Z" -> (known after apply)
~ modified_on = "2026-05-22T19:51:30.060015Z" -> (known after apply)
# (1 unchanged attribute hidden)
},
+ {
+ created_on = (known after apply)
+ cron = "7,37 * * * *"
+ modified_on = (known after apply)
},
]
# (2 unchanged attributes hidden)
}
# module.control_plane_worker.cloudflare_workers_deployment.this will be created
+ resource "cloudflare_workers_deployment" "this" {
+ account_id = "bf66240843ed90d19b82e4b90916d29a"
+ annotations = (known after apply)
+ author_email = (known after apply)
+ created_on = (known after apply)
+ id = (known after apply)
+ script_name = "open-inspect-control-plane-primo"
+ source = (known after apply)
+ strategy = "percentage"
+ versions = [
+ {
+ percentage = 100
+ version_id = (known after apply)
},
]
}
# module.github_bot_worker[0].cloudflare_worker.this will be updated in-place
~ resource "cloudflare_worker" "this" {
id = "4b5e2696491a41eaaa124f4e2a9855f2"
name = "open-inspect-github-bot-primo"
~ observability = {
~ logs = {
+ destinations = (known after apply)
# (4 unchanged attributes hidden)
}
~ traces = {
+ destinations = (known after apply)
# (3 unchanged attributes hidden)
}
# (2 unchanged attributes hidden)
}
~ references = {
~ dispatch_namespace_outbounds = [] -> (known after apply)
~ domains = [] -> (known after apply)
~ durable_objects = [] -> (known after apply)
~ queues = [] -> (known after apply)
~ workers = [] -> (known after apply)
} -> (known after apply)
tags = []
~ updated_on = "2026-07-30T19:37:10Z" -> (known after apply)
# (6 unchanged attributes hidden)
}
# module.github_bot_worker[0].cloudflare_worker_version.this will be created
+ resource "cloudflare_worker_version" "this" {
+ account_id = "bf66240843ed90d19b82e4b90916d29a"
+ annotations = (known after apply)
+ bindings = (sensitive value)
+ compatibility_date = "2024-09-23"
+ compatibility_flags = [
+ "nodejs_compat",
]
+ created_on = (known after apply)
+ id = (known after apply)
+ limits = (known after apply)
+ main_module = "index.js"
+ main_script_base64 = (known after apply)
+ migration_tag = (known after apply)
+ modules = [
+ {
+ content_file = "../../..//packages/github-bot/dist/index.js"
+ content_sha256 = "48f06ec5a8c212ab43a36f744754472e101760f32173ec4e19176cf833c20066"
+ content_type = "application/javascript+module"
+ name = "index.js"
},
]
+ number = (known after apply)
+ source = (known after apply)
+ startup_time_ms = (known after apply)
+ urls = (known after apply)
+ usage_model = "standard"
+ worker_id = "4b5e2696491a41eaaa124f4e2a9855f2"
}
# module.github_bot_worker[0].cloudflare_workers_deployment.this will be created
+ resource "cloudflare_workers_deployment" "this" {
+ account_id = "bf66240843ed90d19b82e4b90916d29a"
+ annotations = (known after apply)
+ author_email = (known after apply)
+ created_on = (known after apply)
+ id = (known after apply)
+ script_name = "open-inspect-github-bot-primo"
+ source = (known after apply)
+ strategy = "percentage"
+ versions = [
+ {
+ percentage = 100
+ version_id = (known after apply)
},
]
}
# module.linear_bot_worker[0].cloudflare_worker.this will be updated in-place
~ resource "cloudflare_worker" "this" {
id = "33782d80e8ff4af9b30b92870084b674"
name = "open-inspect-linear-bot-primo"
~ observability = {
~ logs = {
+ destinations = (known after apply)
# (4 unchanged attributes hidden)
}
~ traces = {
+ destinations = (known after apply)
# (3 unchanged attributes hidden)
}
# (2 unchanged attributes hidden)
}
~ references = {
~ dispatch_namespace_outbounds = [] -> (known after apply)
~ domains = [] -> (known after apply)
~ durable_objects = [] -> (known after apply)
~ queues = [] -> (known after apply)
~ workers = [
- {
- id = "c208a60c393e45e38eb502346bb7ce1e" -> null
- name = "open-inspect-control-plane-primo" -> null
},
] -> (known after apply)
} -> (known after apply)
tags = []
~ updated_on = "2026-08-04T12:35:32Z" -> (known after apply)
# (6 unchanged attributes hidden)
}
# module.linear_bot_worker[0].cloudflare_worker_version.this must be replaced
-/+ resource "cloudflare_worker_version" "this" {
~ annotations = {
+ workers_message = (known after apply)
+ workers_tag = (known after apply)
~ workers_triggered_by = "create_version_api" -> (known after apply)
} -> (known after apply)
~ bindings = (sensitive value) # forces replacement
~ created_on = "2026-08-04T12:35:34Z" -> (known after apply)
~ id = "8cf30ae8-a5dd-4214-ba14-7f922310794b" -> (known after apply)
+ limits = (known after apply)
+ main_script_base64 = (known after apply)
+ migration_tag = (known after apply)
~ modules = [
- { # forces replacement
- content_file = "../../..//packages/linear-bot/dist/index.js" -> null
- content_sha256 = "2f0414718c9f0ea3023176fbd3f9e7a699f51760054b3eadf8791534a074c053" -> null
- content_type = "application/javascript+module" -> null
- name = "index.js" -> null
},
+ { # forces replacement
+ content_file = "../../..//packages/linear-bot/dist/index.js"
+ content_sha256 = "cb7ec20bace9d25b59cf6379316354573388e15b0cc1f6f50be169f1fd318143"
+ content_type = "application/javascript+module"
+ name = "index.js"
},
]
~ number = 61 -> (known after apply)
~ source = "terraform" -> (known after apply)
~ startup_time_ms = 39 -> (known after apply)
~ urls = [
- "https://8cf30ae8-open-inspect-linear-bot-primo.primo-bf6.workers.dev",
] -> (known after apply)
# (6 unchanged attributes hidden)
}
# module.linear_bot_worker[0].cloudflare_workers_deployment.this must be replaced
-/+ resource "cloudflare_workers_deployment" "this" {
~ annotations = {
+ workers_message = (known after apply)
~ workers_triggered_by = "deployment" -> (known after apply)
} -> (known after apply)
~ author_email = "nicolas@primo.la" -> (known after apply)
~ created_on = "2026-08-04T12:35:35Z" -> (known after apply)
~ id = "9c108f32-d908-4b59-9574-175c0a90ad89" -> (known after apply)
~ source = "terraform" -> (known after apply)
~ versions = [ # forces replacement
~ {
~ version_id = "8cf30ae8-a5dd-4214-ba14-7f922310794b" -> (known after apply)
# (1 unchanged attribute hidden)
},
]
# (3 unchanged attributes hidden)
}
# module.modal_app[0].null_resource.modal_deploy is tainted, so must be replaced
-/+ resource "null_resource" "modal_deploy" {
~ id = "1192764756692112984" -> (known after apply)
~ triggers = {
~ "source_hash" = "b8ca0bca092dcbd3335969169a8f2d08e454c57de021e33a7f4ca84e93804874" -> "9cba85cacc65ace137931f798809aa3be528307547e91307e2b764ec8a90c9dd"
# (3 unchanged elements hidden)
}
}
# module.slack_bot_worker[0].cloudflare_worker.this will be updated in-place
~ resource "cloudflare_worker" "this" {
id = "5200e96d69804ea296e1f3a6b39e4243"
name = "open-inspect-slack-bot-primo"
~ observability = {
~ logs = {
+ destinations = (known after apply)
# (4 unchanged attributes hidden)
}
~ traces = {
+ destinations = (known after apply)
# (3 unchanged attributes hidden)
}
# (2 unchanged attributes hidden)
}
~ references = {
~ dispatch_namespace_outbounds = [] -> (known after apply)
~ domains = [] -> (known after apply)
~ durable_objects = [] -> (known after apply)
~ queues = [
- {
- queue_consumer_id = "a755a290fd92417fb11c298f9c1d1f40" -> null
- queue_id = "56ef0f3e13bd46a3a39f30c79ec547fa" -> null
- queue_name = "open-inspect-slack-completion-primo" -> null
},
] -> (known after apply)
~ workers = [
- {
- id = "c208a60c393e45e38eb502346bb7ce1e" -> null
- name = "open-inspect-control-plane-primo" -> null
},
] -> (known after apply)
} -> (known after apply)
tags = []
~ updated_on = "2026-08-04T12:35:32Z" -> (known after apply)
# (6 unchanged attributes hidden)
}
# module.slack_bot_worker[0].cloudflare_worker_version.this must be replaced
-/+ resource "cloudflare_worker_version" "this" {
~ annotations = {
+ workers_message = (known after apply)
+ workers_tag = (known after apply)
~ workers_triggered_by = "create_version_api" -> (known after apply)
} -> (known after apply)
~ bindings = (sensitive value) # forces replacement
~ created_on = "2026-08-04T12:35:33Z" -> (known after apply)
~ id = "6b9fbaec-16ec-4a30-89ad-cc60fb5348b8" -> (known after apply)
+ limits = (known after apply)
+ main_script_base64 = (known after apply)
+ migration_tag = (known after apply)
~ modules = [
- { # forces replacement
- content_file = "../../..//packages/slack-bot/dist/index.js" -> null
- content_sha256 = "329a5e8c43da4df91320a17a8f32b9ca921876def0224489bd51167d47b2d111" -> null
- content_type = "application/javascript+module" -> null
- name = "index.js" -> null
},
+ { # forces replacement
+ content_file = "../../..//packages/slack-bot/dist/index.js"
+ content_sha256 = "ad4e445928a59ff0b8be03f3650b81cdbda4b77d4d6ea0f25f408696607cca69"
+ content_type = "application/javascript+module"
+ name = "index.js"
},
]
~ number = 64 -> (known after apply)
~ source = "terraform" -> (known after apply)
~ startup_time_ms = 40 -> (known after apply)
~ urls = [
- "https://6b9fbaec-open-inspect-slack-bot-primo.primo-bf6.workers.dev",
] -> (known after apply)
# (6 unchanged attributes hidden)
}
# module.slack_bot_worker[0].cloudflare_workers_deployment.this must be replaced
-/+ resource "cloudflare_workers_deployment" "this" {
~ annotations = {
+ workers_message = (known after apply)
~ workers_triggered_by = "deployment" -> (known after apply)
} -> (known after apply)
~ author_email = "nicolas@primo.la" -> (known after apply)
~ created_on = "2026-08-04T12:35:34Z" -> (known after apply)
~ id = "ee7c9fc3-dff3-48b9-85c4-d4579ba23ca7" -> (known after apply)
~ source = "terraform" -> (known after apply)
~ versions = [ # forces replacement
~ {
~ version_id = "6b9fbaec-16ec-4a30-89ad-cc60fb5348b8" -> (known after apply)
# (1 unchanged attribute hidden)
},
]
# (3 unchanged attributes hidden)
}
Plan: 17 to add, 5 to change, 10 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: tfplan
To perform exactly these actions, run the following command to apply:
terraform apply "tfplan"Pushed by: @NicolasWalter |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/web/src/hooks/use-sidebar-sessions.ts (1)
45-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winName the default creator filter.
Line 46 defines the default filter inline. Define
DEFAULT_SESSION_CREATOR_FILTERonce and initializeinitialFilterfrom it.Proposed change
type SessionCreatorFilter = "all" | "mine"; +const DEFAULT_SESSION_CREATOR_FILTER: SessionCreatorFilter = "all"; useEffect(() => { - let initialFilter: SessionCreatorFilter = "all"; + let initialFilter = DEFAULT_SESSION_CREATOR_FILTER;As per coding guidelines, “Define each default value exactly once in a named constant and import or reuse that constant everywhere.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/hooks/use-sidebar-sessions.ts` around lines 45 - 57, Define a named DEFAULT_SESSION_CREATOR_FILTER constant for the "all" default and initialize initialFilter from it in the useEffect hook. Reuse this constant wherever the default creator filter is needed instead of repeating the literal.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/control-plane/src/routes/repos.ts`:
- Line 57: Define the identity ScmApiTimer function in a named constant near the
route timer definitions, then update the relevant constructor or function
parameter to use that constant as its default instead of the inline `(fn) =>
fn()` expression. Reuse the named constant wherever this identity default is
needed.
---
Nitpick comments:
In `@packages/web/src/hooks/use-sidebar-sessions.ts`:
- Around line 45-57: Define a named DEFAULT_SESSION_CREATOR_FILTER constant for
the "all" default and initialize initialFilter from it in the useEffect hook.
Reuse this constant wherever the default creator filter is needed instead of
repeating the literal.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f0902cde-9307-4744-9713-a7f9f30905ac
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpackages/modal-infra/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (21)
packages/control-plane/src/routes/repos.test.tspackages/control-plane/src/routes/repos.tspackages/control-plane/src/webhooks/sentry.tspackages/control-plane/test/integration/webhooks.test.tspackages/github-bot/package.jsonpackages/linear-bot/package.jsonpackages/shared/src/triggers/index.tspackages/shared/src/triggers/sentry/context.tspackages/shared/src/triggers/sentry/index.tspackages/shared/src/triggers/sentry/normalizer.test.tspackages/shared/src/triggers/sentry/normalizer.tspackages/shared/src/triggers/sentry/payloads.tspackages/slack-bot/package.jsonpackages/web/package.jsonpackages/web/src/components/session-sidebar.test.tsxpackages/web/src/components/session-sidebar.tsxpackages/web/src/components/session-timeline.test.tsxpackages/web/src/components/session-timeline.tsxpackages/web/src/components/task-activity-item.tsxpackages/web/src/hooks/use-sidebar-sessions.tspackages/web/src/lib/timeline-items.ts
| env: Env, | ||
| db: SqlDatabase, | ||
| traceId?: string, | ||
| timeScmApi: ScmApiTimer = (fn) => fn() |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Name the identity timer default.
Define the identity ScmApiTimer in a named constant. Use that constant as the parameter default.
Proposed fix
type ScmApiTimer = <T>(fn: () => Promise<T>) => Promise<T>;
+const IDENTITY_SCM_API_TIMER: ScmApiTimer = (fn) => fn();
async function refreshReposCache(
env: Env,
db: SqlDatabase,
traceId?: string,
- timeScmApi: ScmApiTimer = (fn) => fn()
+ timeScmApi: ScmApiTimer = IDENTITY_SCM_API_TIMER
): Promise<ReposRefreshResult> {As per coding guidelines, define each default value exactly once in a named constant and import or reuse that constant everywhere.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| timeScmApi: ScmApiTimer = (fn) => fn() | |
| type ScmApiTimer = <T>(fn: () => Promise<T>) => Promise<T>; | |
| const IDENTITY_SCM_API_TIMER: ScmApiTimer = (fn) => fn(); | |
| async function refreshReposCache( | |
| env: Env, | |
| db: SqlDatabase, | |
| traceId?: string, | |
| timeScmApi: ScmApiTimer = IDENTITY_SCM_API_TIMER | |
| ): Promise<ReposRefreshResult> { |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/control-plane/src/routes/repos.ts` at line 57, Define the identity
ScmApiTimer function in a named constant near the route timer definitions, then
update the relevant constructor or function parameter to use that constant as
its default instead of the inline `(fn) => fn()` expression. Reuse the named
constant wherever this identity default is needed.
Source: Coding guidelines
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3003b52a30
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (issueWebhookResult.data.action !== "created") { | ||
| if (sentryHookResource === "issue") { | ||
| return { status: "skipped", reason: "unsupported_action" }; |
There was a problem hiding this comment.
Handle issue.unresolved as a regression
When the webhook uses the current Sentry-Hook-Resource: issue shape, Sentry issue lifecycle actions include regressed/unresolved issues (the issue webhook docs list unresolved alongside created: https://docs.sentry.io/integrations/integration-platform/webhooks/issues/). This branch returns unsupported_action for every issue action except created, so an automation configured for the already-exposed issue.regression event never fires for the current Sentry issue webhook path; only legacy event-alert regressions can still work. Please map unresolved (and any regression action you expect) to issue.regression instead of skipping it.
Useful? React with 👍 / 👎.
Automated upstream sync
Clean merge from
ColeMurray/background-agents@main.This PR was opened automatically by
.github/workflows/sync-upstream.yml. Review the commit list and merge when CI is green.Summary by CodeRabbit
New Features
Bug Fixes