Skip to content

test(httpapi): pin dot-segment collapse targets at 404 on trailing slash - #1015

Merged
jiashuoz merged 1 commit into
tokencanopy:mainfrom
AmirF194:fix/792-dot-segment-collapse-regression-test
Sep 26, 2026
Merged

jiashuoz merged 1 commit into
tokencanopy:mainfrom
AmirF194:fix/792-dot-segment-collapse-regression-test

Conversation

@AmirF194

Copy link
Copy Markdown
Contributor

Summary

A dot-segment path collapse (DELETE /v1/account/suppressions/.., DELETE /v1/agents/{email}/suppressions/..) resolves to the destructive deleteAccount / deleteAgent routes with a trailing slash. It's safe today only because chi's root router registers no RedirectSlashes/StripSlashes/CleanPath middleware, so the trailing-slash form 404s: a library default the repo never asserted. This adds a regression test pinning that 404, following router_errors_test.go's existing table-test pattern, so a future chi upgrade or an accidental trailing-slash middleware addition fails CI instead of silently turning the collapse into a live destructive hit.

Priority 1 from #792 (the SDK-side guard) already shipped in #909. This covers priority 2 (the router regression test). Priorities 3 (web fetch call-site hardening) and 4 (scaling confirmation to blast radius) are out of scope here.

Operational risk

None, test-only change, no production code touched.

Test plan

  • go test ./internal/httpapi/...: full package suite passes, including both new sub-tests (account, agent).
  • Temporarily added root.Use(middleware.RedirectSlashes) to confirm the new test goes red (301 instead of 404) before reverting; it catches the regression it's meant to catch.
  • go vet and gofmt -l clean on the changed file; go test -cover puts the package at 87.0%, above the 73% floor in .testcoverage.yml.

I ran the package suite standalone against a local Postgres container rather than through make cover's full fixture wiring, so I can't speak to the coverage-gate job's exact numbers, only that this package's own floor is comfortably cleared.

DELETE .../account/suppressions/.. and DELETE .../agents/{email}/suppressions/..
collapse onto deleteAccount and deleteAgent with a trailing slash (tokencanopy#792).
Today chi answers both with the canonical 404 envelope only because no
RedirectSlashes/StripSlashes/CleanPath middleware is registered on the
root router; nothing in the repo asserted it. Add a regression test
pinning that 404, so a future chi upgrade or middleware addition fails
this test instead of turning the collapse into a live destructive hit.

Priority 1 (the SDK guard) shipped in tokencanopy#909. Priorities 3 (web helper
rollout) and 4 (confirmation scaling) from the issue are out of scope
here.

Refs tokencanopy#792
@AmirF194
AmirF194 requested a review from jiashuoz as a code owner September 10, 2026 21:11
@AmirF194

Copy link
Copy Markdown
Contributor Author

tunglambk opened #1030 on the same issue, testing the identical trailing-slash 404 property but spec-driven across every DELETE path instead of the two routes here. This one's narrower and was first; I'll close it if you'd rather take the broader version.

@jiashuoz
jiashuoz merged commit a664a5d into tokencanopy:main Sep 26, 2026
29 checks passed
jiashuoz added a commit that referenced this pull request Sep 26, 2026
* test(contract): point shared test domain at agents.localhost

agents.e2a.dev is a customer identifier per AGENTS.md's public data
boundary, not a safe value for test fixtures. Point the contract
harness's SharedDomain at agents.localhost instead, update the
scenario addresses and the over-cap fixture that depended on it, and
add a test that fails if the old domain reappears.

Fixes #829

* fix(testutil): seed the shared domain in the contract and e2e test harnesses

StartContractServer and TestServer both pass SharedDomain "agents.localhost"
to the API but never call store.EnsureSharedDomain for it, so the domains
table only carries the migration-seeded agents.e2a.dev row. Any scenario
that creates an agent on the shared domain (register_agent in
tests/contract/scenarios.yaml, the Go e2e suite) hits the FK on
agent_identities.registered_domain: exactly the failure EnsureSharedDomain's
own doc comment describes for a deployment whose shared_domain diverges from
that hardcoded seed.

Mirrors the boot-time call cmd/e2a/main.go already makes for production.

* fix(test): update the remaining agents.e2a.dev fixtures to agents.localhost

Three more places hardcoded the pre-move shared domain and only surfaced
once EnsureSharedDomain made contract-server agent creation actually work:
the Python and TypeScript SDK contract-test fixtures asserted or registered
agents on agents.e2a.dev (now unverified, so every one of them 400s), and
the Go max_agents race e2e test registered its race agents on the same
stale domain for the same reason.

* fix(test): stop the new guard test from tripping on its own comments

TestContractHarnessDoesNotUseCustomerSharedDomain does a plain substring
search for the banned domain, which also matched the explanatory comment
above EnsureSharedDomain in both harnesses. Reworded the comments to stop
quoting the literal string.

* fix: serialize delivery feedback with agent purge (#1028)

* deps: bump the go-minor-patch group with 9 updates (#1026)

Bumps the go-minor-patch group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) | `1.33.2` | `1.33.3` |
| [github.com/aws/aws-sdk-go-v2/service/sesv2](https://github.com/aws/aws-sdk-go-v2) | `1.71.0` | `1.72.0` |
| [github.com/aws/aws-sdk-go-v2/service/sts](https://github.com/aws/aws-sdk-go-v2) | `1.48.0` | `1.49.0` |
| [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) | `4.1.4` | `4.1.5` |
| [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) | `5.10.0` | `5.11.0` |
| [golang.org/x/crypto](https://github.com/golang/crypto) | `0.55.0` | `0.57.0` |
| [golang.org/x/net](https://github.com/golang/net) | `0.58.0` | `0.59.0` |
| [golang.org/x/oauth2](https://github.com/golang/oauth2) | `0.36.0` | `0.37.0` |
| [golang.org/x/text](https://github.com/golang/text) | `0.41.0` | `0.42.0` |


Updates `github.com/aws/aws-sdk-go-v2/config` from 1.33.2 to 1.33.3
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@config/v1.33.2...config/v1.33.3)

Updates `github.com/aws/aws-sdk-go-v2/service/sesv2` from 1.71.0 to 1.72.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@service/s3/v1.71.0...service/s3/v1.72.0)

Updates `github.com/aws/aws-sdk-go-v2/service/sts` from 1.48.0 to 1.49.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@service/s3/v1.48.0...service/s3/v1.49.0)

Updates `github.com/go-jose/go-jose/v4` from 4.1.4 to 4.1.5
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Commits](go-jose/go-jose@v4.1.4...v4.1.5)

Updates `github.com/jackc/pgx/v5` from 5.10.0 to 5.11.0
- [Release notes](https://github.com/jackc/pgx/releases)
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](jackc/pgx@v5.10.0...v5.11.0)

Updates `golang.org/x/crypto` from 0.55.0 to 0.57.0
- [Commits](golang/crypto@v0.55.0...v0.57.0)

Updates `golang.org/x/net` from 0.58.0 to 0.59.0
- [Commits](golang/net@v0.58.0...v0.59.0)

Updates `golang.org/x/oauth2` from 0.36.0 to 0.37.0
- [Commits](golang/oauth2@v0.36.0...v0.37.0)

Updates `golang.org/x/text` from 0.41.0 to 0.42.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](golang/text@v0.41.0...v0.42.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-version: 1.33.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-minor-patch
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sesv2
  dependency-version: 1.72.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sts
  dependency-version: 1.49.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-version: 4.1.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-minor-patch
- dependency-name: github.com/jackc/pgx/v5
  dependency-version: 5.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: golang.org/x/crypto
  dependency-version: 0.57.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: golang.org/x/net
  dependency-version: 0.59.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: golang.org/x/oauth2
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: golang.org/x/text
  dependency-version: 0.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps: bump the npm-minor-patch group with 5 updates (#1023)

Bumps the npm-minor-patch group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.4.1` | `26.5.0` |
| [@storybook/react](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/react) | `10.5.10` | `10.6.0` |
| [@storybook/react-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-vite) | `10.5.10` | `10.6.0` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.5` | `19.2.7` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core) | `10.5.10` | `10.6.0` |


Updates `@types/node` from 26.4.1 to 26.5.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@storybook/react` from 10.5.10 to 10.6.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.6.0/code/renderers/react)

Updates `@storybook/react-vite` from 10.5.10 to 10.6.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.6.0/code/frameworks/react-vite)

Updates `@types/react-dom` from 19.2.5 to 19.2.7
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `storybook` from 10.5.10 to 10.6.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.6.0/code/core)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 26.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@storybook/react"
  dependency-version: 10.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@storybook/react-vite"
  dependency-version: 10.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@types/react-dom"
  dependency-version: 19.2.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: storybook
  dependency-version: 10.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(web): bump the npm-minor-patch group in /web with 2 updates (#1022)

Bumps the npm-minor-patch group in /web with 2 updates: [dompurify](https://github.com/cure53/DOMPurify) and [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `dompurify` from 3.4.14 to 3.4.15
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](cure53/DOMPurify@3.4.14...3.4.15)

Updates `@types/node` from 26.4.1 to 26.5.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: "@types/node"
  dependency-version: 26.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps: bump vitest from 4.1.11 to 5.0.0 (#1025)

Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.11 to 5.0.0.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 5.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps: bump @vitest/coverage-v8 from 4.1.11 to 5.0.0 (#1024)

Bumps [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) from 4.1.11 to 5.0.0.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/coverage-v8)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(web): bump the npm-minor-patch group in /web with 4 updates (#1034)

Bumps the npm-minor-patch group in /web with 4 updates: [next](https://github.com/vercel/next.js), [@next/mdx](https://github.com/vercel/next.js/tree/HEAD/packages/next-mdx), [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next).


Updates `next` from 16.3.4 to 16.3.5
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](vercel/next.js@v16.3.4...v16.3.5)

Updates `@next/mdx` from 16.3.4 to 16.3.5
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.5/packages/next-mdx)

Updates `@types/node` from 26.5.0 to 26.6.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint-config-next` from 16.3.4 to 16.3.5
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.5/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.3.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: "@next/mdx"
  dependency-version: 16.3.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: "@types/node"
  dependency-version: 26.6.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: eslint-config-next
  dependency-version: 16.3.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps: bump the go-minor-patch group with 3 updates (#1036)

Bumps the go-minor-patch group with 3 updates: [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2), [github.com/aws/aws-sdk-go-v2/service/sesv2](https://github.com/aws/aws-sdk-go-v2) and [github.com/aws/aws-sdk-go-v2/service/sts](https://github.com/aws/aws-sdk-go-v2).


Updates `github.com/aws/aws-sdk-go-v2/config` from 1.33.3 to 1.33.5
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@config/v1.33.3...config/v1.33.5)

Updates `github.com/aws/aws-sdk-go-v2/service/sesv2` from 1.72.0 to 1.73.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@service/s3/v1.72.0...service/s3/v1.73.0)

Updates `github.com/aws/aws-sdk-go-v2/service/sts` from 1.49.0 to 1.51.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@service/s3/v1.49.0...service/s3/v1.51.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-version: 1.33.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-minor-patch
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sesv2
  dependency-version: 1.73.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sts
  dependency-version: 1.51.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps: bump the npm-minor-patch group with 10 updates (#1035)

Bumps the npm-minor-patch group with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.5.0` | `26.6.1` |
| [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `5.0.0` | `5.0.1` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `5.0.0` | `5.0.1` |
| [yaml](https://github.com/eemeli/yaml) | `2.9.0` | `2.9.1` |
| [zod](https://github.com/colinhacks/zod) | `4.5.4` | `4.6.5` |
| [react](https://github.com/react/react/tree/HEAD/packages/react) | `19.2.8` | `19.3.0` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.18` | `19.3.0` |
| [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) | `19.2.8` | `19.3.0` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.7` | `19.3.0` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.2.2` | `8.3.0` |


Updates `@types/node` from 26.5.0 to 26.6.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.1/packages/coverage-v8)

Updates `vitest` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.1/packages/vitest)

Updates `yaml` from 2.9.0 to 2.9.1
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](eemeli/yaml@v2.9.0...v2.9.1)

Updates `zod` from 4.5.4 to 4.6.5
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](colinhacks/zod@v4.5.4...v4.6.5)

Updates `react` from 19.2.8 to 19.3.0
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.3.0/packages/react)

Updates `@types/react` from 19.2.18 to 19.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `react-dom` from 19.2.8 to 19.3.0
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.3.0/packages/react-dom)

Updates `@types/react-dom` from 19.2.7 to 19.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `vite` from 8.2.2 to 8.3.0
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@8.3.0/packages/vite)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 26.6.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 5.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: vitest
  dependency-version: 5.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: yaml
  dependency-version: 2.9.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: zod
  dependency-version: 4.6.5
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: react
  dependency-version: 19.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@types/react"
  dependency-version: 19.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: react-dom
  dependency-version: 19.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@types/react-dom"
  dependency-version: 19.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: vite
  dependency-version: 8.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test(sdk): budget account metrics live read (#956)

* docs: fix stale toolchain and config references (#1011)

AGENTS.md's toolchain line still said Go 1.25 in go.mod and Go 1.26 for
the Dockerfiles; go.mod is now on 1.26.0 and the Dockerfiles moved to
golang:1.27-alpine. CONTRIBUTING.md's prerequisites table had the same
stale Go 1.25.

AGENTS.md's package catalog never mentioned `internal/sendingpolicy`,
the sending-protection runtime policy package (the sole provider-
authorization gate, ramp/budget composition, operator activation) that
several recent PRs built out under "Send guards & accounting".

docs/deployment.md's OIDC config table omitted `E2A_OIDC_LOGOUT_URL`,
which config.example.yaml and internal/config already document and
internal/auth wires up as the optional post-logout redirect.


Claude-Session: https://claude.ai/code/session_01CR23fVs5zSjJreAZYtpQkb

Co-authored-by: Claude <noreply@anthropic.com>

* test(httpapi): pin dot-segment collapse targets at 404 on trailing slash (#1015)

DELETE .../account/suppressions/.. and DELETE .../agents/{email}/suppressions/..
collapse onto deleteAccount and deleteAgent with a trailing slash (#792).
Today chi answers both with the canonical 404 envelope only because no
RedirectSlashes/StripSlashes/CleanPath middleware is registered on the
root router; nothing in the repo asserted it. Add a regression test
pinning that 404, so a future chi upgrade or middleware addition fails
this test instead of turning the collapse into a live destructive hit.

Priority 1 (the SDK guard) shipped in #909. Priorities 3 (web helper
rollout) and 4 (confirmation scaling) from the issue are out of scope
here.

Refs #792

* test(httpapi): pin destructive routes against trailing slashes (#1030)

chi matches routes exactly and does not redirect trailing slashes, which is what keeps a client-side dot-segment collapse from reaching a destructive parent handler. Nothing asserted it, so a router upgrade or a StrictSlash-style change would make every collapse live with no test failing. The test takes every DELETE path from the committed spec and asserts the trailing-slash form 404s, and that the path itself matches.

Refs #792

Co-authored-by: Tung Lam <lamphamabtung96@gmail.com>

* feat(sending): external sending access for new accounts (#1041)

* feat(sending): external sending access schema and policy object

Migration 121 adds owner-mailbox proof (users.owner_email_verified_at +
bound address/source), the operator grant and revision on
account_sending_controls, the billing entitlement on account_limits, the
append-only access event table, the private request queue, and the
submission.external_sending_not_enabled lifecycle reason. The runtime
policy gains an optional external_sending_access object (absent =
disabled, legacy hashes unchanged) and the capability marker lists it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(sending): enforce external sending access at every gate seam

One decision (internal/sendingpolicy/external_access.go) judges the full
To/Cc/Bcc envelope and the durable sender at acceptance
(PrepareExternalTx), final authorization (ConsumeAttempt, under the
normative locks) and redemption (RedeemProviderCall, refuse-only). A
refused acceptance queues nothing; a queued message newly refused fails
terminally with submission.external_sending_not_enabled and gives its
ledgers back; read errors fail closed without provider I/O. Adds the
operator module (inspect/approve/revoke with revision CAS and append-only
audit, request decisions) and the customer request queue. Tests drive
the real gate and the real provider adapter seam.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* style: gofmt

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(auth): record owner-mailbox proof at verified Google login

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(sending): local operator commands for external sending access

-inspect-external-sending, -approve-external-sending,
-revoke-external-sending and -decline-external-sending-request act on
one account with an explicit revision CAS and reason; revocation warns
when the paid entitlement still allows external sending.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(api): external_sending_not_enabled 403, sending_access status and request intake

- Paid-base entitlement is derived from account_limits.plan_code against
  the hosted policy's paid_plan_codes (no new column, no billing writer).
- DeliverOutbound preflights the full To/Cc/Bcc envelope before screening
  or persistence; accept-tx and approval refusals map to the same 403
  with ExternalSendingNotEnabledDetails (allowed destinations, recovery
  URL). TTL auto-approval rejects a draft that can never be sent.
- GET /v1/account gains the additive beta sending_access booleans.
- Beta GET/POST /v1/account/sending-access/request: idempotent pending
  request bound to the authenticated account, 3 per 30 days, operator
  notified through the fixed FEEDBACK_NOTIFY_* envelope.
- Lifecycle reason submission.external_sending_not_enabled documented;
  spec regenerated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore(sdk): regenerate TS and Python bases for external sending access

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(contract): external sending access scenarios and restricted account

The contract server now runs the production composition with external
sending access enforced behind a far-future cohort cutoff; a fourth
seeded account (E2A_TEST_RESTRICTED_API_KEY, {restricted_api_key}) is the
only one inside it. Scenarios cover the account status, whole-envelope
refusals (To/Cc/Bcc), keyed-refusal non-replay, tenant isolation, the
allowed same-account send, and the request intake.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs: external sending access pipeline, beta fields and data handling

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs: note manual purge of expired access audit rows

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(lifecycle): reconstruct external-access refusals under their own reason

The email.failed event of a refused queued message was reconstructed as
submission.local_retries_exhausted beside the persisted
submission.external_sending_not_enabled transition (seen in the local
over-the-wire e2e). Adds domain-loss and concurrency race tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(api): preflight judges bare addresses, as the gate does

The send API accepts display-name recipients; the composer persists the
bare addr-spec. The preflight now reduces each recipient the same way so
an allowed destination written as "Name <addr>" is not refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(api): declare the 200 resubmit response of createSendingAccessRequest

Without it the generated clients had no case for 200 and returned
nothing on an idempotent resubmit. Spec and both SDK bases regenerated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(python-sdk): external sending access parity

Maps external_sending_not_enabled (permission, not retryable), adds
account.get_sending_access_request / request_sending_access, the
lifecycle reason vocabulary, and the {restricted_api_key} contract
placeholder with live coverage.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(web): external sending restriction disclosure and request flow

Restriction notice on the inboxes dashboard and onboarding success panel
(only when enforcement applies and neither grant nor paid entitlement is
present; paid-plan action only behind NEXT_PUBLIC_BILLING_API), eligible
status lines, review-queue recipient preflight and 403 recovery link, the
/sending-access status + request page, and the new lifecycle reason copy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ts-sdk): external sending access parity

Maps external_sending_not_enabled (permission, not retryable), adds
account.getSendingAccessRequest / requestSendingAccess with unit and live
contract coverage, and the {restricted_api_key} scenario placeholder.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(cli): sending-access commands, whoami restriction line, 403 guidance

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(mcp): document external_sending_not_enabled on send tools

whoami already passes sending_access through; send/reply/forward (and
the send_email alias) now explain the refusal, allowed destinations and
dashboard recovery without suggesting retries. No approval tool.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test: replay migration 121 when race tests rebuild account_sending_controls

Two first-apply race tests drop and rebuild account_sending_controls from
migration 113/115 only; the runner had already recorded 121, so any later
test binary on the same per-package database lost the new columns.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(sending): external access decision metrics; run the domain-loss race case

e2a_external_access_decisions_total{stage,route,mode} records every shadow
or enforce evaluation with bounded labels (shadow route=denied is the
would-refuse impact evidence). The domain-verification-lost redemption
race case was declared but never ranged over; it now runs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(python-sdk): decode the declared 200 resubmit directly

The spec now declares createSendingAccessRequest's 200 response, so the
generated base decodes it; the follow-up-read fallback was dead and its
test mocked an undecodable body. The test now pins a one-call decode of
the existing pending request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* style(telemetry): gofmt

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(sending): paid entitlement is the billing column, not plan_code

Review found that plan_code stays paid while a subscription is trialing
or past_due, so plan-code membership granted external sending to trials.
Reverts to the design: account_limits.external_sending_entitled (default
false, written only by the hosted billing writer from active
subscriptions; the server never writes it) is the only paid route, and
paid_plan_codes is removed from the policy object (the key now fails
strict parsing). Also: the preflight reports pause before any access
answer and treats malformed/empty recipients as a validation matter; the
status object and request intake are absent/501 while the control is
disabled; domain-ownership and entitlement-loss redemption races are
covered at the gate and the real adapter seam.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(api): pause wins at preflight, disabled surfaces, fenced operator mail, no test-hold edits

- A paused account gets sending_paused from the preflight, never an
  external-access restriction.
- GET /v1/account omits sending_access and the request endpoints answer
  501 when the control is disabled (feature-off stays byte-identical).
- The operator notification puts the real commands first and fences the
  customer-supplied text line by line.
- A held platform test (type=test) can no longer be edited at approval:
  edits turned platform-branded noreply mail into arbitrary content to
  arbitrary recipients (adversarial review; affects every account).
- Spec and SDK bases regenerated for the updated descriptions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: review nits (TS doc key, MCP whoami sending_access, synthetic fixtures)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(sending): pause replaces only an enforced external-access denial

The preflight reported sending_paused before the mode/cohort checks, so a
paused account's self-send loopback and review holds were refused in
shadow mode and for out-of-cohort accounts, unlike with the control off.
Pause now replaces only an enforced denial; the preflight evaluates on the
facts it already loaded (one account read). Web: a 501 (control disabled)
reads as no request, like 404.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Josh Zhang <39790535+jiashuoz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Tung Lam <53996158+tunglambk@users.noreply.github.com>
Co-authored-by: Tung Lam <lamphamabtung96@gmail.com>
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.

2 participants