typescript-sdk/docs/behavior-surface-pins.md
Sam Morrow 6032170087
Some checks failed
Conformance Tests / client-conformance (push) Has been cancelled
Conformance Tests / server-conformance (push) Has been cancelled
Deploy Docs / deploy-docs (push) Has been cancelled
Examples / examples (build + e2e) (push) Has been cancelled
/ build (push) Has been cancelled
/ test (20) (push) Has been cancelled
/ test (22) (push) Has been cancelled
/ test (24) (push) Has been cancelled
/ test-e2e (20) (push) Has been cancelled
/ test-e2e (22) (push) Has been cancelled
/ test-e2e (24) (push) Has been cancelled
/ test-runtimes (bun, 1.x) (push) Has been cancelled
/ test-runtimes (deno, v2.x) (push) Has been cancelled
Publish Any Commit / pkg-publish (push) Has been cancelled
Release / Version (push) Has been cancelled
Release / Publish (push) Has been cancelled
feat(server): add request-time OAuth scope challenges (#1624)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-16 16:51:56 +00:00

2.9 KiB

Behavior-surface pins

Some tests in this repo are pins: they assert the exact current value of a wire- or consumer-visible behavior — an error code, a schema boundary, an export map, the stdio env safelist — rather than checking that a feature works. Their job is to distinguish a deliberate surface change from an accidental one: the regular suite stays green through either; a pin goes red through both.

When a pin goes red on your change

A red pin does not mean the change is forbidden. It means the change is surface-visible and must be deliberate:

  1. Confirm the change is intended. If it isn't, the pin just caught an accidental break.
  2. Update the pin in the same PR.
  3. Add a changeset if the surface is consumer-facing.
  4. Update docs/migration/upgrade-to-v2.md (or docs/migration/support-2026-07-28.md if 2026-only) where consumer-facing.

Never weaken a pin (loosen an exact match, delete an assertion) just to make CI pass — that reopens the silent-drift hole the pin exists to close.

Where pins live

Surface File
Wire error-code tables, error classes, version constants packages/core-internal/test/types/errorSurfacePins.test.ts
Schema strict/strip/loose boundaries, key existence packages/core-internal/test/types/schemaBoundaryPins.test.ts
Published package set, export maps, dual ESM/CJS topology packages/core-internal/test/packageTopologyPins.test.ts
stdio environment-inheritance safelist packages/client/test/client/stdioEnvPins.test.ts
2025-11-25 wire method-registry membership, schema identity packages/core-internal/test/types/registryPins.test.ts
OAuth scope challenge timing and serialization packages/server/test/server/scopeChallenge.test.ts

Writing a new pin

  • The expectation side must be a literal frozen in the test, never a value imported from src. Comparing a source constant against itself pins nothing.
  • Mutation-check it once before landing: flip the source behavior locally and confirm the pin actually goes red. A pin that stays green under the drift it claims to guard is worse than no pin.
  • Pin behavior a deployed peer or consumer can observe. Internal details that are invisible across the wire and the public API don't need pins.
  • Don't pin a known bug to make it load-bearing — file an issue instead.

History

The original, much broader inventory was developed against v1.x in #2258 and #2262 (closed unmerged). This sweep ports only the boundary surfaces above; see those PRs for the fuller exploration and the reasoning behind what was left out.