@serviceme/devtools-shared 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1098,11 +1098,11 @@ export interface CopilotCustomizationViewPayload {
1098
1098
  * server (verifier).
1099
1099
  *
1100
1100
  * Single source of truth for the `x-ms-device-*` header names and the
1101
- * HMAC-SHA-256 request-signature algorithm. Previously the same
1102
- * constants + function were copy-pasted in three places
1103
- * (extension `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`,
1104
- * server `lib/auth/device-signature-guard.ts`) and kept in sync by
1105
- * comments alone. Server and extension now import from here.
1101
+ * request-signature algorithms. Previously the same constants +
1102
+ * functions were copy-pasted in three places (extension
1103
+ * `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`, server
1104
+ * `lib/auth/device-signature-guard.ts`) and kept in sync by comments
1105
+ * alone. Server and extension now import from here.
1106
1106
  *
1107
1107
  * NOTE: `packages/serviceme-core/src/device/deviceAuth.ts` keeps its own
1108
1108
  * copy — ADL-003 forbids core → shared (and shared → core) so the core
@@ -1117,7 +1117,15 @@ export declare const DeviceAuthHeaders: {
1117
1117
  readonly signature: "x-ms-device-signature";
1118
1118
  readonly timestamp: "x-ms-device-timestamp";
1119
1119
  readonly secretVersion: "x-ms-device-secret-version";
1120
+ /** v2 only — algorithm self-declaration so the server can verify
1121
+ * both schemes during the legacy-client rollout window. */
1122
+ readonly sigAlg: "x-ms-device-sig-alg";
1123
+ /** v2 only — one-time value folded into the signature basis and
1124
+ * checked against a server-side replay cache. */
1125
+ readonly nonce: "x-ms-device-nonce";
1120
1126
  };
1127
+ /** v2 signature algorithm identifier carried in `x-ms-device-sig-alg`. */
1128
+ export declare const DEVICE_SIG_ALG_V2 = "hmac-sha256-v2";
1121
1129
  export interface DeviceRequestSignatureParams {
1122
1130
  method: string;
1123
1131
  path: string;
@@ -1126,8 +1134,12 @@ export interface DeviceRequestSignatureParams {
1126
1134
  secret: string;
1127
1135
  }
1128
1136
  /**
1129
- * Basis is `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET` (LF-joined, NOT JSON).
1130
- * Output is lowercase hex SHA-256.
1137
+ * Legacy (v1) basis: `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET`
1138
+ * (LF-joined, NOT JSON), hashed with a secret-suffix SHA-256.
1139
+ * Output is lowercase hex.
1140
+ *
1141
+ * Retained for backward compatibility with fielded extensions that
1142
+ * predate v2; new code should use `createDeviceRequestSignatureV2`.
1131
1143
  *
1132
1144
  * Uses `js-sha256` (pure JS, synchronous, browser + Node) instead of
1133
1145
  * `node:crypto` so this module stays importable from the webview (the
@@ -1135,6 +1147,30 @@ export interface DeviceRequestSignatureParams {
1135
1147
  * the vite/rollup build).
1136
1148
  */
1137
1149
  export declare function createDeviceRequestSignature(params: DeviceRequestSignatureParams): string;
1150
+ export interface DeviceRequestSignatureV2Params {
1151
+ method: string;
1152
+ /** Full request path INCLUDING the query string (e.g.
1153
+ * `/api/v1/tools/rtk/download?version=1.2.0&target=darwin-arm64`).
1154
+ * v2 signs the query so GET parameters cannot be substituted or
1155
+ * replayed independently of the signed basis. */
1156
+ path: string;
1157
+ timestamp: number;
1158
+ /** One-time value; the server tracks seen nonces per device and
1159
+ * rejects replays within the timestamp window. */
1160
+ nonce: string;
1161
+ body: string;
1162
+ secret: string;
1163
+ }
1164
+ /**
1165
+ * v2 basis: `METHOD\nPATH?QUERY\nTIMESTAMP\nNONCE\nBODY\nSECRET`
1166
+ * (LF-joined, NOT JSON), MACed with real HMAC-SHA-256 keyed by the
1167
+ * device secret. Output is lowercase hex.
1168
+ *
1169
+ * The client MUST build the exact query string it will send before
1170
+ * signing — the server verifies against the raw `request.url` search,
1171
+ * so the signed string and the wire URL have to match byte-for-byte.
1172
+ */
1173
+ export declare function createDeviceRequestSignatureV2(params: DeviceRequestSignatureV2Params): string;
1138
1174
  //#endregion
1139
1175
  //#region src/git-utils.d.ts
1140
1176
  /**
@@ -1700,13 +1736,7 @@ export declare enum WebviewMessageType {
1700
1736
  UpdateCopilotLegacyPreview = "updateCopilotLegacyPreview",
1701
1737
  GetUtilityModels = "getUtilityModels",
1702
1738
  UtilityModelsResponse = "utilityModelsResponse",
1703
- UpdateUtilityModels = "updateUtilityModels",
1704
- GetServerProxyState = "getServerProxyState",
1705
- ServerProxyStateResponse = "serverProxyStateResponse",
1706
- SetServerProxyEnabled = "setServerProxyEnabled",
1707
- SetServerProxyAllowOverride = "setServerProxyAllowOverride",
1708
- GetCachedServerUrl = "getCachedServerUrl",
1709
- CachedServerUrlResponse = "cachedServerUrlResponse"
1739
+ UpdateUtilityModels = "updateUtilityModels"
1710
1740
  }
1711
1741
  /**
1712
1742
  * Top-level const aliases for the BYO Utility Models message-type
@@ -1728,92 +1758,6 @@ export declare const UpdateUtilityModels: "updateUtilityModels";
1728
1758
  export declare const SetCacheControlEnabled: "setCacheControlEnabled";
1729
1759
  export declare const GetByomSettings: "getByomSettings";
1730
1760
  export declare const ByomSettingsResponse: "byomSettingsResponse";
1731
- export declare const GetServerProxyState: "getServerProxyState";
1732
- export declare const ServerProxyStateResponse: "serverProxyStateResponse";
1733
- export declare const SetServerProxyEnabled: "setServerProxyEnabled";
1734
- export declare const SetServerProxyAllowOverride: "setServerProxyAllowOverride";
1735
- export declare const GetCachedServerUrl: "getCachedServerUrl";
1736
- export declare const CachedServerUrlResponse: "cachedServerUrlResponse";
1737
- /**
1738
- * Snapshot of the r7 server-proxy toggle (HTTP CONNECT through intranet
1739
- * Server). Mirrors `IProxyConfigService`'s `ProxyState` shape so the
1740
- * webview can render the same fields without a reshape.
1741
- *
1742
- * Returned by `GetServerProxyState` and broadcast as
1743
- * `ServerProxyStateResponse` so the ProvidersTab's ServerProxyToggle
1744
- * component can paint at the persisted state on mount.
1745
- *
1746
- * See `apps/extension/src/services/proxy/ProxyConfigService.ts` for
1747
- * the authoritative source of truth.
1748
- */
1749
- export type ServerProxySupportMode = "off" | "on" | "fallback" | "override";
1750
- export interface ServerProxySnapshot {
1751
- httpProxy: string | undefined;
1752
- httpProxyStrictSSL: boolean;
1753
- httpProxySupport: ServerProxySupportMode;
1754
- /** Self-flag at serverProxy.enabled; computed by the extension handler. */
1755
- enabled: boolean;
1756
- /**
1757
- * rev.21 — opt-in to bypass the `proxySupport === "override"`
1758
- * guard. Power users (e.g. corp environments that WANT all
1759
- * extensions including GitHub Copilot Chat to route through the
1760
- * corp tunnel) tick the "Allow under proxySupport=override"
1761
- * checkbox in the Webview; this flag is persisted to
1762
- * `~/.serviceme/server-proxy.json` alongside `enabled`.
1763
- */
1764
- allowOverride: boolean;
1765
- /** Last server URL we toggled ON with. Used for re-toggling and UI hint. */
1766
- lastServerUrl?: string;
1767
- }
1768
- /**
1769
- * Payload for `SetServerProxyEnabled`. The extension handler is the
1770
- * sole owner of `http.proxy` writes — the webview only sends the
1771
- * desired state + (optional) target scope. Server URL is normally read
1772
- * from the snapshot the webview already received via
1773
- * `ServerProxyStateResponse`; if missing, the handler rejects with
1774
- * `serverProxy.error.missingServerUrl`.
1775
- *
1776
- * `serverUrl` is an OVERRIDE: when supplied, the handler uses it
1777
- * instead of the snapshot's `http.proxy` for the `enable` write
1778
- * path. The Webview's "Use Cached Base URL" affordance relies on this
1779
- * so the cached `ServerConnectionService.getBaseUrl()` value gets
1780
- * applied as `http.proxy` even when `http.proxy` is currently empty.
1781
- * Still subject to the `proxySupport !== "override"` server-side gate.
1782
- */
1783
- export interface ServerProxyTogglePayload {
1784
- enabled: boolean;
1785
- /** Optional — defaults to Workspace. */
1786
- target?: "workspace" | "global";
1787
- /**
1788
- * Optional — override the snapshot's `http.proxy` for the write.
1789
- * Only honoured when `enabled === true`; ignored on disable so the
1790
- * existing "only clear our own write" semantics stay intact.
1791
- */
1792
- serverUrl?: string;
1793
- }
1794
- /**
1795
- * rev.21 — payload for `SetServerProxyAllowOverride`. Toggles the
1796
- * `serverProxy.allowOverride` self-flag in `~/.serviceme/server-proxy.json`.
1797
- * Persisted across VS Code restarts; defaults to `false` so users
1798
- * must explicitly opt-in to the `override` mode bypass.
1799
- */
1800
- export interface ServerProxyAllowOverridePayload {
1801
- allowOverride: boolean;
1802
- }
1803
- /**
1804
- * Reply to `GetCachedServerUrl`. Carries the cached base URL resolved
1805
- * by `ServerConnectionService` (probe + cache of `SERVER_URL_CANDIDATES`)
1806
- * and the same `proxySupport` snapshot for the UI to gate the
1807
- * "Apply" button.
1808
- *
1809
- * `baseUrl: null` means the candidate probe has not yet resolved a
1810
- * reachable Server — the Webview should hide the "Apply cached base
1811
- * URL" affordance rather than offer a no-op button.
1812
- */
1813
- export interface CachedServerUrlSnapshot {
1814
- baseUrl: string | null;
1815
- httpProxySupport: ServerProxySupportMode;
1816
- }
1817
1761
  /**
1818
1762
  * Where the three `msDevTools.utilityModels.*` settings (and their
1819
1763
  * derived `chat.*` mirrors) are persisted.
package/dist/index.d.ts CHANGED
@@ -1098,11 +1098,11 @@ export interface CopilotCustomizationViewPayload {
1098
1098
  * server (verifier).
1099
1099
  *
1100
1100
  * Single source of truth for the `x-ms-device-*` header names and the
1101
- * HMAC-SHA-256 request-signature algorithm. Previously the same
1102
- * constants + function were copy-pasted in three places
1103
- * (extension `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`,
1104
- * server `lib/auth/device-signature-guard.ts`) and kept in sync by
1105
- * comments alone. Server and extension now import from here.
1101
+ * request-signature algorithms. Previously the same constants +
1102
+ * functions were copy-pasted in three places (extension
1103
+ * `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`, server
1104
+ * `lib/auth/device-signature-guard.ts`) and kept in sync by comments
1105
+ * alone. Server and extension now import from here.
1106
1106
  *
1107
1107
  * NOTE: `packages/serviceme-core/src/device/deviceAuth.ts` keeps its own
1108
1108
  * copy — ADL-003 forbids core → shared (and shared → core) so the core
@@ -1117,7 +1117,15 @@ export declare const DeviceAuthHeaders: {
1117
1117
  readonly signature: "x-ms-device-signature";
1118
1118
  readonly timestamp: "x-ms-device-timestamp";
1119
1119
  readonly secretVersion: "x-ms-device-secret-version";
1120
+ /** v2 only — algorithm self-declaration so the server can verify
1121
+ * both schemes during the legacy-client rollout window. */
1122
+ readonly sigAlg: "x-ms-device-sig-alg";
1123
+ /** v2 only — one-time value folded into the signature basis and
1124
+ * checked against a server-side replay cache. */
1125
+ readonly nonce: "x-ms-device-nonce";
1120
1126
  };
1127
+ /** v2 signature algorithm identifier carried in `x-ms-device-sig-alg`. */
1128
+ export declare const DEVICE_SIG_ALG_V2 = "hmac-sha256-v2";
1121
1129
  export interface DeviceRequestSignatureParams {
1122
1130
  method: string;
1123
1131
  path: string;
@@ -1126,8 +1134,12 @@ export interface DeviceRequestSignatureParams {
1126
1134
  secret: string;
1127
1135
  }
1128
1136
  /**
1129
- * Basis is `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET` (LF-joined, NOT JSON).
1130
- * Output is lowercase hex SHA-256.
1137
+ * Legacy (v1) basis: `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET`
1138
+ * (LF-joined, NOT JSON), hashed with a secret-suffix SHA-256.
1139
+ * Output is lowercase hex.
1140
+ *
1141
+ * Retained for backward compatibility with fielded extensions that
1142
+ * predate v2; new code should use `createDeviceRequestSignatureV2`.
1131
1143
  *
1132
1144
  * Uses `js-sha256` (pure JS, synchronous, browser + Node) instead of
1133
1145
  * `node:crypto` so this module stays importable from the webview (the
@@ -1135,6 +1147,30 @@ export interface DeviceRequestSignatureParams {
1135
1147
  * the vite/rollup build).
1136
1148
  */
1137
1149
  export declare function createDeviceRequestSignature(params: DeviceRequestSignatureParams): string;
1150
+ export interface DeviceRequestSignatureV2Params {
1151
+ method: string;
1152
+ /** Full request path INCLUDING the query string (e.g.
1153
+ * `/api/v1/tools/rtk/download?version=1.2.0&target=darwin-arm64`).
1154
+ * v2 signs the query so GET parameters cannot be substituted or
1155
+ * replayed independently of the signed basis. */
1156
+ path: string;
1157
+ timestamp: number;
1158
+ /** One-time value; the server tracks seen nonces per device and
1159
+ * rejects replays within the timestamp window. */
1160
+ nonce: string;
1161
+ body: string;
1162
+ secret: string;
1163
+ }
1164
+ /**
1165
+ * v2 basis: `METHOD\nPATH?QUERY\nTIMESTAMP\nNONCE\nBODY\nSECRET`
1166
+ * (LF-joined, NOT JSON), MACed with real HMAC-SHA-256 keyed by the
1167
+ * device secret. Output is lowercase hex.
1168
+ *
1169
+ * The client MUST build the exact query string it will send before
1170
+ * signing — the server verifies against the raw `request.url` search,
1171
+ * so the signed string and the wire URL have to match byte-for-byte.
1172
+ */
1173
+ export declare function createDeviceRequestSignatureV2(params: DeviceRequestSignatureV2Params): string;
1138
1174
  //#endregion
1139
1175
  //#region src/git-utils.d.ts
1140
1176
  /**
@@ -1700,13 +1736,7 @@ export declare enum WebviewMessageType {
1700
1736
  UpdateCopilotLegacyPreview = "updateCopilotLegacyPreview",
1701
1737
  GetUtilityModels = "getUtilityModels",
1702
1738
  UtilityModelsResponse = "utilityModelsResponse",
1703
- UpdateUtilityModels = "updateUtilityModels",
1704
- GetServerProxyState = "getServerProxyState",
1705
- ServerProxyStateResponse = "serverProxyStateResponse",
1706
- SetServerProxyEnabled = "setServerProxyEnabled",
1707
- SetServerProxyAllowOverride = "setServerProxyAllowOverride",
1708
- GetCachedServerUrl = "getCachedServerUrl",
1709
- CachedServerUrlResponse = "cachedServerUrlResponse"
1739
+ UpdateUtilityModels = "updateUtilityModels"
1710
1740
  }
1711
1741
  /**
1712
1742
  * Top-level const aliases for the BYO Utility Models message-type
@@ -1728,92 +1758,6 @@ export declare const UpdateUtilityModels: "updateUtilityModels";
1728
1758
  export declare const SetCacheControlEnabled: "setCacheControlEnabled";
1729
1759
  export declare const GetByomSettings: "getByomSettings";
1730
1760
  export declare const ByomSettingsResponse: "byomSettingsResponse";
1731
- export declare const GetServerProxyState: "getServerProxyState";
1732
- export declare const ServerProxyStateResponse: "serverProxyStateResponse";
1733
- export declare const SetServerProxyEnabled: "setServerProxyEnabled";
1734
- export declare const SetServerProxyAllowOverride: "setServerProxyAllowOverride";
1735
- export declare const GetCachedServerUrl: "getCachedServerUrl";
1736
- export declare const CachedServerUrlResponse: "cachedServerUrlResponse";
1737
- /**
1738
- * Snapshot of the r7 server-proxy toggle (HTTP CONNECT through intranet
1739
- * Server). Mirrors `IProxyConfigService`'s `ProxyState` shape so the
1740
- * webview can render the same fields without a reshape.
1741
- *
1742
- * Returned by `GetServerProxyState` and broadcast as
1743
- * `ServerProxyStateResponse` so the ProvidersTab's ServerProxyToggle
1744
- * component can paint at the persisted state on mount.
1745
- *
1746
- * See `apps/extension/src/services/proxy/ProxyConfigService.ts` for
1747
- * the authoritative source of truth.
1748
- */
1749
- export type ServerProxySupportMode = "off" | "on" | "fallback" | "override";
1750
- export interface ServerProxySnapshot {
1751
- httpProxy: string | undefined;
1752
- httpProxyStrictSSL: boolean;
1753
- httpProxySupport: ServerProxySupportMode;
1754
- /** Self-flag at serverProxy.enabled; computed by the extension handler. */
1755
- enabled: boolean;
1756
- /**
1757
- * rev.21 — opt-in to bypass the `proxySupport === "override"`
1758
- * guard. Power users (e.g. corp environments that WANT all
1759
- * extensions including GitHub Copilot Chat to route through the
1760
- * corp tunnel) tick the "Allow under proxySupport=override"
1761
- * checkbox in the Webview; this flag is persisted to
1762
- * `~/.serviceme/server-proxy.json` alongside `enabled`.
1763
- */
1764
- allowOverride: boolean;
1765
- /** Last server URL we toggled ON with. Used for re-toggling and UI hint. */
1766
- lastServerUrl?: string;
1767
- }
1768
- /**
1769
- * Payload for `SetServerProxyEnabled`. The extension handler is the
1770
- * sole owner of `http.proxy` writes — the webview only sends the
1771
- * desired state + (optional) target scope. Server URL is normally read
1772
- * from the snapshot the webview already received via
1773
- * `ServerProxyStateResponse`; if missing, the handler rejects with
1774
- * `serverProxy.error.missingServerUrl`.
1775
- *
1776
- * `serverUrl` is an OVERRIDE: when supplied, the handler uses it
1777
- * instead of the snapshot's `http.proxy` for the `enable` write
1778
- * path. The Webview's "Use Cached Base URL" affordance relies on this
1779
- * so the cached `ServerConnectionService.getBaseUrl()` value gets
1780
- * applied as `http.proxy` even when `http.proxy` is currently empty.
1781
- * Still subject to the `proxySupport !== "override"` server-side gate.
1782
- */
1783
- export interface ServerProxyTogglePayload {
1784
- enabled: boolean;
1785
- /** Optional — defaults to Workspace. */
1786
- target?: "workspace" | "global";
1787
- /**
1788
- * Optional — override the snapshot's `http.proxy` for the write.
1789
- * Only honoured when `enabled === true`; ignored on disable so the
1790
- * existing "only clear our own write" semantics stay intact.
1791
- */
1792
- serverUrl?: string;
1793
- }
1794
- /**
1795
- * rev.21 — payload for `SetServerProxyAllowOverride`. Toggles the
1796
- * `serverProxy.allowOverride` self-flag in `~/.serviceme/server-proxy.json`.
1797
- * Persisted across VS Code restarts; defaults to `false` so users
1798
- * must explicitly opt-in to the `override` mode bypass.
1799
- */
1800
- export interface ServerProxyAllowOverridePayload {
1801
- allowOverride: boolean;
1802
- }
1803
- /**
1804
- * Reply to `GetCachedServerUrl`. Carries the cached base URL resolved
1805
- * by `ServerConnectionService` (probe + cache of `SERVER_URL_CANDIDATES`)
1806
- * and the same `proxySupport` snapshot for the UI to gate the
1807
- * "Apply" button.
1808
- *
1809
- * `baseUrl: null` means the candidate probe has not yet resolved a
1810
- * reachable Server — the Webview should hide the "Apply cached base
1811
- * URL" affordance rather than offer a no-op button.
1812
- */
1813
- export interface CachedServerUrlSnapshot {
1814
- baseUrl: string | null;
1815
- httpProxySupport: ServerProxySupportMode;
1816
- }
1817
1761
  /**
1818
1762
  * Where the three `msDevTools.utilityModels.*` settings (and their
1819
1763
  * derived `chat.*` mirrors) are persisted.
package/dist/index.js CHANGED
@@ -1728,11 +1728,11 @@ sha224.hmac = createNodeHmacMethod("sha224");
1728
1728
  * server (verifier).
1729
1729
  *
1730
1730
  * Single source of truth for the `x-ms-device-*` header names and the
1731
- * HMAC-SHA-256 request-signature algorithm. Previously the same
1732
- * constants + function were copy-pasted in three places
1733
- * (extension `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`,
1734
- * server `lib/auth/device-signature-guard.ts`) and kept in sync by
1735
- * comments alone. Server and extension now import from here.
1731
+ * request-signature algorithms. Previously the same constants +
1732
+ * functions were copy-pasted in three places (extension
1733
+ * `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`, server
1734
+ * `lib/auth/device-signature-guard.ts`) and kept in sync by comments
1735
+ * alone. Server and extension now import from here.
1736
1736
  *
1737
1737
  * NOTE: `packages/serviceme-core/src/device/deviceAuth.ts` keeps its own
1738
1738
  * copy — ADL-003 forbids core → shared (and shared → core) so the core
@@ -1746,11 +1746,23 @@ const DeviceAuthHeaders = {
1746
1746
  deviceSecret: "x-ms-device-secret",
1747
1747
  signature: "x-ms-device-signature",
1748
1748
  timestamp: "x-ms-device-timestamp",
1749
- secretVersion: "x-ms-device-secret-version"
1749
+ secretVersion: "x-ms-device-secret-version",
1750
+ /** v2 only — algorithm self-declaration so the server can verify
1751
+ * both schemes during the legacy-client rollout window. */
1752
+ sigAlg: "x-ms-device-sig-alg",
1753
+ /** v2 only — one-time value folded into the signature basis and
1754
+ * checked against a server-side replay cache. */
1755
+ nonce: "x-ms-device-nonce"
1750
1756
  };
1757
+ /** v2 signature algorithm identifier carried in `x-ms-device-sig-alg`. */
1758
+ const DEVICE_SIG_ALG_V2 = "hmac-sha256-v2";
1751
1759
  /**
1752
- * Basis is `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET` (LF-joined, NOT JSON).
1753
- * Output is lowercase hex SHA-256.
1760
+ * Legacy (v1) basis: `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET`
1761
+ * (LF-joined, NOT JSON), hashed with a secret-suffix SHA-256.
1762
+ * Output is lowercase hex.
1763
+ *
1764
+ * Retained for backward compatibility with fielded extensions that
1765
+ * predate v2; new code should use `createDeviceRequestSignatureV2`.
1754
1766
  *
1755
1767
  * Uses `js-sha256` (pure JS, synchronous, browser + Node) instead of
1756
1768
  * `node:crypto` so this module stays importable from the webview (the
@@ -1767,6 +1779,26 @@ function createDeviceRequestSignature(params) {
1767
1779
  ].join("\n");
1768
1780
  return sha256(basis);
1769
1781
  }
1782
+ /**
1783
+ * v2 basis: `METHOD\nPATH?QUERY\nTIMESTAMP\nNONCE\nBODY\nSECRET`
1784
+ * (LF-joined, NOT JSON), MACed with real HMAC-SHA-256 keyed by the
1785
+ * device secret. Output is lowercase hex.
1786
+ *
1787
+ * The client MUST build the exact query string it will send before
1788
+ * signing — the server verifies against the raw `request.url` search,
1789
+ * so the signed string and the wire URL have to match byte-for-byte.
1790
+ */
1791
+ function createDeviceRequestSignatureV2(params) {
1792
+ const basis = [
1793
+ params.method.toUpperCase(),
1794
+ params.path,
1795
+ String(params.timestamp),
1796
+ params.nonce,
1797
+ params.body,
1798
+ params.secret
1799
+ ].join("\n");
1800
+ return sha256.hmac(params.secret, basis);
1801
+ }
1770
1802
  //#endregion
1771
1803
  //#region src/git-utils.ts
1772
1804
  /**
@@ -2263,12 +2295,6 @@ let WebviewMessageType = /* @__PURE__ */ function(WebviewMessageType) {
2263
2295
  WebviewMessageType["GetUtilityModels"] = "getUtilityModels";
2264
2296
  WebviewMessageType["UtilityModelsResponse"] = "utilityModelsResponse";
2265
2297
  WebviewMessageType["UpdateUtilityModels"] = "updateUtilityModels";
2266
- WebviewMessageType["GetServerProxyState"] = "getServerProxyState";
2267
- WebviewMessageType["ServerProxyStateResponse"] = "serverProxyStateResponse";
2268
- WebviewMessageType["SetServerProxyEnabled"] = "setServerProxyEnabled";
2269
- WebviewMessageType["SetServerProxyAllowOverride"] = "setServerProxyAllowOverride";
2270
- WebviewMessageType["GetCachedServerUrl"] = "getCachedServerUrl";
2271
- WebviewMessageType["CachedServerUrlResponse"] = "cachedServerUrlResponse";
2272
2298
  return WebviewMessageType;
2273
2299
  }({});
2274
2300
  /**
@@ -2291,12 +2317,6 @@ const UpdateUtilityModels = "updateUtilityModels";
2291
2317
  const SetCacheControlEnabled = "setCacheControlEnabled";
2292
2318
  const GetByomSettings = "getByomSettings";
2293
2319
  const ByomSettingsResponse = "byomSettingsResponse";
2294
- const GetServerProxyState = "getServerProxyState";
2295
- const ServerProxyStateResponse = "serverProxyStateResponse";
2296
- const SetServerProxyEnabled = "setServerProxyEnabled";
2297
- const SetServerProxyAllowOverride = "setServerProxyAllowOverride";
2298
- const GetCachedServerUrl = "getCachedServerUrl";
2299
- const CachedServerUrlResponse = "cachedServerUrlResponse";
2300
2320
  //#endregion
2301
2321
  //#region src/utils/safe-cast.ts
2302
2322
  /**
@@ -2357,12 +2377,10 @@ function safeJson(text, fallback) {
2357
2377
  exports.BUILTIN_PROVIDER_PRESETS = BUILTIN_PROVIDER_PRESETS;
2358
2378
  exports.ByomSettingsResponse = ByomSettingsResponse;
2359
2379
  exports.CERTIFICATE_BUNDLE_FORMATS = CERTIFICATE_BUNDLE_FORMATS;
2360
- exports.CachedServerUrlResponse = CachedServerUrlResponse;
2380
+ exports.DEVICE_SIG_ALG_V2 = DEVICE_SIG_ALG_V2;
2361
2381
  exports.DeviceAuthHeaders = DeviceAuthHeaders;
2362
2382
  exports.GIT_REMOTE_HOST_ALIASES = GIT_REMOTE_HOST_ALIASES;
2363
2383
  exports.GetByomSettings = GetByomSettings;
2364
- exports.GetCachedServerUrl = GetCachedServerUrl;
2365
- exports.GetServerProxyState = GetServerProxyState;
2366
2384
  exports.GetUtilityModels = GetUtilityModels;
2367
2385
  exports.LISTABLE_PRESET_MODELS = LISTABLE_PRESET_MODELS;
2368
2386
  exports.LogLevel = LogLevel;
@@ -2374,10 +2392,7 @@ exports.NAMESPACE_ALIAS_FAMILY = NAMESPACE_ALIAS_FAMILY;
2374
2392
  exports.PRESET_MODEL_FAMILIES = PRESET_MODEL_FAMILIES;
2375
2393
  exports.PROVIDER_BASE_URL_PRESETS = PROVIDER_BASE_URL_PRESETS;
2376
2394
  exports.PROVIDER_CACHE_CONTROL_METADATA = PROVIDER_CACHE_CONTROL_METADATA;
2377
- exports.ServerProxyStateResponse = ServerProxyStateResponse;
2378
2395
  exports.SetCacheControlEnabled = SetCacheControlEnabled;
2379
- exports.SetServerProxyAllowOverride = SetServerProxyAllowOverride;
2380
- exports.SetServerProxyEnabled = SetServerProxyEnabled;
2381
2396
  exports.UpdateUtilityModels = UpdateUtilityModels;
2382
2397
  exports.UtilityModelsResponse = UtilityModelsResponse;
2383
2398
  exports.WebviewMessageType = WebviewMessageType;
@@ -2388,6 +2403,7 @@ exports.buildPresetModel = buildPresetModel;
2388
2403
  exports.checkGitHubOrgMembership = checkGitHubOrgMembership;
2389
2404
  exports.createConsoleLogger = createConsoleLogger;
2390
2405
  exports.createDeviceRequestSignature = createDeviceRequestSignature;
2406
+ exports.createDeviceRequestSignatureV2 = createDeviceRequestSignatureV2;
2391
2407
  exports.currencyForBaseUrl = currencyForBaseUrl;
2392
2408
  exports.effectiveAdapterType = effectiveAdapterType;
2393
2409
  exports.fetchGitHubUser = fetchGitHubUser;
package/dist/index.mjs CHANGED
@@ -1727,11 +1727,11 @@ sha224.hmac = createNodeHmacMethod("sha224");
1727
1727
  * server (verifier).
1728
1728
  *
1729
1729
  * Single source of truth for the `x-ms-device-*` header names and the
1730
- * HMAC-SHA-256 request-signature algorithm. Previously the same
1731
- * constants + function were copy-pasted in three places
1732
- * (extension `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`,
1733
- * server `lib/auth/device-signature-guard.ts`) and kept in sync by
1734
- * comments alone. Server and extension now import from here.
1730
+ * request-signature algorithms. Previously the same constants +
1731
+ * functions were copy-pasted in three places (extension
1732
+ * `services/device/deviceAuth.ts`, core `device/deviceAuth.ts`, server
1733
+ * `lib/auth/device-signature-guard.ts`) and kept in sync by comments
1734
+ * alone. Server and extension now import from here.
1735
1735
  *
1736
1736
  * NOTE: `packages/serviceme-core/src/device/deviceAuth.ts` keeps its own
1737
1737
  * copy — ADL-003 forbids core → shared (and shared → core) so the core
@@ -1745,11 +1745,23 @@ const DeviceAuthHeaders = {
1745
1745
  deviceSecret: "x-ms-device-secret",
1746
1746
  signature: "x-ms-device-signature",
1747
1747
  timestamp: "x-ms-device-timestamp",
1748
- secretVersion: "x-ms-device-secret-version"
1748
+ secretVersion: "x-ms-device-secret-version",
1749
+ /** v2 only — algorithm self-declaration so the server can verify
1750
+ * both schemes during the legacy-client rollout window. */
1751
+ sigAlg: "x-ms-device-sig-alg",
1752
+ /** v2 only — one-time value folded into the signature basis and
1753
+ * checked against a server-side replay cache. */
1754
+ nonce: "x-ms-device-nonce"
1749
1755
  };
1756
+ /** v2 signature algorithm identifier carried in `x-ms-device-sig-alg`. */
1757
+ const DEVICE_SIG_ALG_V2 = "hmac-sha256-v2";
1750
1758
  /**
1751
- * Basis is `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET` (LF-joined, NOT JSON).
1752
- * Output is lowercase hex SHA-256.
1759
+ * Legacy (v1) basis: `METHOD\nPATH\nTIMESTAMP\nBODY\nSECRET`
1760
+ * (LF-joined, NOT JSON), hashed with a secret-suffix SHA-256.
1761
+ * Output is lowercase hex.
1762
+ *
1763
+ * Retained for backward compatibility with fielded extensions that
1764
+ * predate v2; new code should use `createDeviceRequestSignatureV2`.
1753
1765
  *
1754
1766
  * Uses `js-sha256` (pure JS, synchronous, browser + Node) instead of
1755
1767
  * `node:crypto` so this module stays importable from the webview (the
@@ -1766,6 +1778,26 @@ function createDeviceRequestSignature(params) {
1766
1778
  ].join("\n");
1767
1779
  return sha256(basis);
1768
1780
  }
1781
+ /**
1782
+ * v2 basis: `METHOD\nPATH?QUERY\nTIMESTAMP\nNONCE\nBODY\nSECRET`
1783
+ * (LF-joined, NOT JSON), MACed with real HMAC-SHA-256 keyed by the
1784
+ * device secret. Output is lowercase hex.
1785
+ *
1786
+ * The client MUST build the exact query string it will send before
1787
+ * signing — the server verifies against the raw `request.url` search,
1788
+ * so the signed string and the wire URL have to match byte-for-byte.
1789
+ */
1790
+ function createDeviceRequestSignatureV2(params) {
1791
+ const basis = [
1792
+ params.method.toUpperCase(),
1793
+ params.path,
1794
+ String(params.timestamp),
1795
+ params.nonce,
1796
+ params.body,
1797
+ params.secret
1798
+ ].join("\n");
1799
+ return sha256.hmac(params.secret, basis);
1800
+ }
1769
1801
  //#endregion
1770
1802
  //#region src/git-utils.ts
1771
1803
  /**
@@ -2262,12 +2294,6 @@ let WebviewMessageType = /* @__PURE__ */ function(WebviewMessageType) {
2262
2294
  WebviewMessageType["GetUtilityModels"] = "getUtilityModels";
2263
2295
  WebviewMessageType["UtilityModelsResponse"] = "utilityModelsResponse";
2264
2296
  WebviewMessageType["UpdateUtilityModels"] = "updateUtilityModels";
2265
- WebviewMessageType["GetServerProxyState"] = "getServerProxyState";
2266
- WebviewMessageType["ServerProxyStateResponse"] = "serverProxyStateResponse";
2267
- WebviewMessageType["SetServerProxyEnabled"] = "setServerProxyEnabled";
2268
- WebviewMessageType["SetServerProxyAllowOverride"] = "setServerProxyAllowOverride";
2269
- WebviewMessageType["GetCachedServerUrl"] = "getCachedServerUrl";
2270
- WebviewMessageType["CachedServerUrlResponse"] = "cachedServerUrlResponse";
2271
2297
  return WebviewMessageType;
2272
2298
  }({});
2273
2299
  /**
@@ -2290,12 +2316,6 @@ const UpdateUtilityModels = "updateUtilityModels";
2290
2316
  const SetCacheControlEnabled = "setCacheControlEnabled";
2291
2317
  const GetByomSettings = "getByomSettings";
2292
2318
  const ByomSettingsResponse = "byomSettingsResponse";
2293
- const GetServerProxyState = "getServerProxyState";
2294
- const ServerProxyStateResponse = "serverProxyStateResponse";
2295
- const SetServerProxyEnabled = "setServerProxyEnabled";
2296
- const SetServerProxyAllowOverride = "setServerProxyAllowOverride";
2297
- const GetCachedServerUrl = "getCachedServerUrl";
2298
- const CachedServerUrlResponse = "cachedServerUrlResponse";
2299
2319
  //#endregion
2300
2320
  //#region src/utils/safe-cast.ts
2301
2321
  /**
@@ -2353,4 +2373,4 @@ function safeJson(text, fallback) {
2353
2373
  }
2354
2374
  }
2355
2375
  //#endregion
2356
- export { BUILTIN_PROVIDER_PRESETS, ByomSettingsResponse, CERTIFICATE_BUNDLE_FORMATS, CachedServerUrlResponse, DeviceAuthHeaders, GIT_REMOTE_HOST_ALIASES, GetByomSettings, GetCachedServerUrl, GetServerProxyState, GetUtilityModels, LISTABLE_PRESET_MODELS, LogLevel, MEDALSOFT_NUGET_PRIVATE_SOURCE, MEDALSOFT_PRIVATE_GATEWAY_URL, MODEL_METADATA, NAMESPACE_ALIASES, NAMESPACE_ALIAS_FAMILY, PRESET_MODEL_FAMILIES, PROVIDER_BASE_URL_PRESETS, PROVIDER_CACHE_CONTROL_METADATA, ServerProxyStateResponse, SetCacheControlEnabled, SetServerProxyAllowOverride, SetServerProxyEnabled, UpdateUtilityModels, UtilityModelsResponse, WebviewMessageType, __internal, asAbortSignal, buildGitHubLocalEmail, buildPresetModel, checkGitHubOrgMembership, createConsoleLogger, createDeviceRequestSignature, currencyForBaseUrl, effectiveAdapterType, fetchGitHubUser, getBuiltinProviderPreset, getGitHubOrgMembership, getPresetModelDisplayName, getProviderBaseUrlPresets, isGitHubLocalEmail, isProviderCacheControlAware, isValidCanonicalSlug, isWholePackageInstall, listPresetModelGroups, lookupModelMetadata, normalizeCanonicalSlug, normalizeErrorForLog, normalizeGitUrl, parsePayload, protocolForBaseUrl, registrationIdFromPackageId, resolvePrimaryEmail, safeJson, unionProviderModelWithPreset };
2376
+ export { BUILTIN_PROVIDER_PRESETS, ByomSettingsResponse, CERTIFICATE_BUNDLE_FORMATS, DEVICE_SIG_ALG_V2, DeviceAuthHeaders, GIT_REMOTE_HOST_ALIASES, GetByomSettings, GetUtilityModels, LISTABLE_PRESET_MODELS, LogLevel, MEDALSOFT_NUGET_PRIVATE_SOURCE, MEDALSOFT_PRIVATE_GATEWAY_URL, MODEL_METADATA, NAMESPACE_ALIASES, NAMESPACE_ALIAS_FAMILY, PRESET_MODEL_FAMILIES, PROVIDER_BASE_URL_PRESETS, PROVIDER_CACHE_CONTROL_METADATA, SetCacheControlEnabled, UpdateUtilityModels, UtilityModelsResponse, WebviewMessageType, __internal, asAbortSignal, buildGitHubLocalEmail, buildPresetModel, checkGitHubOrgMembership, createConsoleLogger, createDeviceRequestSignature, createDeviceRequestSignatureV2, currencyForBaseUrl, effectiveAdapterType, fetchGitHubUser, getBuiltinProviderPreset, getGitHubOrgMembership, getPresetModelDisplayName, getProviderBaseUrlPresets, isGitHubLocalEmail, isProviderCacheControlAware, isValidCanonicalSlug, isWholePackageInstall, listPresetModelGroups, lookupModelMetadata, normalizeCanonicalSlug, normalizeErrorForLog, normalizeGitUrl, parsePayload, protocolForBaseUrl, registrationIdFromPackageId, resolvePrimaryEmail, safeJson, unionProviderModelWithPreset };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serviceme/devtools-shared",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Shared webview↔extension message contracts and cross-package data models used by SERVICEME.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {