Merge branch 'v2/main' into v2/fix/2096-stdio-env-cwd-revert

This commit is contained in:
Cliff Hall 2026-08-25 08:55:35 -04:00 • committed by GitHub
commit 6af849e217
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1391,6 +1391,7 @@ export function createRemoteApp(
authorizationUrl?: string;
tokenUrl?: string;
enterpriseManaged?: boolean;
requestRefreshToken?: boolean;
} => {
if (v === null || typeof v !== "object" || Array.isArray(v)) return false;
const o = v as Record<string, unknown>;
@ -1418,6 +1419,14 @@ export function createRemoteApp(
) {
return false;
}
// #2068 — shape only; the read side keeps just an explicit `false`, so a
// stray `true` from a hand-edited file reads back as the default anyway.
if (
o.requestRefreshToken !== undefined &&
typeof o.requestRefreshToken !== "boolean"
) {
return false;
}
return true;
};
// A roots array: each entry must have a string `uri` and, when present, a
@ -1531,7 +1540,7 @@ export function createRemoteApp(
if ("oauth" in valObj && !isOauthObject(valObj.oauth)) {
logWarn(
{ route: "/api/servers", id, droppedKey: "oauth" },
"Dropping malformed `oauth` field — expected `{ clientId?, clientSecret?, scopes?, authorizationParams?, authorizationUrl?, tokenUrl?, enterpriseManaged?, onInsufficientScope? }`.",
"Dropping malformed `oauth` field — expected `{ clientId?, clientSecret?, scopes?, authorizationParams?, authorizationUrl?, tokenUrl?, enterpriseManaged?, onInsufficientScope?, requestRefreshToken? }`.",
);
delete valObj.oauth;
}
@ -1834,6 +1843,15 @@ export function createRemoteApp(
error: "settings.enterpriseManaged must be a boolean",
};
}
if (
obj.oauthRequestRefreshToken !== undefined &&
typeof obj.oauthRequestRefreshToken !== "boolean"
) {
return {
ok: false,
error: "settings.oauthRequestRefreshToken must be a boolean",
};
}
if (
obj.oauthOnInsufficientScope !== undefined &&
obj.oauthOnInsufficientScope !== "reauthorize" &&
@ -1961,6 +1979,11 @@ export function createRemoteApp(
if (obj.enterpriseManaged === true) {
value.enterpriseManaged = true;
}
// #2068: the default is on, so only the explicit opt-out is carried; a
// `true` on the wire reads back as unset, which means the same thing.
if (obj.oauthRequestRefreshToken === false) {
value.oauthRequestRefreshToken = false;
}
if (
obj.oauthOnInsufficientScope === "reauthorize" ||
obj.oauthOnInsufficientScope === "throw"