@cmmd-center/forge 0.13.124 → 0.13.125

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/bin.cjs CHANGED
@@ -30767,7 +30767,7 @@ function frameClassByte(frameClass) {
30767
30767
  if (frameClass === "application") return Uint8Array.of(1);
30768
30768
  return Uint8Array.of(2);
30769
30769
  }
30770
- function encodeBase64Url$1(value) {
30770
+ function encodeBase64Url$2(value) {
30771
30771
  let output = "";
30772
30772
  for (let index = 0; index < value.byteLength; index += 3) {
30773
30773
  const first = value[index] ?? 0;
@@ -30797,7 +30797,7 @@ function decodeBase64Url$1(value) {
30797
30797
  outputIndex += 1;
30798
30798
  }
30799
30799
  }
30800
- if (encodeBase64Url$1(output) !== value) throw new RelayPayloadChannelFailure("channel_authentication_failed", "Encrypted relay frame has a non-canonical base64url encoding.");
30800
+ if (encodeBase64Url$2(output) !== value) throw new RelayPayloadChannelFailure("channel_authentication_failed", "Encrypted relay frame has a non-canonical base64url encoding.");
30801
30801
  return output;
30802
30802
  }
30803
30803
  function isLowOrderX25519PublicKey(value) {
@@ -30836,7 +30836,7 @@ async function createRelayPayloadBinding(input, digestProvider = defaultDigestPr
30836
30836
  };
30837
30837
  }
30838
30838
  function relayPayloadTicketDigestBase64Url(binding) {
30839
- return encodeBase64Url$1(binding.ticketDigest);
30839
+ return encodeBase64Url$2(binding.ticketDigest);
30840
30840
  }
30841
30841
  function relayPayloadInfo(binding) {
30842
30842
  return concat([
@@ -30873,7 +30873,7 @@ async function generateRelayEndpointKeyPair(randomSource = defaultRandomSource)
30873
30873
  }
30874
30874
  async function serializeRelayEndpointPublicKey(publicKey) {
30875
30875
  try {
30876
- return encodeBase64Url$1(bytes(await suite.kem.serializePublicKey(publicKey)));
30876
+ return encodeBase64Url$2(bytes(await suite.kem.serializePublicKey(publicKey)));
30877
30877
  } catch (error) {
30878
30878
  throw new RelayPayloadChannelFailure("endpoint_key_invalid", error instanceof Error ? error.message : "Endpoint public-key serialization failed.");
30879
30879
  }
@@ -30928,7 +30928,7 @@ var HpkeRelayPayloadSender = class {
30928
30928
  constructor(binding, context) {
30929
30929
  this.binding = binding;
30930
30930
  this.context = context;
30931
- this.encapsulatedKey = encodeBase64Url$1(bytes(context.enc));
30931
+ this.encapsulatedKey = encodeBase64Url$2(bytes(context.enc));
30932
30932
  }
30933
30933
  seal(input) {
30934
30934
  return this.queue.run(async () => {
@@ -30958,7 +30958,7 @@ var HpkeRelayPayloadSender = class {
30958
30958
  direction: this.binding.direction,
30959
30959
  frameClass: input.frameClass,
30960
30960
  sequence,
30961
- ciphertext: encodeBase64Url$1(ciphertext)
30961
+ ciphertext: encodeBase64Url$2(ciphertext)
30962
30962
  };
30963
30963
  });
30964
30964
  }
@@ -66337,7 +66337,7 @@ function normalizeNumberish(value) {
66337
66337
  }
66338
66338
  //#endregion
66339
66339
  //#region package.json
66340
- var version$1 = "0.13.124";
66340
+ var version$1 = "0.13.125";
66341
66341
  //#endregion
66342
66342
  //#region src/sentry.ts
66343
66343
  const SERVER_APP_NAME = "forge-server";
@@ -71414,6 +71414,19 @@ function mintCmmdShortLivedToken(grantToken) {
71414
71414
  });
71415
71415
  }
71416
71416
  /**
71417
+ * The redemption request body. `popPublicKeyPem` is the server's PoP identity
71418
+ * (forge#3534): presented when bound sessions are enabled so CMMD stamps the
71419
+ * returned JWT with this server's key (`cnf.jkt`), omitted otherwise.
71420
+ */
71421
+ function buildSessionGrantRedemptionBody(grantToken, popPublicKeyPem) {
71422
+ return {
71423
+ grant_type: "forge_session_grant",
71424
+ grant_token: grantToken,
71425
+ client_id: "cmmd-forge-web",
71426
+ ...popPublicKeyPem ? { pop_public_key: popPublicKeyPem } : {}
71427
+ };
71428
+ }
71429
+ /**
71417
71430
  * Redeem a durable CMMD session grant for a fresh credential set.
71418
71431
  *
71419
71432
  * The grant is CMMD's designed recovery path for exactly the case a rotating
@@ -71425,15 +71438,11 @@ function mintCmmdShortLivedToken(grantToken) {
71425
71438
  * Returns the new MCP PAT alongside the JWT/refresh pair, because CMMD mints a
71426
71439
  * fresh PAT on redemption and the old one is not carried over.
71427
71440
  */
71428
- function redeemCmmdSessionGrant(grantToken) {
71441
+ function redeemCmmdSessionGrant(grantToken, popPublicKeyPem) {
71429
71442
  return fetch(new URL("/api/mcp-server/oauth/token", resolveCommandAppUrl()).toString(), {
71430
71443
  method: "POST",
71431
71444
  headers: { "Content-Type": "application/json" },
71432
- body: JSON.stringify({
71433
- grant_type: "forge_session_grant",
71434
- grant_token: grantToken,
71435
- client_id: "cmmd-forge-web"
71436
- })
71445
+ body: JSON.stringify(buildSessionGrantRedemptionBody(grantToken, popPublicKeyPem))
71437
71446
  }).then(async (response) => {
71438
71447
  if (!response.ok) return null;
71439
71448
  const payload = await response.json();
@@ -71504,6 +71513,140 @@ async function readOAuthErrorCode(response) {
71504
71513
  }
71505
71514
  }
71506
71515
  //#endregion
71516
+ //#region ../../packages/shared/src/cmmdSessionPop.ts
71517
+ /**
71518
+ * CMMD session proof-of-possession client protocol (forge#3517).
71519
+ *
71520
+ * A CMMD session issued to a Forge client can be bound to the client's Ed25519
71521
+ * device key: the public key travels with the login (`pop_public_key`), CMMD
71522
+ * stamps its thumbprint into the token (`cnf.jkt`), and every authenticated
71523
+ * request must then carry a detached Ed25519 signature over a canonical
71524
+ * request binding (method + path + timestamp + nonce). A stolen bearer token
71525
+ * alone is unusable.
71526
+ *
71527
+ * This module is the client half of the scheme CMMD verifies in
71528
+ * `server/services/auth/session-pop-binding.ts`. The protocol deliberately
71529
+ * reuses CMMD's existing crypto shapes rather than inventing a new scheme: the
71530
+ * thumbprint is the same sha256-over-SPKI-DER base64url digest as the forge
71531
+ * device registry and the desktop relay identity, and the signature covers
71532
+ * `<purpose>.<base64url payload>`, the forge relay challenge shape, with
71533
+ * Ed25519. It is not a DPoP port: proofs are plain headers, not JWTs.
71534
+ */
71535
+ const HEADER_KEY = "x-cmmd-pop-key";
71536
+ const HEADER_INPUT = "x-cmmd-pop-input";
71537
+ const HEADER_SIGNATURE = "x-cmmd-pop-signature";
71538
+ const CMMD_SESSION_POP_PURPOSE = "cmmd-session-pop-v1";
71539
+ function encodeBase64Url$1(bytes) {
71540
+ let binary = "";
71541
+ for (const byte of bytes) binary += String.fromCharCode(byte);
71542
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/u, "");
71543
+ }
71544
+ function buildCmmdSessionPopSigningInput(payload) {
71545
+ return `${CMMD_SESSION_POP_PURPOSE}.${encodeBase64Url$1(new TextEncoder().encode(JSON.stringify(payload)))}`;
71546
+ }
71547
+ function randomNonce() {
71548
+ const bytes = new Uint8Array(16);
71549
+ crypto.getRandomValues(bytes);
71550
+ return encodeBase64Url$1(bytes);
71551
+ }
71552
+ /**
71553
+ * Build the three proof headers for one request. Each call produces a fresh
71554
+ * nonce; callers must not reuse the returned headers across attempts
71555
+ * (retries included), because CMMD rejects replayed nonces.
71556
+ */
71557
+ async function buildCmmdSessionPopProofHeaders(input) {
71558
+ const payload = {
71559
+ version: 1,
71560
+ htm: input.method.toUpperCase(),
71561
+ htu: input.path,
71562
+ ts: input.nowSeconds ?? Math.floor(Date.now() / 1e3),
71563
+ nonce: input.nonce ?? randomNonce()
71564
+ };
71565
+ const signingInput = buildCmmdSessionPopSigningInput(payload);
71566
+ const signature = await input.signer.sign(signingInput);
71567
+ const spkiDer = decodePemSpkiDer(input.signer.publicKeyPem);
71568
+ return {
71569
+ [HEADER_KEY]: encodeBase64Url$1(spkiDer),
71570
+ [HEADER_INPUT]: encodeBase64Url$1(new TextEncoder().encode(JSON.stringify(payload))),
71571
+ [HEADER_SIGNATURE]: encodeBase64Url$1(signature)
71572
+ };
71573
+ }
71574
+ function decodePemSpkiDer(pem) {
71575
+ const base64 = pem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace(/\s+/gu, "").replace(/-/g, "+").replace(/_/g, "/");
71576
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
71577
+ const binary = atob(padded);
71578
+ const bytes = new Uint8Array(binary.length);
71579
+ for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
71580
+ return bytes;
71581
+ }
71582
+ //#endregion
71583
+ //#region src/cmmd/cmmdSessionPopServer.ts
71584
+ /**
71585
+ * The Forge server's own CMMD session proof-of-possession identity (forge#3534,
71586
+ * D3): the server holds an Ed25519 key, presents its SPKI PEM as
71587
+ * `pop_public_key` when it redeems a CMMD session grant, and signs every
71588
+ * CMMD-origin REST call it makes with detached proofs, so a stolen bearer JWT
71589
+ * alone is unusable. CMMD verifies the scheme in
71590
+ * `server/services/auth/session-pop-binding.ts`.
71591
+ *
71592
+ * Rollout order (docs/forge-cmmd-auth-lanes.md): CMMD deploys first; Forge
71593
+ * flips `FORGE_CMMD_SESSION_POP_ENABLED` afterwards; CMMD's
71594
+ * `JWT_REQUIRE_BOUND_SESSIONS=true` is the contract phase. While the flag is
71595
+ * off this module produces no keys and no headers, and CMMD treats tokens as
71596
+ * plain bearers.
71597
+ *
71598
+ * The identity lives in memory for the process lifetime. After a restart the
71599
+ * server mints a new identity; CMMD then refuses proofs from the old one, and
71600
+ * the JWT resolver's recovery ladder re-mints the affected credentials. The
71601
+ * persistence duty (a stable identity across restarts) lands with the flag
71602
+ * rollout, not with this plumbing.
71603
+ */
71604
+ const ENABLED_FLAG = "FORGE_CMMD_SESSION_POP_ENABLED";
71605
+ /** Enables session proofs only when the rollout flag is exactly "true". */
71606
+ function isCmmdSessionPopEnabled() {
71607
+ return process.env[ENABLED_FLAG] === "true";
71608
+ }
71609
+ let cachedSigner = null;
71610
+ /** Creates an in-memory Ed25519 identity with a public SPKI PEM and a detached signer. */
71611
+ function createServerSigner() {
71612
+ const { publicKey, privateKey } = (0, node_crypto.generateKeyPairSync)("ed25519");
71613
+ const exported = publicKey.export({
71614
+ type: "spki",
71615
+ format: "pem"
71616
+ });
71617
+ return {
71618
+ publicKeyPem: typeof exported === "string" ? exported : exported.toString("utf8"),
71619
+ sign: async (signingInput) => new Uint8Array((0, node_crypto.sign)(null, Buffer.from(signingInput, "utf8"), privateKey))
71620
+ };
71621
+ }
71622
+ /**
71623
+ * The server's PoP identity, created on first use under the flag and stable
71624
+ * for the process lifetime. Null while the flag is off.
71625
+ */
71626
+ function resolveCmmdSessionPopSigner() {
71627
+ if (!isCmmdSessionPopEnabled()) return null;
71628
+ cachedSigner ??= createServerSigner();
71629
+ return cachedSigner;
71630
+ }
71631
+ /** The `pop_public_key` value to present at issuance, or null while disabled. */
71632
+ function cmmdSessionPopPublicKey() {
71633
+ return resolveCmmdSessionPopSigner()?.publicKeyPem ?? null;
71634
+ }
71635
+ /**
71636
+ * The three proof headers for one CMMD-origin request, or no headers while
71637
+ * disabled. Each call carries a fresh nonce; never reuse the result across
71638
+ * attempts, because CMMD rejects replayed nonces.
71639
+ */
71640
+ async function cmmdSessionPopRequestHeaders(input) {
71641
+ const signer = resolveCmmdSessionPopSigner();
71642
+ if (!signer) return {};
71643
+ return buildCmmdSessionPopProofHeaders({
71644
+ signer,
71645
+ method: input.method,
71646
+ path: input.path
71647
+ });
71648
+ }
71649
+ //#endregion
71507
71650
  //#region src/command/cmmdTokenMintLane.ts
71508
71651
  /**
71509
71652
  * The CMMD token-mint lane (forge#3518, expand phase).
@@ -71756,7 +71899,7 @@ function tryGrantRedemption(sessionId, context) {
71756
71899
  return require_Schema$1.gen(function* () {
71757
71900
  yield* logCmmdJwtRung(context, "grant-redemption", "attempted", "redeeming this session's durable CMMD session grant");
71758
71901
  yield* recordCmmdCredentialRefreshMetric("grant-redemption", "attempted");
71759
- const redeemed = yield* require_Schema$1.promise(() => redeemCmmdSessionGrant(grantToken)).pipe(require_Schema$1.orElseSucceed(() => null));
71902
+ const redeemed = yield* require_Schema$1.promise(() => redeemCmmdSessionGrant(grantToken, cmmdSessionPopPublicKey())).pipe(require_Schema$1.orElseSucceed(() => null));
71760
71903
  const accessToken = usableCmmdUserJwt(redeemed?.accessToken);
71761
71904
  if (!accessToken) {
71762
71905
  yield* logCmmdJwtRung(context, "grant-redemption", "failed", "session grant redemption did not return a usable user access JWT");
@@ -72045,11 +72188,25 @@ async function requireCmmdProxySuccess(response, signal) {
72045
72188
  * Uses the stored JWT (set after OAuth auth-code flow with post-update CMMD)
72046
72189
  * to make authenticated REST calls on behalf of the user. A missing delegated
72047
72190
  * JWT is an authentication-required state, not a CMMD availability failure.
72191
+ *
72192
+ * Every request this module sends can carry the server's session
72193
+ * proof-of-possession headers (forge#3534): while
72194
+ * `FORGE_CMMD_SESSION_POP_ENABLED` is true, `authHeaders` attaches detached
72195
+ * Ed25519 proofs over each request's method and path, which CMMD requires for
72196
+ * tokens bound with `cnf.jkt` and ignores otherwise. Each call gets a fresh
72197
+ * nonce, so retries re-sign rather than replay.
72048
72198
  */
72049
- function authHeaders(jwt, orgId) {
72199
+ /** Builds owner JWT and optional organization headers with fresh, flag-gated session proofs. */
72200
+ async function authHeaders(jwt, orgId, method, path) {
72050
72201
  const headers = { Authorization: `Bearer ${jwt}` };
72051
72202
  if (orgId) headers["X-Organization-ID"] = orgId;
72052
- return headers;
72203
+ return {
72204
+ ...headers,
72205
+ ...await cmmdSessionPopRequestHeaders({
72206
+ method,
72207
+ path
72208
+ })
72209
+ };
72053
72210
  }
72054
72211
  async function fetchResponse(url, init, options) {
72055
72212
  try {
@@ -72061,18 +72218,20 @@ async function fetchResponse(url, init, options) {
72061
72218
  rethrowCmmdProxyTimeout(error, options?.signal);
72062
72219
  }
72063
72220
  }
72221
+ /** Fetches a CMMD JSON resource with optional query parameters and caller cancellation. */
72064
72222
  async function proxyGet(jwt, path, searchParams, orgId, options) {
72065
72223
  const cmmdBase = resolveCommandAppUrl();
72066
72224
  const url = new URL(path, cmmdBase);
72067
72225
  if (searchParams) for (const [k, v] of Object.entries(searchParams)) url.searchParams.set(k, v);
72068
- return handleCmmdProxyResponse(await fetchResponse(url.toString(), { headers: authHeaders(jwt, orgId) }, options), options?.signal);
72226
+ return handleCmmdProxyResponse(await fetchResponse(url.toString(), { headers: await authHeaders(jwt, orgId, "GET", path) }, options), options?.signal);
72069
72227
  }
72228
+ /** Posts JSON to CMMD on the owner JWT lane and decodes the response or upstream error. */
72070
72229
  async function proxyPost(jwt, path, body, orgId, options) {
72071
72230
  const cmmdBase = resolveCommandAppUrl();
72072
72231
  return handleCmmdProxyResponse(await fetchResponse(new URL(path, cmmdBase).toString(), {
72073
72232
  method: "POST",
72074
72233
  headers: {
72075
- ...authHeaders(jwt, orgId),
72234
+ ...await authHeaders(jwt, orgId, "POST", path),
72076
72235
  "Content-Type": "application/json"
72077
72236
  },
72078
72237
  body: JSON.stringify(body)
@@ -72086,44 +72245,49 @@ async function responseWithMetadata(response, signal) {
72086
72245
  retryAfter: response.headers.get("retry-after")
72087
72246
  };
72088
72247
  }
72248
+ /** Fetches a CMMD resource while preserving status, Location, and Retry-After metadata. */
72089
72249
  async function proxyGetWithMetadata(jwt, path, orgId, options) {
72090
- return responseWithMetadata(await fetchResponse(new URL(path, resolveCommandAppUrl()).toString(), { headers: authHeaders(jwt, orgId) }, options), options?.signal);
72250
+ return responseWithMetadata(await fetchResponse(new URL(path, resolveCommandAppUrl()).toString(), { headers: await authHeaders(jwt, orgId, "GET", path) }, options), options?.signal);
72091
72251
  }
72252
+ /** Posts JSON to CMMD while preserving status, Location, and Retry-After metadata. */
72092
72253
  async function proxyPostWithMetadata(jwt, path, body, orgId, options) {
72093
72254
  const cmmdBase = resolveCommandAppUrl();
72094
72255
  return responseWithMetadata(await fetchResponse(new URL(path, cmmdBase).toString(), {
72095
72256
  method: "POST",
72096
72257
  headers: {
72097
- ...authHeaders(jwt, orgId),
72258
+ ...await authHeaders(jwt, orgId, "POST", path),
72098
72259
  "Content-Type": "application/json"
72099
72260
  },
72100
72261
  body: JSON.stringify(body)
72101
72262
  }, options), options?.signal);
72102
72263
  }
72264
+ /** Applies a JSON patch request to CMMD using the owner JWT and optional organization. */
72103
72265
  async function proxyPatch(jwt, path, body, orgId) {
72104
72266
  const cmmdBase = resolveCommandAppUrl();
72105
72267
  const url = new URL(path, cmmdBase);
72106
72268
  return handleCmmdProxyResponse(await fetch(url.toString(), {
72107
72269
  method: "PATCH",
72108
72270
  headers: {
72109
- ...authHeaders(jwt, orgId),
72271
+ ...await authHeaders(jwt, orgId, "PATCH", path),
72110
72272
  "Content-Type": "application/json"
72111
72273
  },
72112
72274
  body: JSON.stringify(body)
72113
72275
  }));
72114
72276
  }
72277
+ /** Sends a JSON replacement request to CMMD and decodes its response or upstream error. */
72115
72278
  async function proxyPut(jwt, path, body, orgId) {
72116
72279
  const cmmdBase = resolveCommandAppUrl();
72117
72280
  const url = new URL(path, cmmdBase);
72118
72281
  return handleCmmdProxyResponse(await fetch(url.toString(), {
72119
72282
  method: "PUT",
72120
72283
  headers: {
72121
- ...authHeaders(jwt, orgId),
72284
+ ...await authHeaders(jwt, orgId, "PUT", path),
72122
72285
  "Content-Type": "application/json"
72123
72286
  },
72124
72287
  body: JSON.stringify(body)
72125
72288
  }));
72126
72289
  }
72290
+ /** Deletes a CMMD resource with optional query parameters and JSON body; 204 returns undefined. */
72127
72291
  async function proxyDelete(jwt, path, searchParams, orgId, body) {
72128
72292
  const cmmdBase = resolveCommandAppUrl();
72129
72293
  const url = new URL(path, cmmdBase);
@@ -72131,7 +72295,7 @@ async function proxyDelete(jwt, path, searchParams, orgId, body) {
72131
72295
  const response = await fetch(url.toString(), {
72132
72296
  method: "DELETE",
72133
72297
  headers: {
72134
- ...authHeaders(jwt, orgId),
72298
+ ...await authHeaders(jwt, orgId, "DELETE", path),
72135
72299
  ...body === void 0 ? {} : { "Content-Type": "application/json" }
72136
72300
  },
72137
72301
  ...body === void 0 ? {} : { body: JSON.stringify(body) }
@@ -72139,13 +72303,14 @@ async function proxyDelete(jwt, path, searchParams, orgId, body) {
72139
72303
  if (!response.ok && response.status !== 204) await requireCmmdProxySuccess(response);
72140
72304
  return response.status === 204 ? void 0 : handleCmmdProxyResponse(response);
72141
72305
  }
72306
+ /** Forwards multipart bytes to CMMD, preserving the caller's content type and boundary. */
72142
72307
  async function proxyMultipart(jwt, path, body, contentType, orgId) {
72143
72308
  const cmmdBase = resolveCommandAppUrl();
72144
72309
  const url = new URL(path, cmmdBase);
72145
72310
  return handleCmmdProxyResponse(await fetch(url.toString(), {
72146
72311
  method: "POST",
72147
72312
  headers: {
72148
- ...authHeaders(jwt, orgId),
72313
+ ...await authHeaders(jwt, orgId, "POST", path),
72149
72314
  "Content-Type": contentType
72150
72315
  },
72151
72316
  body
@@ -300407,7 +300572,7 @@ function resolveBuildCommitFromEnv(env) {
300407
300572
  * environment descriptor down instead of reporting an honest "unknown".
300408
300573
  */
300409
300574
  function readBakedBuildCommit() {
300410
- return "52e8c25f0de536143b44ff1ac86510aa93d35772";
300575
+ return "2b217d6b85f7c98cf77e2a23bce2ef8102d3a0a5";
300411
300576
  }
300412
300577
  async function resolveServerBuildCommit(input) {
300413
300578
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -313335,6 +313500,44 @@ const cmmdUpdateProjectAgentMemberAvatarRouteLayer = registerProxyRoute({
313335
313500
  responseShape: "unwrapData"
313336
313501
  });
313337
313502
  //#endregion
313503
+ //#region src/command/cmmdPushProxyRoutes.ts
313504
+ /**
313505
+ * The signed-in phone's push registration, forwarded to CMMD's push
313506
+ * device-token API on the owner's stored CMMD JWT (forge#3534).
313507
+ *
313508
+ * CMMD owns push delivery: the `device_push_tokens` table, the Expo transport,
313509
+ * and the `mobile_push_v1` delivery flag are all CMMD-side, and its
313510
+ * registration API lives at `/api/push`, not under `/api/forge/context`. The
313511
+ * mobile push delivery spec (docs/specs/2026-09-09-mobile-push-delivery.md,
313512
+ * stage 2) recommends reusing that API over adding a forge-context doorway
313513
+ * first: the Forge server already holds the phone's CMMD credential, and the
313514
+ * registry prologue here provides the same session auth, CMMD-connection
313515
+ * gate, and `CMMD_AUTH_REQUIRED` mapping every `/api/cmmd` route gets. The
313516
+ * deny-listed legacy owner control paths are untouched. If review wants a
313517
+ * forge-context doorway first, these two routes are the only call sites to
313518
+ * repoint.
313519
+ *
313520
+ * `orgIdSource` is `none` (the organization comes from the JWT, like the
313521
+ * settings and device-registry routes): a phone registers against its default
313522
+ * organization and has no workspace context to pass.
313523
+ */
313524
+ const cmmdRegisterMobilePushDeviceRouteLayer = registerProxyRoute({
313525
+ forgePath: "/api/cmmd/mobile/push/registration",
313526
+ method: "POST",
313527
+ cmmdPath: "/api/push/device-tokens",
313528
+ orgIdSource: "none",
313529
+ responseShape: "unwrapData",
313530
+ successStatus: 201
313531
+ });
313532
+ const cmmdDeleteMobilePushDeviceRouteLayer = registerProxyRoute({
313533
+ forgePath: "/api/cmmd/mobile/push/registration",
313534
+ method: "DELETE",
313535
+ cmmdPath: "/api/push/device-tokens",
313536
+ orgIdSource: "none",
313537
+ responseShape: "unwrapData",
313538
+ requestBody: "json"
313539
+ });
313540
+ //#endregion
313338
313541
  //#region src/command/runtimeProviderAuthorityUpgradeModel.ts
313339
313542
  const AUTHORITY_UPGRADE_OPERATION_KEYS = new Set([
313340
313543
  "operationId",
@@ -324954,7 +325157,7 @@ const MiscRuntimeLayerLive = require_Schema$1.mergeAll(AnalyticsServiceLayerLive
324954
325157
  const RuntimeDependenciesWithoutPullRequestsLive = ReactorLayerLive.pipe(require_Schema$1.provideMerge(CheckpointingLayerLive), require_Schema$1.provideMerge(GitLayerLive), require_Schema$1.provideMerge(OrchestrationLayerLive), require_Schema$1.provideMerge(ProviderLayerLive), require_Schema$1.provideMerge(TerminalLayerLive), require_Schema$1.provideMerge(AgentBrowserManagerLive), require_Schema$1.provideMerge(require_Schema$1.mergeAll(ThreadDevRuntimeLive, DevTunnelLive.pipe(require_Schema$1.provide$1(ThreadDevRuntimeLive)))), require_Schema$1.provideMerge(PersistenceLayerLive), require_Schema$1.provideMerge(KeybindingsLive), require_Schema$1.provideMerge(ProviderRegistryLive), require_Schema$1.provideMerge(require_Schema$1.mergeAll(ServerSettingsLive, UsageServiceLive.pipe(require_Schema$1.provide$1(ServerSettingsLive), require_Schema$1.provide$1(UsageSessionLookupLive), require_Schema$1.provide$1(UsageRecordedSourceLive.pipe(require_Schema$1.provide$1(OrchestrationLayerLive), require_Schema$1.provide$1(RuntimeReplicationOutboxLive), require_Schema$1.provide$1(ProviderSessionRuntimeRepositoryLive), require_Schema$1.provide$1(TextGenerationSessionRepositoryLive)))))), require_Schema$1.provideMerge(WorkspaceLayerLive), require_Schema$1.provideMerge(WorkspaceReadinessStateLive), require_Schema$1.provideMerge(ProjectFaviconResolverLive), require_Schema$1.provideMerge(RepositoryIdentityResolverLive), require_Schema$1.provideMerge(ServerEnvironmentLive), require_Schema$1.provideMerge(AuthLayerLive), require_Schema$1.provideMerge(ServerSecretStoreLayerLive), require_Schema$1.provideMerge(require_Schema$1.mergeAll(CloudRedisCoordinationLive, CloudStateSyncLive.pipe(require_Schema$1.provide$1(PersistenceLayerLive)))), require_Schema$1.provideMerge(MiscRuntimeLayerLive));
324955
325158
  const RuntimeDependenciesLive = pullRequestServiceFactoryLayer.pipe(require_Schema$1.provideMerge(RuntimeDependenciesWithoutPullRequestsLive), require_Schema$1.provideMerge(cmmdProjectIdentityResolverLive.pipe(require_Schema$1.provide$1(RuntimeDependenciesWithoutPullRequestsLive))), require_Schema$1.provideMerge(pullRequestProviderRuntimeLive));
324956
325159
  const RuntimeServicesLive = ServerRuntimeStartupLive.pipe(require_Schema$1.provideMerge(RuntimeDependenciesLive));
324957
- const makeRoutesLayer = require_Schema$1.mergeAll(attachmentUploadRouteLayer, authBearerBootstrapRouteLayer, authBootstrapRouteLayer, authCommandBearerBootstrapRouteLayer, authCommandBootstrapRouteLayer, authCmmdEmbedExchangeRouteLayer, authOAuthTokenExchangeRouteLayer, authWebSocketTicketRouteLayer, authCmmdOAuthDeviceRouteLayer, authCmmdOAuthTokenRouteLayer, authCmmdPasswordTokenRouteLayer, authClientsRevokeOthersRouteLayer, authClientsRevokeRouteLayer, authClientsRouteLayer, authLogoutRouteLayer, authPairingLinksRevokeRouteLayer, authPairingLinksRouteLayer, authPairingCredentialRouteLayer, authSessionRenewRouteLayer, authSessionRouteLayer, authWebSocketTokenRouteLayer, authWebLoginRouteLayer, authWebCallbackRouteLayer, cloudOwnerSessionRedeemRouteLayer, cloudOwnerSessionRevokeRouteLayer, desktopLocalWebBridgePublishRouteLayer, desktopLocalWebBridgeBootstrapRouteLayer, desktopRelayControlPlaneRouteLayer, apiDocsHtmlRouteLayer, apiDocsOpenApiRouteLayer, pulseSignalStateListRouteLayer, pulseSignalStateUpsertRouteLayer, cmmdProfileRouteLayer, ...cmmdProxyRouteLayers, cmmdWorkIntakeRouteLayer, cmmdWsTokenRouteLayer, cmmdGetProjectCommentsRouteLayer, cmmdAddProjectCommentRouteLayer, cmmdUpdateProjectRouteLayer, cmmdUploadTaskAttachmentRouteLayer, cmmdUpdateTaskCommentRouteLayer, cmmdListWorkspaceMembersRouteLayer, cmmdAddProjectMemberRouteLayer, cmmdUpdateProjectAgentMemberAvatarRouteLayer, runtimeReplicationStatusRouteLayer, cmmdRefreshProviderUsageRouteLayer, cmmdForgeCloudProjectsListRouteLayer, cmmdForgeCloudProjectsEventsRouteLayer, cmmdForgeEnvironmentsEventsRouteLayer, cmmdForgeRuntimesEnsureRouteLayer, cmmdForgeRuntimesConnectRouteLayer, ownerRuntimeCodexReadinessRouteLayer, cmmdForgeRuntimesStatusRouteLayer, cmmdForgeRuntimesStartRouteLayer, cmmdForgeRuntimesStopRouteLayer, cmmdForgeRuntimesRecycleRouteLayer, cmmdForgeRuntimesUpdateCommitRouteLayer, cmmdForgeRuntimesDestroyRouteLayer, mobileProviderCatalogRouteLayer, attachmentsRouteLayer, orchestrationDispatchRouteLayer, orchestrationCmmdWorkRunEventRouteLayer, orchestrationAutomationStartThreadRouteLayer, orchestrationAutomationRebindRouteLayer, orchestrationAutomationTerminalReconcileRouteLayer, mobileGitRunStackedActionRouteLayer, pullRequestDiffRouteLayer, orchestrationSnapshotRouteLayer, orchestrationThreadSnapshotRouteLayer, localAutomationListRouteLayer, localAutomationCreateRouteLayer, localAutomationUpdateRouteLayer, localAutomationDeleteRouteLayer, localAutomationRunRouteLayer, otlpTracesProxyRouteLayer, devTunnelProxyRouteLayer, devTunnelLocalPortProxyRouteLayer, projectFaviconRouteLayer, serverEnvironmentRouteLayer, browserWebRtcReadinessRouteLayer, staticAndDevRouteLayer, githubStatusRouteLayer, githubAuthorizeUrlRouteLayer, githubDisconnectRouteLayer, githubReposRouteLayer, githubCloneRouteLayer, githubCloneJobStartRouteLayer, githubCloneJobStatusRouteLayer, githubRefreshCredentialsRouteLayer, githubToolConfirmationApproveRouteLayer, projectLinkGetRouteLayer, projectLinkListRouteLayer, projectLinkSetRouteLayer, projectLinkDeleteRouteLayer, cmmdWorkspacesRouteLayer, cmmdCampaignsRouteLayer, cmmdProjectLinksRouteLayer, cmmdEnsureGitHubProjectContextRouteLayer, cmmdProjectRepositoryEnsureRouteLayer, cmmdProjectsGetRouteLayer, cmmdProjectsCreateRouteLayer, workspaceReadinessRouteLayer, runtimeLivenessRouteLayer, runtimeFilesystemHealthRouteLayer, claudeNativeGenerationProofRouteLayer, claudeUsageRouteLayer, codexRuntimeProviderReadinessRouteLayer, runtimeDiagnosticsRouteLayer, cloudFoldersRouteLayer, cloudProjectCreateRouteLayer, gitUrlCloneRouteLayer, websocketRpcRouteLayer).pipe(require_Schema$1.provide$1(browserApiCorsLayer));
325160
+ const makeRoutesLayer = require_Schema$1.mergeAll(attachmentUploadRouteLayer, authBearerBootstrapRouteLayer, authBootstrapRouteLayer, authCommandBearerBootstrapRouteLayer, authCommandBootstrapRouteLayer, authCmmdEmbedExchangeRouteLayer, authOAuthTokenExchangeRouteLayer, authWebSocketTicketRouteLayer, authCmmdOAuthDeviceRouteLayer, authCmmdOAuthTokenRouteLayer, authCmmdPasswordTokenRouteLayer, authClientsRevokeOthersRouteLayer, authClientsRevokeRouteLayer, authClientsRouteLayer, authLogoutRouteLayer, authPairingLinksRevokeRouteLayer, authPairingLinksRouteLayer, authPairingCredentialRouteLayer, authSessionRenewRouteLayer, authSessionRouteLayer, authWebSocketTokenRouteLayer, authWebLoginRouteLayer, authWebCallbackRouteLayer, cloudOwnerSessionRedeemRouteLayer, cloudOwnerSessionRevokeRouteLayer, desktopLocalWebBridgePublishRouteLayer, desktopLocalWebBridgeBootstrapRouteLayer, desktopRelayControlPlaneRouteLayer, apiDocsHtmlRouteLayer, apiDocsOpenApiRouteLayer, pulseSignalStateListRouteLayer, pulseSignalStateUpsertRouteLayer, cmmdProfileRouteLayer, ...cmmdProxyRouteLayers, cmmdWorkIntakeRouteLayer, cmmdWsTokenRouteLayer, cmmdGetProjectCommentsRouteLayer, cmmdAddProjectCommentRouteLayer, cmmdUpdateProjectRouteLayer, cmmdUploadTaskAttachmentRouteLayer, cmmdUpdateTaskCommentRouteLayer, cmmdListWorkspaceMembersRouteLayer, cmmdAddProjectMemberRouteLayer, cmmdUpdateProjectAgentMemberAvatarRouteLayer, runtimeReplicationStatusRouteLayer, cmmdRefreshProviderUsageRouteLayer, cmmdForgeCloudProjectsListRouteLayer, cmmdForgeCloudProjectsEventsRouteLayer, cmmdForgeEnvironmentsEventsRouteLayer, cmmdForgeRuntimesEnsureRouteLayer, cmmdForgeRuntimesConnectRouteLayer, ownerRuntimeCodexReadinessRouteLayer, cmmdRegisterMobilePushDeviceRouteLayer, cmmdDeleteMobilePushDeviceRouteLayer, cmmdForgeRuntimesStatusRouteLayer, cmmdForgeRuntimesStartRouteLayer, cmmdForgeRuntimesStopRouteLayer, cmmdForgeRuntimesRecycleRouteLayer, cmmdForgeRuntimesUpdateCommitRouteLayer, cmmdForgeRuntimesDestroyRouteLayer, mobileProviderCatalogRouteLayer, attachmentsRouteLayer, orchestrationDispatchRouteLayer, orchestrationCmmdWorkRunEventRouteLayer, orchestrationAutomationStartThreadRouteLayer, orchestrationAutomationRebindRouteLayer, orchestrationAutomationTerminalReconcileRouteLayer, mobileGitRunStackedActionRouteLayer, pullRequestDiffRouteLayer, orchestrationSnapshotRouteLayer, orchestrationThreadSnapshotRouteLayer, localAutomationListRouteLayer, localAutomationCreateRouteLayer, localAutomationUpdateRouteLayer, localAutomationDeleteRouteLayer, localAutomationRunRouteLayer, otlpTracesProxyRouteLayer, devTunnelProxyRouteLayer, devTunnelLocalPortProxyRouteLayer, projectFaviconRouteLayer, serverEnvironmentRouteLayer, browserWebRtcReadinessRouteLayer, staticAndDevRouteLayer, githubStatusRouteLayer, githubAuthorizeUrlRouteLayer, githubDisconnectRouteLayer, githubReposRouteLayer, githubCloneRouteLayer, githubCloneJobStartRouteLayer, githubCloneJobStatusRouteLayer, githubRefreshCredentialsRouteLayer, githubToolConfirmationApproveRouteLayer, projectLinkGetRouteLayer, projectLinkListRouteLayer, projectLinkSetRouteLayer, projectLinkDeleteRouteLayer, cmmdWorkspacesRouteLayer, cmmdCampaignsRouteLayer, cmmdProjectLinksRouteLayer, cmmdEnsureGitHubProjectContextRouteLayer, cmmdProjectRepositoryEnsureRouteLayer, cmmdProjectsGetRouteLayer, cmmdProjectsCreateRouteLayer, workspaceReadinessRouteLayer, runtimeLivenessRouteLayer, runtimeFilesystemHealthRouteLayer, claudeNativeGenerationProofRouteLayer, claudeUsageRouteLayer, codexRuntimeProviderReadinessRouteLayer, runtimeDiagnosticsRouteLayer, cloudFoldersRouteLayer, cloudProjectCreateRouteLayer, gitUrlCloneRouteLayer, websocketRpcRouteLayer).pipe(require_Schema$1.provide$1(browserApiCorsLayer));
324958
325161
  const makeServerLayer = require_Schema$1.unwrap(require_Schema$1.gen(function* () {
324959
325162
  const config = yield* ServerConfig;
324960
325163
  fixPath({ preferProcessPath: config.forgeCmmdRuntimeMode === true });