Skip to content

chore(release): merge v2/main into main for v2.8.0 - #2456

Merged
cliffhall merged 95 commits into
mainfrom
v2/chore/milestone-merge-v2.8.0
Sep 23, 2026
Merged

cliffhall merged 95 commits into
mainfrom
v2/chore/milestone-merge-v2.8.0

Conversation

@cliffhall

@cliffhall cliffhall commented Sep 23, 2026

Copy link
Copy Markdown
Member

Closes #2455

Milestone merge of v2/main into main for the v2.8.0 release — step 2 of the release skill.

This is a pure merge

No commits of its own — the merge commit and nothing else:

$ git rev-list HEAD --not origin/main origin/v2/main
3ad3f72e chore: merge v2/main into main for the v2.8.0 release

$ git rev-parse origin/v2/main^{tree}
3f7322f1d33747ee41ccfc9482b1a2308c31d9cd
$ git rev-parse HEAD^{tree}
3f7322f1d33747ee41ccfc9482b1a2308c31d9cd

The merged tree is byte-identical to origin/v2/main, with no conflicts. Version on the tree: 2.8.0 (bumped on v2/main first in #2453 / PR #2454, per #2010).

Milestone payload

v2.8.0 is complete: 14 contributions closed, plus the bump. Fifteen PRs landed on v2/main since 2.7.0 (#2390#2396, #2398, #2401, #2402, #2444, #2448, #2449, #2452, #2454), one per milestone issue plus the bump. The only issue still open is this merge (#2455).

Verification

Check Result
npm run local:gate (dedicated worktree, full npm install) green, EXIT=0, 4m57s
Root tooling (node --test) 668 passed
Web unit + integration 8,448 passed / 436 files
CLI · TUI · Launcher 388 / 29 · 433 / 30 · 5 / 1
Storybook 527 passed / 123 files
Smokes 11 green (Chromium + Firefox)
npm run pack:verify (its own step; not a gate stage) OK, tarball 1,206,059 B, 23 entries

All 14 of 14 milestone issues were driven from the production build (built launcher, served web dist, CLI and TUI bundles) against real test servers. Highlights:

Full ledger, one row per issue with the output observed: https://claude.ai/artifact/YLGV4sYUwwRwusNNgPZPFF

After merge

Tag origin/main with the bare 2.8.0 (no v prefix) and publish the GitHub Release, which fires publish and publish-github-container-registry.

🤖 Generated with Claude Code

cliffhall and others added 30 commits September 16, 2026 13:12
!!process.env.DANGEROUSLY_OMIT_AUTH read every non-empty string as on, so
=false silently disabled the bearer gate. Reuse the DANGEROUSLY_BIND_ALL_INTERFACES
parser (exported as isEnvFlagEnabled) so both safety flags fail closed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…stream (#2317)

A new suppressNotificationStream server setting answers the Streamable HTTP
transport's standalone GET with a local 405, which the SDK already treats as
'no standalone stream', so traffic stays POST-only. It persists omit-when-off,
is validated by the web backend, reaches createTransportNode on the web, CLI
and TUI paths, and is exposed as a checkbox in Server Settings > Options for
streamable-http servers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
A Zod schema instance reused by two fields is emitted once under $defs and
referenced by a bare $ref with no type, so the web form rendered the second
field as a JSON editor and dropped a plain string typed into it. Inline local
refs once in core and use it in the web form schema, core argument conversion
and the TUI tool form.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
The 2026-07-28 Streamable HTTP transport requires Mcp-Method on every
POSTed message, notifications included, but the SDK derives the standard
headers for requests only. Closing a subscriptions/listen stream — which
every modern resource unsubscribe does — POSTs a notifications/cancelled
without it, and a strict server refuses it with 400.

Wrap the Streamable HTTP fetch so a single JSON-RPC notification carrying
a modern protocol-version _meta claim gains Mcp-Method and
MCP-Protocol-Version, mirroring the SDK's own request rule. Legacy and
unclaimed messages pass through untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…uth-false

fix(web): only DANGEROUSLY_OMIT_AUTH=true/1 disables /api auth
…endencies (#2391 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…round (#2392 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
Neither the non-OK probe's release nor the substituted original's is awaited
any more, so a body cancel that never settles can no longer stall discovery
or keep the caller's abort from reaching it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…etached-body-release

Signed-off-by: cliffhall <cliff@futurescale.com>
…me-header

fix: stamp Mcp-Method on modern-era notification POSTs
…expansion (#2391 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…etached-body-release

fix: detach the OIDC compat's normal-path body releases
…he legacy era (#2394 review)

The transport shares its fetch with OAuth metadata discovery, so matching every
headerless GET would have answered discovery with a synthetic 405. Match only a
GET to the MCP endpoint asking for text/event-stream without Last-Event-ID.
Docs, type comments and the form now say the stream exists only on the legacy
era; the checkbox is hidden for a server pinned to modern.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…eep enumNames (#2391 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…ess-get-stream

Signed-off-by: cliffhall <cliff@futurescale.com>

# Conflicts:
#	core/mcp/node/transport.ts
…e-ref-widgets

fix: resolve local $refs before choosing form widgets (#2321)
…ess-get-stream

feat: per-server setting to suppress the standalone GET notification stream
…2286)

Keep the rule at warning severity (it never fails --strict's exit 6), but
reword its message to acknowledge that providers recommend the array form
for nullable fields, and name the concrete consumer class it is unportable
to instead of an unevidenced 'several MCP clients'.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…t's contract (#2395 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
….json (#2396 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…view)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…#2396 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…on (#2396 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…on (#2396 review)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…-union-caveat

fix(core): reframe the type-union lint as a portability trade
cliffhall and others added 20 commits September 22, 2026 21:08
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
chore: add the project LICENSE and point every manifest at it
…del (#2447)

Read the file-store passphrase from a file named by
MCP_INSPECTOR_SECRET_KEY_FILE, so Docker and Compose secrets can supply
it without putting it in the environment. Both variables set, or a key
file that is missing, unreadable or empty, is a key problem: the store
refuses to read or write rather than falling back to plaintext, and
reports it as "File (unreadable)" with the reason.

docker.md gains a warning that mounting the volume turns on plaintext
file storage unless a key is supplied, with KEY_FILE examples for
docker run and Compose; secret-storage.md gains a threat model for the
file store.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
 review)

A set-but-empty key-file variable is a template that failed to expand,
not a request for plaintext; also strip a lone trailing CR, and assert
both key variables in the caveat and footer tooltip tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
#2447)

A [!WARNING] after the selection table in secret-storage.md, and in the
README and environment-variables.md, for Linux without libsecret,
headless/SSH and Termux, where secrets land in a plaintext file without
the user asking. The fallback and caveat warnings on stderr now end with
a link to the guide.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…#2448 review)

Source comments name MCP_INSPECTOR_SECRET_KEY_FILE and the per-write salt;
the 'both set' conflict is qualified to a non-blank MCP_INSPECTOR_SECRET_KEY;
the Docker example creates the key file 0600 under ~/.config (not in the
project directory) and explains the uid 1000 ownership it needs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
Reading secrets.json as the passphrase and then overwriting it with
ciphertext would change the key under the file on the next start.
Checked by path and by inode, before reading.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…ity-advisory-skill

docs: add the security-advisory skill, and reconcile the two rules it contradicts
gh project item-list truncates silently past --limit, and board #28 now
holds more than the 500 the lookups asked for, so existing cards read as
missing. Issue cards are now looked up from the issue's projectItems,
which is independent of board size. Draft-card lookups and whole-board
dumps (GHSA lookup, snapshot, recovery, triage sweep and audit) use
--limit 2000 and assert .items|length == .totalCount, failing closed on
a truncated listing or a failed gh call.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…t-storage-guide

feat: MCP_INSPECTOR_SECRET_KEY_FILE, and document secret storage for every runtime
…#2452 review)

Clear ITEM_ID before the GHSA lookup so a failed listing cannot leave an
earlier id in place; guard item-edit and item-delete on a non-empty id,
and split the issue-side lookup from the Status edit so the delete
recipe does not inherit it; end every dump guard with false so an
incomplete dump returns non-zero; widen projectItems to first:100.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…2452 review)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
A deleted dump still let the redirect create an empty lost-ids.json, so
the re-apply loop ran zero times and exited 0. lost-ids.json is now
written only inside the completeness check, and step 3 refuses to run
without it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…iew)

The snapshot is the only record of what the orphaned cards held, and an
incomplete one is now deleted, so step 1 drops lost-ids.json when the
snapshot report cannot run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…lookup-limits

docs(skills): stop board lookups from trusting item-list --limit
npm audit --audit-level=high reports 0 vulnerabilities across the root
and all four client installs, so no audit fixes precede the bump.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…-2-8-0

chore: bump version to 2.8.0 (release step 1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Sep 23, 2026
Copilot AI balanced review requested due to automatic review settings September 23, 2026 05:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Private advisory summaries are exposed to broader project-board access, and required release verification evidence is still missing.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 3 Medium severity · 1 Low severity

Open (4)
What changed in this PR

Merges the complete v2.8.0 development tree into the release branch.

Changes:

  • Adds schema-reference handling and Streamable HTTP compatibility controls.
  • Hardens authentication and encrypted secret storage.
  • Updates licensing, documentation, automation skills, and test coverage.
File Description
package.json Bumps v2.8.0 and updates licensing.
package-lock.json Synchronizes release metadata.
LICENSE Adds transitional licensing terms.
README.md Adds security, licensing, and roadmap guidance.
AGENTS.md Updates repository and advisory rules.
scripts/​lib/​claude-cli.mjs Generalizes CLI spawning and probing.
scripts/​lib/​claude-cli.test.mjs Tests generic CLI helpers.
scripts/​skill-eval.mjs Adds Copilot skill evaluation.
scripts/​skill-eval.test.mjs Tests Copilot evaluation behavior.
docs/​secret-storage.md Documents secret-store selection and security.
docs/​docker.md Expands container secret guidance.
docs/​environment-variables.md Documents hardened flags and key files.
docs/​mcp-server-configuration.md Documents new transport setting and interoperability.
docs/​publishing.md Links secret-storage guidance.
docs/​skill-authoring.md Documents Copilot skill measurements.
docs/​v1-to-v2-migration.md Notes stricter auth flag parsing.
docs/​inspector-roadmap-2026-h2.md Adds the six-month roadmap.
core/​json/​localRefs.ts Implements bounded local-reference inlining.
core/​json/​jsonUtils.ts Resolves references before coercion.
core/​json/​schemaLint.ts Clarifies union portability warnings.
core/​mcp/​types.ts Adds notification-stream suppression settings.
core/​mcp/​serverList.ts Persists the new transport setting.
core/​mcp/​remote/​node/​server.ts Validates and normalizes the setting.
core/​mcp/​node/​transport.ts Installs HTTP fetch wrappers.
core/​mcp/​node/​suppressNotificationStreamFetch.ts Suppresses standalone legacy SSE streams.
core/​mcp/​node/​notificationHeadersFetch.ts Stamps modern notification headers.
core/​auth/​secret-storage-info.ts Mentions both encryption-key mechanisms.
core/​auth/​oidcDiscoveryCompat.ts Prevents stalled response cancellation.
core/​auth/​node/​secret-store.ts Documents key-file support.
core/​auth/​node/​secret-store-selection.ts Adds secret-storage guidance links.
core/​auth/​node/​file-secret-store.ts Adds fail-closed key-file loading.
clients/​web/​src/​utils/​jsonUtils.ts Resolves references for web forms.
clients/​web/​server/​web-server-config.ts Parses omit-auth safely.
clients/​web/​server/​resolve-bind-host.ts Shares strict environment-flag parsing.
clients/​web/​src/​components/​groups/​ServerSettingsModal/​ServerSettingsModal.tsx Connects stream suppression to settings.
clients/​web/​src/​components/​groups/​ServerSettingsModal/​ServerSettingsModal.test.tsx Tests modal persistence behavior.
clients/​web/​src/​components/​groups/​ServerSettingsForm/​ServerSettingsForm.tsx Adds the suppression checkbox.
clients/​web/​src/​components/​groups/​ServerSettingsForm/​ServerSettingsForm.test.tsx Tests checkbox behavior and visibility.
clients/​web/​src/​components/​groups/​ServerSettingsForm/​ServerSettingsForm.stories.tsx Updates interactive stories.
clients/​web/​src/​components/​groups/​SchemaForm/​SchemaForm.test.tsx Tests referenced form properties.
clients/​web/​src/​components/​elements/​SecretStorageFooter/​SecretStorageFooter.tsx Updates encryption advice.
clients/​web/​src/​components/​elements/​SecretStorageFooter/​SecretStorageFooter.test.tsx Tests key-file advice.
clients/​web/​src/​test/​core/​localRefs.test.ts Covers reference resolution and bounds.
clients/​web/​src/​test/​core/​jsonUtils.test.ts Tests referenced-value coercion.
clients/​web/​src/​test/​core/​schemaLint.test.ts Tests revised portability warnings.
clients/​web/​src/​test/​core/​mcp/​serverList.test.ts Tests suppression-setting round trips.
clients/​web/​src/​test/​core/​mcp/​node/​suppressNotificationStreamFetch.test.ts Tests request classification.
clients/​web/​src/​test/​core/​mcp/​node/​notificationHeadersFetch.test.ts Tests notification header stamping.
clients/​web/​src/​test/​core/​auth/​secret-storage-info.test.ts Tests encryption guidance.
clients/​web/​src/​test/​core/​auth/​oidcDiscoveryCompat.test.ts Tests non-settling cancellation.
clients/​web/​src/​test/​integration/​server/​web-server-config.test.ts Tests strict auth opt-in values.
clients/​web/​src/​test/​integration/​mcp/​suppress-notification-stream.test.ts Exercises suppression through the SDK.
clients/​web/​src/​test/​integration/​mcp/​remote/​server-extra-coverage.test.ts Tests remote setting validation.
clients/​web/​src/​test/​integration/​mcp/​inspectorClient-subscriptions-era.test.ts Verifies modern notification headers.
clients/​web/​src/​test/​integration/​auth/​node/​secret-store-selection.test.ts Tests guidance warnings.
clients/​web/​src/​test/​integration/​auth/​node/​file-secret-store.test.ts Tests key-file failure modes.
clients/​web/​package.json Updates web licensing metadata.
clients/​web/​package-lock.json Synchronizes web licensing metadata.
clients/​tui/​src/​components/​ToolTestModal.tsx Resolves references for TUI forms.
clients/​tui/​__tests__/​ToolTestModal.test.tsx Tests referenced union validation.
clients/​tui/​package.json Updates TUI licensing metadata.
clients/​tui/​package-lock.json Synchronizes TUI licensing metadata.
clients/​cli/​package.json Updates CLI licensing metadata.
clients/​cli/​package-lock.json Synchronizes CLI licensing metadata.
clients/​launcher/​package.json Updates launcher licensing metadata.
clients/​launcher/​package-lock.json Synchronizes launcher licensing metadata.
.claude/​skills/​testing/​SKILL.md Strengthens test-server handoff guidance.
.claude/​skills/​security-advisory/​SKILL.md Adds the private-advisory procedure.
.claude/​skills/​security-advisory/​evals/​evals.json Adds advisory-skill trigger cases.
.claude/​skills/​issue-triage/​SKILL.md Hardens board audits and advisory handling.
.claude/​skills/​issue-create/​SKILL.md Documents the advisory exception.
.claude/​skills/​board-ops/​SKILL.md Hardens project-card lookup procedures.
Files not reviewed (4)
  • clients/cli/package-lock.json: Generated file
  • clients/launcher/package-lock.json: Generated file
  • clients/tui/package-lock.json: Generated file
  • clients/web/package-lock.json: Generated file

Comment thread .claude/skills/board-ops/SKILL.md
Comment thread .claude/skills/security-advisory/SKILL.md
Comment thread AGENTS.md
Comment thread package.json
@cliffhall

Copy link
Copy Markdown
Member Author

Correction to the round-1 summary: the advisory-title finding is declined, not deferred. #2457 is closed as not planned. Board #28's audience can already see the repo's Security Advisories, so the title leaks nothing. No findings from round 1 remain open.

@cliffhall
cliffhall merged commit 1e31c78 into main Sep 23, 2026
8 checks passed
@cliffhall
cliffhall deleted the v2/chore/milestone-merge-v2.8.0 branch September 23, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Release 2.8.0 step 2: merge v2/main into main and cut the release

2 participants