Skip to content

Release 2.0.13: merge main into release#618

Merged
corinagum merged 18 commits into
releasefrom
prep-release/2.0.13
Jun 15, 2026
Merged

Release 2.0.13: merge main into release#618
corinagum merged 18 commits into
releasefrom
prep-release/2.0.13

Conversation

@corinagum

Copy link
Copy Markdown
Collaborator

Release 2.0.13

Merges main into release for stable publish.

Notable changes since 2.0.12

Release steps

  1. Merge this PR
  2. Trigger the release pipeline for release branch with Public publish type
  3. Bump version on main to 2.0.14-preview.{height}
  4. Create git tag and GitHub Release page

corinagum and others added 18 commits May 28, 2026 10:34
## Summary

Post-2.0.12 housekeeping on main.

- `version.json`: `2.0.12-preview.{height}` → `2.0.13-preview.{height}`
— preview builds off main start fresh height counters after the 2.0.12
stable cut. Mirrors PR #577.
- `RELEASE.md`: adds **step 5** to "Creating a Release" covering the git
tag + GitHub Release page step, including the date-based `gh api` query
that surfaces the real PR delta from main (auto-generated notes against
the squash-merged release branch only show the release PR itself).

## Test plan

- [x] `cat version.json` shows `2.0.13-preview.{height}`
- [x] RELEASE.md renders cleanly in preview

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary

- Adds `merge_group:` to the `on:` triggers of
`.github/workflows/build-test-lint.yml` so the workflow runs on
`gh-readonly-queue/*` refs created by GitHub's merge queue.
- No behavior change until a merge queue is enabled on the `main`
ruleset; the trigger is dormant otherwise.
- Prereq for turning on "Require merge queue" — without this, the
required `Build & Test & Lint (24.x)` check would never report on queued
PRs and the queue would stall.

## Test plan

- [ ] Confirm CI still runs as expected on this PR (pull_request trigger
unchanged)
- [ ] After merge, enable "Require merge queue" on the `main` ruleset
and verify the workflow fires against the queue's temporary refs

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary
- Make Activity.addEntity/addEntities merge root schema.org Message
entities instead of blindly appending them
- Keep AI-generated labels and citations on one root message entity
- Add regression coverage in the Activity tests

## Why this matters
- This shows up when a message is assembled in pieces, like streaming a
response or combining multiple helpers that each add root Message
metadata
- Before this change, those pieces could leave you with multiple root
Message entities on the same activity, which Teams doesn’t love
- In practice that means features like AI-generated markers and
citations could get split across duplicate root entities

## Test plan
- cd packages/api && npx jest --runInBand
src/activities/activity.spec.ts
- cd packages/apps && npx jest --runInBand src/http/http-stream.spec.ts

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
## Summary
- Bumps `@azure/msal-node` in `@microsoft/teams.apps` to v5.2.2.
- Updates the token manager test mock for MSAL's `fromNativeBroker` ->
`fromPlatformBroker` rename.

## Why
- Gets our direct MSAL dependency onto the current v5 line and removes
the direct vulnerable `uuid` dependency path from
`@microsoft/teams.apps`.

## Interesting bits
- I left BotBuilder alone, so `npm audit` still reports the existing
BotBuilder/Restify transitive stuff. No spicy force-downgrades today.

## Testing
Tested using User Managed Identity, FIC (UMI) and FIC system, and
ofcourse secrets.
This pull request makes significant improvements to the Teams MCP server
example, focusing on enabling multiple simultaneous "ask" requests per
user, adding a user search tool via Microsoft Graph, and updating the
documentation and code to reflect these enhancements.
**Key changes include:**

### 1. Enhanced Ask/Reply Flow
- Replaces the previous "one ask per user" model with support for
multiple concurrent asks by using Adaptive Cards with embedded request
IDs and a new `card.action.ask_reply` handler. This enables tracking
replies to individual asks and allows multiple pending questions per
user.

### 2. User Search via Microsoft Graph
- Adds a new `find_user` tool that searches for users by name, email, or
UPN using Microsoft Graph, and returns up to 5 Azure AD object IDs. This
is implemented in a new `graphClient.ts` file and documented in the
README.

### 3. Documentation and Developer Experience
- Updates the README to reflect new tool names, parameters, and usage
patterns, including detailed instructions for setting up Graph API
permissions and clarifying the meaning of `userId` as the AAD object id.

### 4. Package and Dependency Updates
- Adds new dependencies for Microsoft Graph support in `package.json`.
(`examples/mcp-server/package.json`)

These changes collectively make the MCP server example more robust,
flexible, and easier to use in real-world scenarios.

AI-MCP Example
- Add AI generated label to card responses as well
Bumps
[react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)
from 7.13.1 to 7.15.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/releases">react-router's
releases</a>.</em></p>
<blockquote>
<h2>v7.15.0</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7150">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7150</a></p>
<h2>v7.14.2</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7142">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7142</a></p>
<h2>v7.14.1</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7141">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7141</a></p>
<h2>v7.14.0</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7140">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7140</a></p>
<h2>v7.13.2</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7132">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7132</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md">react-router's
changelog</a>.</em></p>
<blockquote>
<h2>v7.15.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p>Stabilize <code>unstable_defaultShouldRevalidate</code> as
<code>defaultShouldRevalidate</code> on <code>&lt;Link&gt;</code>,
<code>&lt;Form&gt;</code>, <code>useLinkClickHandler</code>,
<code>useSubmit</code>, <code>fetcher.submit</code>, and
<code>setSearchParams</code> (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Stabilize the instrumentation APIs.
<code>unstable_instrumentations</code> is now
<code>instrumentations</code> and <code>unstable_pattern</code> is now
<code>pattern</code> (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>The <code>unstable_ServerInstrumentation</code>,
<code>unstable_ClientInstrumentation</code>,
<code>unstable_InstrumentRequestHandlerFunction</code>,
<code>unstable_InstrumentRouterFunction</code>,
<code>unstable_InstrumentRouteFunction</code>, and
<code>unstable_InstrumentationHandlerResult</code> types have had their
<code>unstable_</code> prefixes removed</li>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Stabilize <code>unstable_mask</code> as <code>mask</code> on
<code>&lt;Link&gt;</code>, <code>useLinkClickHandler</code>, and
<code>useNavigate</code>, and rename the corresponding
<code>Location.unstable_mask</code> field to <code>Location.mask</code>
(<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Stabilize the <code>unstable_normalizePath</code> option on
<code>staticHandler.query</code> and
<code>staticHandler.queryRoute</code> as <code>normalizePath</code> (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Stabilize <code>future.unstable_passThroughRequests</code> as
<code>future.v8_passThroughRequests</code> (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Remove <code>unstable_subResourceIntegrity</code> from the runtime
<code>FutureConfig</code> type; the flag is now controlled by the
top-level <code>subResourceIntegrity</code> option in
<code>react-router.config.ts</code> (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Stabilize <code>unstable_url</code> as <code>url</code> on
<code>loader</code>, <code>action</code>, and <code>middleware</code>
function args (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
<li>
<p>Stabilize <code>unstable_useTransitions</code> as
<code>useTransitions</code> on <code>&lt;BrowserRouter&gt;</code>,
<code>&lt;HashRouter&gt;</code>, <code>&lt;HistoryRouter&gt;</code>,
<code>&lt;MemoryRouter&gt;</code>, <code>&lt;Router&gt;</code>,
<code>&lt;RouterProvider&gt;</code>,
<code>&lt;HydratedRouter&gt;</code>, and
<code>useLinkClickHandler</code> (<a
href="https://github.com/remix-run/react-router/commit/a993f09">a993f09</a>)</p>
<ul>
<li>⚠️ This is a breaking change if you have already opted into the
unstable version - you will need to update your code accordingly</li>
</ul>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Add <code>nonce</code> to <code>&lt;Scripts&gt;</code> <code>&lt;link
rel=&quot;modulepreload&quot;&gt;</code> elements (if provided) (<a
href="https://github.com/remix-run/react-router/commit/af5d49b">af5d49b</a>)</p>
</li>
<li>
<p>Fix a bug with <code>unstable_defaultShouldRevalidate={false}</code>
where parent routes that did not export a <code>shouldRevalidate</code>
function could be incorrectly included in the single fetch call for new
child route data (<a
href="https://redirect.github.com/remix-run/react-router/pull/15012">#15012</a>)</p>
</li>
<li>
<p>Improve server-side route matching performance by pre-computing
flattened/cached route branches (<a
href="https://redirect.github.com/remix-run/react-router/pull/14967">#14967</a>)
(<a
href="https://github.com/remix-run/react-router/commit/af5d49b">af5d49b</a>)</p>
<ul>
<li>Performance benchmarks showed roughly a 10-15% improvement in
server-side request handling performance</li>
</ul>
</li>
<li>
<p>Mark <code>mask</code> as an optional field in <code>Location</code>
for easier mocking in unit tests (<a
href="https://redirect.github.com/remix-run/react-router/pull/14999">#14999</a>)</p>
</li>
<li>
<p>Cache flattened/ranked route branches to optimize server-side route
matching (<a
href="https://redirect.github.com/remix-run/react-router/pull/14967">#14967</a>)</p>
</li>
<li>
<p>Improve route matching performance in Framework/Data Mode (<a
href="https://redirect.github.com/remix-run/react-router/pull/14971">#14971</a>)
(<a
href="https://github.com/remix-run/react-router/commit/af5d49b">af5d49b</a>)</p>
<ul>
<li>Avoiding unnecessary calls to <code>matchRoutes</code> in data
router scenarios
<ul>
<li>This includes adding back the optimization that was removed in
<code>7.6.0</code> (<a
href="https://redirect.github.com/remix-run/react-router/pull/13562">#13562</a>)</li>
<li>The issues that prompted the revert have been addressed by using the
available router <code>matches</code> but always updating
<code>match.route</code> to the latest route in the
<code>manifest</code></li>
</ul>
</li>
<li>Leverage pre-computed pre-computing flattened/cached route branches
during client side route matching</li>
<li>Performance benchmarks showed roughly a 15-30% improvement in
server-side request handling performance</li>
</ul>
</li>
</ul>
<h2>v7.14.2</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/remix-run/react-router/commit/97c8de79c38f107acd15f74d8295c7bf75894a5d"><code>97c8de7</code></a>
Release v7.15.0 (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/15018">#15018</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/af5d49b71c15fa502cb0918482597284e8cb39c4"><code>af5d49b</code></a>
Update change files again</li>
<li><a
href="https://github.com/remix-run/react-router/commit/a993f09533fa15bbf01ce734c8c7c116564cf4b7"><code>a993f09</code></a>
Update change files</li>
<li><a
href="https://github.com/remix-run/react-router/commit/362635b8fdf020afdf697823ca71ba4c01b40e0d"><code>362635b</code></a>
Move chnageset to change file</li>
<li><a
href="https://github.com/remix-run/react-router/commit/e756132b5bcae52b65c504bdac8cec406c746e62"><code>e756132</code></a>
chore: format</li>
<li><a
href="https://github.com/remix-run/react-router/commit/49295b5c220b567cff9934ddf0199877663b552c"><code>49295b5</code></a>
Stabilize APIs (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14999">#14999</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/5f61543c31c442271162b31ee9fe1499e170c68c"><code>5f61543</code></a>
Client-side route matching optimizations (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14971">#14971</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/67518cb61054f1b3eede95dde95480aca962626d"><code>67518cb</code></a>
Remove unnecessary hasShouldRevalidate condition for opting out (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/15012">#15012</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/6f18edde6b5eac5f7028bfde885bbb8031025480"><code>6f18edd</code></a>
Add nonce to scripts <code>modulepreload</code> (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/15002">#15002</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/10a968671d94a1147d78e766cffae33c6d151162"><code>10a9686</code></a>
Migrate changeset to change file</li>
<li>Additional commits viewable in <a
href="https://github.com/remix-run/react-router/commits/[email protected]/packages/react-router">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-router&package-manager=npm_and_yarn&previous-version=7.13.1&new-version=7.15.0)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/microsoft/teams.ts/network/alerts).

</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…sence (#579)

While following the citations example
(https://microsoft.github.io/teams-sdk/typescript/in-depth-guides/ai/best-practices)
(which calls addCitation without text), I encountered a BadSyntax error:
citation.appearance.text and citation.appearance.encodingFormat must
either both be empty or both have values. This happens because
encodingFormat was unconditionally set to
'application/vnd.microsoft.card.adaptive', even when text was omitted

## Summary

Fixes `BadSyntax` error when `addCitation` is called without `text`.

## Problem

Calling `addCitation(position, appearance)` without `appearance.text`
causes a 400 error:

```
code: "BadSyntax"
message: "Error while parsing citation entity with id: x"
Detail: "citation.appearance.text and citation.appearance.encodingFormat must either both be empty or both have values"
```

The root cause: `encodingFormat` was hardcoded to
`'application/vnd.microsoft.card.adaptive'` unconditionally, but the
Teams API requires it to be absent when `text` is absent.

## Fix

Changed `encodingFormat` to be set only when `appearance.text` is
truthy:

```ts
encodingFormat: appearance.text ? 'application/vnd.microsoft.card.adaptive' : undefined,
```
Bumps [hono](https://github.com/honojs/hono) from 4.12.18 to 4.12.21.
<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.12.21</h2>
<h2>Security fixes</h2>
<p>This release includes fixes for the following security issues:</p>
<h3>app.mount() strips mount prefix using undecoded path, causing
incorrect routing for percent-encoded paths</h3>
<p>Affects: <code>app.mount()</code>. Fixes prefix stripping using the
raw URL pathname instead of the decoded path, where percent-encoded
characters in the mount prefix or path could cause the prefix to be
removed at the wrong position, resulting in the sub-application
receiving an incorrect path. GHSA-2gcr-mfcq-wcc3</p>
<h3>IP Restriction bypasses static deny rules for non-canonical
IPv6</h3>
<p>Affects: <code>hono/ip-restriction</code>. Fixes IP address
comparison using string equality, where non-canonical IPv6
representations of a denied address — such as compressed forms or
hex-notation IPv4-mapped addresses — could bypass static deny rules.
GHSA-xrhx-7g5j-rcj5</p>
<h3>Cookie helper does not sanitize sameSite and priority, allowing
Set-Cookie injection</h3>
<p>Affects: <code>hono/cookie</code>. Fixes missing validation of
<code>sameSite</code> and <code>priority</code> options against
injection characters (<code>;</code>, <code>\r</code>, <code>\n</code>),
where user-controlled input passed to either option could inject
additional attributes into the Set-Cookie response header.
GHSA-3hrh-pfw6-9m5x</p>
<h3>JWT middleware accepts any Authorization scheme, not only
Bearer</h3>
<p>Affects: <code>hono/jwt</code>, <code>hono/jwk</code>. Fixes missing
scheme validation in the Authorization header, where any two-part header
value was accepted regardless of the scheme name, allowing non-Bearer
schemes to pass JWT authentication. GHSA-f577-qrjj-4474</p>
<hr />
<p>Users who use <code>app.mount()</code>,
<code>hono/ip-restriction</code>, <code>hono/cookie</code>, or
<code>hono/jwt</code>/<code>hono/jwk</code> are encouraged to upgrade to
this version.</p>
<h2>v4.12.20</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(route): preserve the base path of the mounted route() app by <a
href="https://github.com/usualoma"><code>@​usualoma</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4942">honojs/hono#4942</a></li>
<li>fix(jsx): widen jsx and jsxFn children to Child[] by <a
href="https://github.com/ashunar0"><code>@​ashunar0</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4947">honojs/hono#4947</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/ashunar0"><code>@​ashunar0</code></a>
made their first contribution in <a
href="https://redirect.github.com/honojs/hono/pull/4947">honojs/hono#4947</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/honojs/hono/compare/v4.12.19...v4.12.20">https://github.com/honojs/hono/compare/v4.12.19...v4.12.20</a></p>
<h2>v4.12.19</h2>
<h2>What's Changed</h2>
<ul>
<li>ci: pin GitHub Actions to SHAs by <a
href="https://github.com/yusukebe"><code>@​yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4932">honojs/hono#4932</a></li>
<li>fix(serveStatic): make options parameter optional in all adapters by
<a href="https://github.com/mixelburg"><code>@​mixelburg</code></a> in
<a
href="https://redirect.github.com/honojs/hono/pull/4934">honojs/hono#4934</a></li>
<li>fix(cookie): return the first cookie when there are multiple cookies
with the same name by <a
href="https://github.com/usualoma"><code>@​usualoma</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4922">honojs/hono#4922</a></li>
<li>feat(bearer-auth): make bearerAuth generic for typed context in
verifyToken by <a
href="https://github.com/justinnais"><code>@​justinnais</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4913">honojs/hono#4913</a></li>
<li>feat(cache): key cache entries by configured vary headers by <a
href="https://github.com/usualoma"><code>@​usualoma</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4915">honojs/hono#4915</a></li>
<li>feat(request): add <code>bytes()</code> by <a
href="https://github.com/yusukebe"><code>@​yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4921">honojs/hono#4921</a></li>
<li>fix(stream): upgrade <code>@hono/node-server</code> to v2 and fix
abort handling by <a
href="https://github.com/yusukebe"><code>@​yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4940">honojs/hono#4940</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/justinnais"><code>@​justinnais</code></a> made
their first contribution in <a
href="https://redirect.github.com/honojs/hono/pull/4913">honojs/hono#4913</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/honojs/hono/compare/v4.12.18...v4.12.19">https://github.com/honojs/hono/compare/v4.12.18...v4.12.19</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/honojs/hono/commit/a83ddb882e0c0b8c336050dba087bb2e1b12488e"><code>a83ddb8</code></a>
4.12.21</li>
<li><a
href="https://github.com/honojs/hono/commit/6cbb025ff87fca1a3d00d0ccca0eaf3a6385c3f1"><code>6cbb025</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/honojs/hono/commit/c831020fb1fa2e929d222f6c84e1abfe013e512b"><code>c831020</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/honojs/hono/commit/905aedbc20661e0e2fa378783a7ec44a5c3df43d"><code>905aedb</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/honojs/hono/commit/5463db2735476959b8af67756f4e513f4fe19115"><code>5463db2</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/honojs/hono/commit/c657a39ccc8d3194d345d9e82c8587bd25b5b6e8"><code>c657a39</code></a>
4.12.20</li>
<li><a
href="https://github.com/honojs/hono/commit/eb2d0c238adbcee5933d0f8c15f1a65a88f50565"><code>eb2d0c2</code></a>
fix(jsx): widen jsx and jsxFn children to Child[] (<a
href="https://redirect.github.com/honojs/hono/issues/4947">#4947</a>)</li>
<li><a
href="https://github.com/honojs/hono/commit/dcabbece347817ef7193439c39d28546b8ac3a85"><code>dcabbec</code></a>
fix(route): preserve the base path of the mounted route() app (<a
href="https://redirect.github.com/honojs/hono/issues/4942">#4942</a>)</li>
<li><a
href="https://github.com/honojs/hono/commit/7e62bcd22fa4e8f0e83cb564bac85e32f5434dd3"><code>7e62bcd</code></a>
4.12.19</li>
<li><a
href="https://github.com/honojs/hono/commit/e2f252a8745eb25f06485b8d43e8410bf027c8ef"><code>e2f252a</code></a>
fix(stream): upgrade <code>@hono/node-server</code> to v2 and fix abort
handling (<a
href="https://redirect.github.com/honojs/hono/issues/4940">#4940</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/honojs/hono/compare/v4.12.18...v4.12.21">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hono&package-manager=npm_and_yarn&previous-version=4.12.18&new-version=4.12.21)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/microsoft/teams.ts/network/alerts).

</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
If a server is set up without any credentials, it currently will not be
able to _send_ messages, but it _will_ currently accept all incoming
requests.
This scenario is rare, but possible, and in this PR we reject any
incoming requests if creds are not setup (and if `skipAuth` isn't
explicitly set to true)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Corina Gum <[email protected]>
## Summary
- Refresh the `@microsoft/teams.apps` README so it works better as the
npm landing page.

## Why
- This is the main package people land on, so the README should quickly
explain what it is and show the happy path.

## Interesting bits
- Adds a tiny hello agent snippet.
- Adds a simple existing-server example using `ExpressAdapter`.
- Points folks to the TypeScript docs and examples folder without
overdoing it.

## Testing
- Docs-only change; reviewed the rendered markdown content locally.
Adds a scheduled ADO pipeline (`.azdo/sdl.yml`) using the
`1ES.Official.PipelineTemplate` that runs weekly on `main`.

**Why:** The publish pipeline is manually triggered and cannot guarantee
CodeQL/CredScan run regularly on the default branch. This pipeline
ensures continuous SDL compliance independent of release cadence.

**How it works:** The 1ES Official template auto-injects CodeQL 3000 and
CredScan in the SDL Sources stage. For interpreted languages, scanning
is automatic based on file detection — no build step is needed.

**Schedule:** Mondays at 08:00 UTC (`always: true` ensures it runs even
without code changes).

**Note:** After merging, a pipeline definition must be created in ADO
(DomoreexpGithub/Github_Pipelines) pointing to this YAML file for the
schedule to activate.

**Related:**
- microsoft/teams.py#366
- #607
- microsoft/teams.py#449 (PY counterpart)

Co-authored-by: Copilot <[email protected]>
…607)

Switch the publish pipeline from `1ES.Unofficial.PipelineTemplate` to
`1ES.Official.PipelineTemplate`.

The Official template auto-injects CodeQL 3000 and CredScan on
default-branch runs, which is required for SFI-PS2.1 (Continuous SDL)
compliance.

This is the same one-line change made to teams.py in
microsoft/teams.py#366.

Co-authored-by: Copilot <[email protected]>
Cache the MSAL confidential client used by federated identity
credentials.

Why:
Recreating it on every token request means MSAL never gets to use its
internal token cache. Reusing it avoids extra token exchanges and makes
the FIC path less chatty.

Interesting bits:
The managed identity token is now provided through MSAL's lazy
clientAssertion callback, so we only fetch the exchange token when MSAL
actually needs it.

Reviewer tips:
Start in packages/apps/src/token-manager.ts. The important bit is the
FIC client cache and callback assertion.

Testing:
- Manual VM test of the FIC token flow

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Removing the manifest concept from `@microsoft/teams.apps`.

Why:
The Teams app manifest is deployment/configuration metadata, not runtime
state. The server does not need the manifest to exist when it runs, and
in some setups it may not exist at runtime at all.

`teams.apps` currently assumes manifest data can be passed into the
runtime, stored on `App`, mutated by `tab()`/`configTab()`, and used for
proactive bot identity. That couples runtime behavior to one specific
configuration mechanism. If someone configures or packages their app
another way, those runtime dependencies are weird and not very useful.
Additionally, we are not promoting keeping manifests in `appPackage/`
now either (the new CLI doesn't promote it for eg).

It also does not buy us much right now:
- `app.manifest` synthesizes metadata, but nothing in the runtime
depends on it.
- `tab()`'s useful runtime behavior is serving static files; the
manifest mutation is packaging metadata.
- `configTab()` only mutates manifest metadata.
- `app.name` only reads `manifest.name.full` to set proactive
`bot.name`, but bot name is not required.

Interesting bits:
- Removed `manifest`, `_manifest`, and `name` from `App`.
- `tab()` now matches teams.py behavior: it just hosts static content.
- Removed `configTab()` since it only existed to mutate manifest
metadata.
- Dropped generated manifest types/schema from the apps package.
- Made `Account.name` optional because proactive bot references don't
need to invent a name.
- Devtools falls back to `App` when rendering unnamed senders.

Tips for reviewers:
Start with `packages/apps/src/app.ts` and
`packages/apps/src/app.embed.ts`. The giant deletions are generated
manifest types/schema.

Testing:
- `npm run build --workspace @microsoft/teams.api`
- `npm test --workspace @microsoft/teams.apps`
- `npm run clean --workspace @microsoft/teams.apps && npm run build
--workspace @microsoft/teams.apps`
- `npm run build --workspace @microsoft/teams.devtools`
## Summary

Mark all deprecated packages as `private: true` so they are excluded
from `npm pack` during publish runs. Also adds a `deprecated` field
check in the publish pipeline as a secondary safeguard.

### Packages affected
- `@microsoft/teams.ai`
- `@microsoft/teams.openai`
- `@microsoft/teams.dev`
- `@microsoft/teams.mcp`
- `@microsoft/teams.mcpclient`
- `@microsoft/teams.a2a`

### Changes
1. Added `"private": true` to each deprecated package's `package.json`
2. Added `"deprecated"` field to `@microsoft/teams.dev` (was missing)
3. Updated `.azdo/publish.yml` to skip packages with a `deprecated`
field

### Note
All packages except `@microsoft/teams.dev` are already marked deprecated
on npm. `teams.dev` needs an org admin to run `npm deprecate`.

Co-authored-by: Copilot <[email protected]>
Make BotBuilder an HTTP server adapter instead of an App plugin.

Why: BotBuilder participates at the inbound HTTP layer. Modeling it as
an adapter keeps App plugin DI cleaner and lets Core/App treat
BotBuilder as host integration rather than a privileged plugin that
reaches back into the server. This also allows us to clean up our plugin
DI that is unnecessarily fairly privileged (eg. why do plugins get
access to creds, tokens etc). Doing this allows us to then move toward a
more layered architecture (similar to .net), where the "core" layer will
be the only "more" priviledged layer (with creds, tokens etc), instead
of this information being passed around everywhere.

Migration path:
```ts
// Before
new App({
  plugins: [new BotBuilderPlugin({ handler })],
});

// After
new App({
  httpServerAdapter: new BotBuilderAdapter({ handler }),
});
```

If you already construct a BotBuilder CloudAdapter:
```ts
new App({
  httpServerAdapter: new BotBuilderAdapter({ cloudAdapter, handler }),
});
```

If no cloudAdapter is supplied, BotBuilderAdapter constructs one from
explicit credentials, MicrosoftApp* environment variables, or the same
CLIENT_ID / CLIENT_SECRET / TENANT_ID env vars used by teams.apps.

Interesting bits:
- Adds BotBuilderAdapter implementing IHttpServerAdapter.
- Removes BotBuilderPlugin and its DI dependencies.
- Cleans up now-unused App plugin DI entries for raw tokens, raw client,
metadata, and credentials.

Reviewer tips:
- Start with packages/botbuilder/src/adapter.ts.
- The key thing to check is whether the adapter wrapper preserves the
previous BotBuilder flow before forwarding to the Teams handler.

Testing:

<img width="1037" height="646" alt="image"
src="https://github.com/user-attachments/assets/939f8eb4-8d9e-4f2c-8624-f2020e8f84d8"
/>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
…ility (#616)

## Summary

Fixes #612 — Token acquisition fails on Teams Desktop but works on Teams
Web.

## Problem

On Teams Desktop, the OneAuth/WAM broker (via Nested App Auth) cannot
resolve the `.default` scope for Graph token requests the way browser
MSAL does. The graph client in `@microsoft/teams.client` hardcoded `{
scopes: ['.default'] }`, which caused `ApiContractViolation` errors
("declined scopes") on Desktop.

Additionally, the MSAL config had `authority: ''` (overriding MSAL's
sensible default) and did not set `supportsNestedAppAuth: true`.

## Fix

- **`graph-utils.ts`**: Accept explicit scopes via a `getGraphScopes()`
parameter instead of hardcoding `.default`. Logs a warning when falling
back to `.default` to aid discoverability.
- **`app.ts`**: Pass the developer's `prewarmScopes` through to the
graph client so Graph calls use explicit scopes.
- **`msal-utils.ts`**: Remove empty `authority` override (let MSAL use
its default `common`), add `supportsNestedAppAuth: true`, and handle
`ApiContractViolation` errors from the Desktop broker as
interaction-required (triggers popup fallback).

## Testing

- Reproduced the original failure on Teams Desktop (Mac) with the tab
example
- Confirmed the fix resolves the issue — Graph calls (`/me`) succeed on
Desktop
- All 41 unit tests pass with 100% coverage on `msal-utils.ts` and
`graph-utils.ts`
- Lint clean

## Notes for reviewers

- The `.default` scope still works on Web, so this is backward
compatible. If `prewarmScopes` is not set, the graph client falls back
to `.default` with a warning.
- Developers targeting Desktop **must** set explicit scopes in
`msalOptions.prewarmScopes`.
@corinagum
corinagum merged commit 85cca75 into release Jun 15, 2026
4 checks passed
@corinagum
corinagum deleted the prep-release/2.0.13 branch June 15, 2026 20:30
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.

4 participants