@rubytech/create-maxy-code 0.1.459 → 0.1.460

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.
Files changed (145) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +116 -6
  3. package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
  4. package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.js +20 -0
  5. package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.js.map +1 -1
  6. package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.d.ts +2 -0
  7. package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.d.ts.map +1 -0
  8. package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.js +41 -0
  9. package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.js.map +1 -0
  10. package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +1 -0
  11. package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
  12. package/payload/platform/lib/storage-broker/dist/cf-exec.js +116 -48
  13. package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
  14. package/payload/platform/lib/storage-broker/dist/index.d.ts +1 -0
  15. package/payload/platform/lib/storage-broker/dist/index.d.ts.map +1 -1
  16. package/payload/platform/lib/storage-broker/dist/index.js +1 -0
  17. package/payload/platform/lib/storage-broker/dist/index.js.map +1 -1
  18. package/payload/platform/lib/storage-broker/dist/object-limits.d.ts +27 -0
  19. package/payload/platform/lib/storage-broker/dist/object-limits.d.ts.map +1 -1
  20. package/payload/platform/lib/storage-broker/dist/object-limits.js +27 -7
  21. package/payload/platform/lib/storage-broker/dist/object-limits.js.map +1 -1
  22. package/payload/platform/lib/storage-broker/dist/resource-limits.d.ts +102 -0
  23. package/payload/platform/lib/storage-broker/dist/resource-limits.d.ts.map +1 -0
  24. package/payload/platform/lib/storage-broker/dist/resource-limits.js +105 -0
  25. package/payload/platform/lib/storage-broker/dist/resource-limits.js.map +1 -0
  26. package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +130 -7
  27. package/payload/platform/lib/storage-broker/src/__tests__/object-limits.test.ts +30 -0
  28. package/payload/platform/lib/storage-broker/src/__tests__/resource-limits.test.ts +49 -0
  29. package/payload/platform/lib/storage-broker/src/cf-exec.ts +129 -56
  30. package/payload/platform/lib/storage-broker/src/index.ts +1 -0
  31. package/payload/platform/lib/storage-broker/src/object-limits.ts +26 -6
  32. package/payload/platform/lib/storage-broker/src/resource-limits.ts +105 -0
  33. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +5 -4
  34. package/payload/platform/plugins/cloudflare/PLUGIN.md +3 -1
  35. package/payload/platform/plugins/cloudflare/mcp/__tests__/auth-route.test.ts +206 -0
  36. package/payload/platform/plugins/cloudflare/mcp/__tests__/authorize.test.ts +201 -0
  37. package/payload/platform/plugins/cloudflare/mcp/__tests__/file-routes.test.ts +178 -0
  38. package/payload/platform/plugins/cloudflare/mcp/__tests__/harness.test.ts +32 -0
  39. package/payload/platform/plugins/cloudflare/mcp/__tests__/passcode.test.ts +74 -0
  40. package/payload/platform/plugins/cloudflare/mcp/__tests__/ratelimit.test.ts +77 -0
  41. package/payload/platform/plugins/cloudflare/mcp/__tests__/skill-contract.test.ts +46 -0
  42. package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +55 -0
  43. package/payload/platform/plugins/cloudflare/mcp/__tests__/upload-route.test.ts +255 -0
  44. package/payload/platform/plugins/cloudflare/mcp/package.json +5 -2
  45. package/payload/platform/plugins/cloudflare/references/r2-object-storage.md +46 -0
  46. package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +123 -0
  47. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/authorize.ts +32 -0
  48. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/log.ts +12 -0
  49. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/passcode.ts +73 -0
  50. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/ratelimit.ts +55 -0
  51. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/session.ts +85 -0
  52. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/types.ts +44 -0
  53. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/auth.ts +113 -0
  54. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/delete.ts +89 -0
  55. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/download.ts +70 -0
  56. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/files.ts +41 -0
  57. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/upload.ts +151 -0
  58. package/payload/platform/plugins/cloudflare/skills/data-portal/template/public/index.html +42 -0
  59. package/payload/platform/plugins/cloudflare/skills/data-portal/template/public/portal.css +113 -0
  60. package/payload/platform/plugins/cloudflare/skills/data-portal/template/public/portal.js +155 -0
  61. package/payload/platform/plugins/cloudflare/skills/data-portal/template/schema.sql +64 -0
  62. package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +21 -0
  63. package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +8 -0
  64. package/payload/platform/plugins/docs/references/outlook-guide.md +3 -3
  65. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +1 -0
  66. package/payload/platform/plugins/filesystem/PLUGIN.md +0 -1
  67. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +14 -10
  68. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
  69. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +14 -10
  70. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
  71. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
  72. package/payload/platform/plugins/outlook/PLUGIN.md +3 -5
  73. package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.d.ts +2 -0
  74. package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.d.ts.map +1 -0
  75. package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.js +75 -0
  76. package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.js.map +1 -0
  77. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.d.ts +2 -0
  78. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.d.ts.map +1 -0
  79. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.js +187 -0
  80. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.js.map +1 -0
  81. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js +1 -1
  82. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js.map +1 -1
  83. package/payload/platform/plugins/outlook/mcp/dist/index.js +3 -2
  84. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  85. package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.d.ts +43 -0
  86. package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.d.ts.map +1 -0
  87. package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.js +65 -0
  88. package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.js.map +1 -0
  89. package/payload/platform/plugins/outlook/mcp/dist/lib/detach.d.ts +65 -0
  90. package/payload/platform/plugins/outlook/mcp/dist/lib/detach.d.ts.map +1 -0
  91. package/payload/platform/plugins/outlook/mcp/dist/lib/detach.js +99 -0
  92. package/payload/platform/plugins/outlook/mcp/dist/lib/detach.js.map +1 -0
  93. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts +6 -1
  94. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts.map +1 -1
  95. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js.map +1 -1
  96. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts +42 -22
  97. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts.map +1 -1
  98. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js +59 -23
  99. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js.map +1 -1
  100. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.d.ts +15 -16
  101. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.d.ts.map +1 -1
  102. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.js +8 -41
  103. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.js.map +1 -1
  104. package/payload/platform/plugins/outlook/references/auth.md +1 -1
  105. package/payload/platform/plugins/outlook/references/graph-surfaces.md +7 -3
  106. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +1 -1
  107. package/payload/platform/plugins/storage-broker/PLUGIN.md +1 -1
  108. package/payload/platform/plugins/voice-mirror/PLUGIN.md +19 -7
  109. package/payload/platform/plugins/voice-mirror/mcp/dist/index.d.ts.map +1 -1
  110. package/payload/platform/plugins/voice-mirror/mcp/dist/index.js +35 -16
  111. package/payload/platform/plugins/voice-mirror/mcp/dist/index.js.map +1 -1
  112. package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.d.ts +31 -0
  113. package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.d.ts.map +1 -0
  114. package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.js +87 -0
  115. package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.js.map +1 -0
  116. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
  117. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js +13 -3
  118. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js.map +1 -1
  119. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -1
  120. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-ingest-session-text.js +2 -1
  121. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-ingest-session-text.js.map +1 -1
  122. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-record-feedback.d.ts.map +1 -1
  123. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-record-feedback.js +2 -1
  124. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-record-feedback.js.map +1 -1
  125. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.d.ts +2 -2
  126. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.d.ts.map +1 -1
  127. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.js +12 -3
  128. package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.js.map +1 -1
  129. package/payload/platform/plugins/voice-mirror/mcp/scripts/smoke.mjs +334 -0
  130. package/payload/platform/plugins/voice-mirror/skills/voice-mirror/SKILL.md +13 -0
  131. package/payload/platform/scripts/voice-author-key-audit.sh +155 -0
  132. package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.d.ts +17 -0
  133. package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.d.ts.map +1 -0
  134. package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.js +88 -0
  135. package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.js.map +1 -0
  136. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +0 -1
  137. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  138. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +34 -23
  139. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  140. package/payload/server/{chunk-Q6W4U6HL.js → chunk-JXWFVE5X.js} +83 -39
  141. package/payload/server/server.js +213 -38
  142. package/payload/server/{src-3I2RYZFB.js → src-4F37OHLK.js} +11 -1
  143. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts +0 -2
  144. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js +0 -215
  145. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js.map +0 -1
@@ -113,15 +113,19 @@ import {
113
113
  writeAdminUserAndPerson
114
114
  } from "./chunk-POBXIHOF.js";
115
115
  import {
116
+ D1_MAX_SQL_STATEMENT_BYTES,
117
+ D1_QUERY_MAX_BODY_BYTES,
118
+ R2_OBJECT_ENVELOPE_MAX_BODY_BYTES,
116
119
  R2_OBJECT_MAX_BYTES,
117
120
  R2_OBJECT_PUT_MAX_BODY_BYTES,
121
+ STORAGE_RESOURCE_NAME_MAX_BODY_BYTES,
118
122
  authorizeAccess,
119
123
  listResources,
120
124
  makeHouseCfExec,
121
125
  registerResource,
122
126
  resolveOwner,
123
127
  tooLargeMessage
124
- } from "./chunk-Q6W4U6HL.js";
128
+ } from "./chunk-JXWFVE5X.js";
125
129
  import {
126
130
  __commonJS,
127
131
  __toESM
@@ -8745,6 +8749,49 @@ function log(action, kind, account, target, owner, result, reason) {
8745
8749
  function cfExec() {
8746
8750
  return makeHouseCfExec(platformRoot());
8747
8751
  }
8752
+ async function readJsonBody(c) {
8753
+ let parsed;
8754
+ try {
8755
+ parsed = await c.req.json();
8756
+ } catch (err) {
8757
+ if (err instanceof Error && err.name === "BodyLimitError") throw err;
8758
+ return { ok: false, res: c.json({ error: "invalid-json" }, 400) };
8759
+ }
8760
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
8761
+ return { ok: false, res: c.json({ error: "invalid-json" }, 400) };
8762
+ }
8763
+ return { ok: true, body: parsed };
8764
+ }
8765
+ function nameBodyLimit(kind) {
8766
+ return bodyLimit({
8767
+ maxSize: STORAGE_RESOURCE_NAME_MAX_BODY_BYTES,
8768
+ onError: (c) => {
8769
+ log("write", kind, caller(c) ?? "none", "*", null, "deny", "name-body-too-large");
8770
+ return c.json(
8771
+ {
8772
+ error: `request body exceeds the ${(STORAGE_RESOURCE_NAME_MAX_BODY_BYTES / 1024).toFixed(
8773
+ 1
8774
+ )} KiB (${STORAGE_RESOURCE_NAME_MAX_BODY_BYTES} bytes) limit for a storage resource create, which carries only a name.`
8775
+ },
8776
+ 413
8777
+ );
8778
+ }
8779
+ });
8780
+ }
8781
+ var d1QueryBodyLimit = bodyLimit({
8782
+ maxSize: D1_QUERY_MAX_BODY_BYTES,
8783
+ onError: (c) => {
8784
+ log("read", "d1", caller(c) ?? "none", "*", null, "deny", "sql-body-too-large");
8785
+ return c.json(
8786
+ {
8787
+ error: `request body exceeds the ${(D1_QUERY_MAX_BODY_BYTES / 1024 / 1024).toFixed(
8788
+ 1
8789
+ )} MiB (${D1_QUERY_MAX_BODY_BYTES} bytes) limit for a D1 query, which carries a database name and a SQL statement of at most ${D1_MAX_SQL_STATEMENT_BYTES} bytes.`
8790
+ },
8791
+ 413
8792
+ );
8793
+ }
8794
+ });
8748
8795
  app3.get("/d1/list", async (c) => {
8749
8796
  const account = caller(c);
8750
8797
  if (!account) return c.json({ error: "no-caller" }, 403);
@@ -8759,10 +8806,12 @@ app3.get("/d1/list", async (c) => {
8759
8806
  await session.close();
8760
8807
  }
8761
8808
  });
8762
- app3.post("/d1/create", async (c) => {
8809
+ app3.post("/d1/create", nameBodyLimit("d1"), async (c) => {
8763
8810
  const account = caller(c);
8764
8811
  if (!account) return c.json({ error: "no-caller" }, 403);
8765
- const { name } = await c.req.json();
8812
+ const parsed = await readJsonBody(c);
8813
+ if (!parsed.ok) return parsed.res;
8814
+ const { name } = parsed.body;
8766
8815
  if (!name || typeof name !== "string") return c.json({ error: "name-required" }, 400);
8767
8816
  const session = getSession();
8768
8817
  try {
@@ -8781,10 +8830,12 @@ app3.post("/d1/create", async (c) => {
8781
8830
  await session.close();
8782
8831
  }
8783
8832
  });
8784
- app3.post("/d1/query", async (c) => {
8833
+ app3.post("/d1/query", d1QueryBodyLimit, async (c) => {
8785
8834
  const account = caller(c);
8786
8835
  if (!account) return c.json({ error: "no-caller" }, 403);
8787
- const { name, sql } = await c.req.json();
8836
+ const parsed = await readJsonBody(c);
8837
+ if (!parsed.ok) return parsed.res;
8838
+ const { name, sql } = parsed.body;
8788
8839
  if (!name || typeof name !== "string") return c.json({ error: "name-required" }, 400);
8789
8840
  if (!sql || typeof sql !== "string") return c.json({ error: "sql-required" }, 400);
8790
8841
  const session = getSession();
@@ -8815,10 +8866,12 @@ app3.get("/r2/list", async (c) => {
8815
8866
  await session.close();
8816
8867
  }
8817
8868
  });
8818
- app3.post("/r2/create", async (c) => {
8869
+ app3.post("/r2/create", nameBodyLimit("r2"), async (c) => {
8819
8870
  const account = caller(c);
8820
8871
  if (!account) return c.json({ error: "no-caller" }, 403);
8821
- const { name } = await c.req.json();
8872
+ const parsed = await readJsonBody(c);
8873
+ if (!parsed.ok) return parsed.res;
8874
+ const { name } = parsed.body;
8822
8875
  if (!name || typeof name !== "string") return c.json({ error: "name-required" }, 400);
8823
8876
  const session = getSession();
8824
8877
  try {
@@ -8869,7 +8922,39 @@ function readKey(body) {
8869
8922
  const key = body.key;
8870
8923
  return typeof key === "string" && key.length > 0 ? key : null;
8871
8924
  }
8872
- app3.post("/r2/object/list", async (c) => {
8925
+ function envelopeBodyLimit(action) {
8926
+ return bodyLimit({
8927
+ maxSize: R2_OBJECT_ENVELOPE_MAX_BODY_BYTES,
8928
+ // Names the limit rather than the object: the body is deliberately unparsed
8929
+ // here, which is the whole point of the middleware, so the key is genuinely
8930
+ // unknown — as recorded for put in 1695. Stated in KiB with exact bytes rather
8931
+ // than the MiB the object messages use: 64 KiB renders as "0.1 MiB", which is
8932
+ // less legible, not more. The exact bytes are there for the same reason
8933
+ // tooLargeMessage carries them.
8934
+ //
8935
+ // The {error} body is the routes' convention, which the default's bare text
8936
+ // is not. On the content-length branch no body is read and no handler runs, so
8937
+ // this log line is the only trace the request ever existed.
8938
+ //
8939
+ // reason distinguishes this from put's body-too-large rather than reusing it.
8940
+ // They are different events refusing bodies ~2,100x apart, and put and delete
8941
+ // both log action=write, so a shared slug would make a 140 MB put denial and a
8942
+ // 65 KiB delete denial byte-identical — the same conflation the reason field
8943
+ // exists to prevent for ownership-vs-size.
8944
+ onError: (c) => {
8945
+ log(action, "r2", caller(c) ?? "none", "*", null, "deny", "envelope-too-large");
8946
+ return c.json(
8947
+ {
8948
+ error: `request body exceeds the ${(R2_OBJECT_ENVELOPE_MAX_BODY_BYTES / 1024).toFixed(
8949
+ 1
8950
+ )} KiB (${R2_OBJECT_ENVELOPE_MAX_BODY_BYTES} bytes) limit for an R2 object metadata envelope, which carries only a bucket and a key or prefix.`
8951
+ },
8952
+ 413
8953
+ );
8954
+ }
8955
+ });
8956
+ }
8957
+ app3.post("/r2/object/list", envelopeBodyLimit("list"), async (c) => {
8873
8958
  const gate = await objectGate(c, "list");
8874
8959
  if (!gate.ok) return gate.res;
8875
8960
  const prefix = gate.body.prefix;
@@ -8883,15 +8968,15 @@ app3.post("/r2/object/list", async (c) => {
8883
8968
  return c.json({ error: String(err) }, 500);
8884
8969
  }
8885
8970
  });
8886
- app3.post("/r2/object/get", async (c) => {
8971
+ app3.post("/r2/object/get", envelopeBodyLimit("read"), async (c) => {
8887
8972
  const gate = await objectGate(c, "read");
8888
8973
  if (!gate.ok) return gate.res;
8889
8974
  const key = readKey(gate.body);
8890
8975
  if (!key) return c.json({ error: "key-required" }, 400);
8891
8976
  try {
8892
8977
  const cf = await cfExec();
8893
- const listed = await cf.r2ObjectList(gate.bucket, key);
8894
- const size = listed.find((o) => o.key === key)?.size;
8978
+ const found = await cf.r2ObjectFind(gate.bucket, key);
8979
+ const size = found?.size;
8895
8980
  if (typeof size !== "number" || !Number.isFinite(size) || size < 0) {
8896
8981
  log("read", "r2", caller(c) ?? "none", key, caller(c), "deny", "size-unknown");
8897
8982
  return c.json(
@@ -8962,7 +9047,7 @@ app3.post(
8962
9047
  }
8963
9048
  }
8964
9049
  );
8965
- app3.post("/r2/object/delete", async (c) => {
9050
+ app3.post("/r2/object/delete", envelopeBodyLimit("write"), async (c) => {
8966
9051
  const gate = await objectGate(c, "write");
8967
9052
  if (!gate.ok) return gate.res;
8968
9053
  const key = readKey(gate.body);
@@ -8976,7 +9061,7 @@ app3.post("/r2/object/delete", async (c) => {
8976
9061
  });
8977
9062
  var storage_broker_default = app3;
8978
9063
  async function runStorageAudit(root) {
8979
- const { reconcileStorage } = await import("./src-3I2RYZFB.js");
9064
+ const { reconcileStorage } = await import("./src-4F37OHLK.js");
8980
9065
  const session = getSession();
8981
9066
  try {
8982
9067
  const cf = await makeHouseCfExec(root);
@@ -9901,6 +9986,78 @@ function pickActivity(entries, grown, nowMs, concurrencyWindowMs) {
9901
9986
  return { hex: newest.hex, lastEmitAt: newest.mtimeMs, count };
9902
9987
  }
9903
9988
 
9989
+ // server/routes/stream-lifecycle.ts
9990
+ var GAUGE_INTERVAL_MS = 6e4;
9991
+ function isArmed(timer2) {
9992
+ return timer2._destroyed !== true;
9993
+ }
9994
+ var Registration = class {
9995
+ constructor(connId, channel, startedAt) {
9996
+ this.connId = connId;
9997
+ this.channel = channel;
9998
+ this.startedAt = startedAt;
9999
+ }
10000
+ timers = [];
10001
+ closed = false;
10002
+ arm(timer2) {
10003
+ this.timers.push(timer2);
10004
+ return timer2;
10005
+ }
10006
+ teardown(reason) {
10007
+ if (this.closed) return false;
10008
+ this.closed = true;
10009
+ for (const t of this.timers) clearInterval(t);
10010
+ const stillArmed = this.timers.filter(isArmed).length;
10011
+ if (stillArmed > 0) {
10012
+ console.error(
10013
+ `[wa-stream] op=teardown-defect conn=${this.connId} channel=${this.channel} stillArmed=${stillArmed} reason=${reason}`
10014
+ );
10015
+ return true;
10016
+ }
10017
+ registry.delete(this);
10018
+ if (registry.size === 0) emitGauge();
10019
+ return true;
10020
+ }
10021
+ };
10022
+ var registry = /* @__PURE__ */ new Set();
10023
+ var gaugeTimer = null;
10024
+ function emitGauge() {
10025
+ const now = Date.now();
10026
+ const counts = { reader: 0, store: 0 };
10027
+ let oldestMs = 0;
10028
+ let stale = 0;
10029
+ for (const reg of [...registry]) {
10030
+ if (!reg.timers.some(isArmed)) {
10031
+ stale++;
10032
+ registry.delete(reg);
10033
+ continue;
10034
+ }
10035
+ counts[reg.channel]++;
10036
+ oldestMs = Math.max(oldestMs, now - reg.startedAt);
10037
+ }
10038
+ const armed = counts.reader + counts.store;
10039
+ console.log(
10040
+ `[wa-stream] op=gauge armed=${armed} reader=${counts.reader} store=${counts.store} oldestSec=${Math.floor(oldestMs / 1e3)} stale=${stale}`
10041
+ );
10042
+ if (armed === 0) stopGauge();
10043
+ }
10044
+ function startGauge() {
10045
+ if (gaugeTimer) return;
10046
+ gaugeTimer = setInterval(emitGauge, GAUGE_INTERVAL_MS);
10047
+ gaugeTimer.unref();
10048
+ }
10049
+ function stopGauge() {
10050
+ if (!gaugeTimer) return;
10051
+ clearInterval(gaugeTimer);
10052
+ gaugeTimer = null;
10053
+ }
10054
+ function openStream(connId, channel, startedAt) {
10055
+ const reg = new Registration(connId, channel, startedAt);
10056
+ registry.add(reg);
10057
+ startGauge();
10058
+ return reg;
10059
+ }
10060
+
9904
10061
  // app/admin-types.ts
9905
10062
  var ACCEPT_MIME = "image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html,text/calendar,application/zip,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.text,text/rtf,application/rtf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.oasis.opendocument.spreadsheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.ms-powerpoint,application/vnd.oasis.opendocument.presentation,audio/ogg,audio/opus,audio/mp4,audio/x-m4a,audio/mpeg,audio/webm,audio/wav,video/mp4,.docx,.odt,.rtf,.xlsx,.xls,.ods,.pptx,.ppt,.odp,.opus,.ogg,.m4a,.mp4,.mp3,.wav,.webm";
9906
10063
  var SUPPORTED_MIME_SET = new Set(ACCEPT_MIME.split(",").filter((t) => !t.startsWith(".")));
@@ -10209,6 +10366,8 @@ data: ${JSON.stringify(turn)}
10209
10366
  const connId = `${sessionId.slice(0, 8)}-${process.hrtime.bigint().toString(36).slice(-6)}`;
10210
10367
  const startedAt = Date.now();
10211
10368
  const lastEventId = c.req.header("Last-Event-ID");
10369
+ let teardown = () => {
10370
+ };
10212
10371
  const readable = new ReadableStream({
10213
10372
  start(controller) {
10214
10373
  const fileEnd0 = (() => {
@@ -10293,27 +10452,34 @@ data: ${JSON.stringify(obj)}
10293
10452
  actx.now = Date.now();
10294
10453
  runActivityTick(actx);
10295
10454
  };
10296
- const poll = setInterval(tick, 1e3);
10297
- const heartbeat = setInterval(() => {
10298
- try {
10299
- controller.enqueue(encoder.encode(": ping\n\n"));
10300
- console.log(`[wa-stream] op=heartbeat conn=${connId}`);
10301
- } catch {
10302
- }
10303
- }, 2e4);
10304
- c.req.raw.signal.addEventListener("abort", () => {
10455
+ const lifecycle = openStream(connId, "reader", startedAt);
10456
+ lifecycle.arm(setInterval(tick, 1e3));
10457
+ lifecycle.arm(
10458
+ setInterval(() => {
10459
+ try {
10460
+ controller.enqueue(encoder.encode(": ping\n\n"));
10461
+ console.log(`[wa-stream] op=heartbeat conn=${connId}`);
10462
+ } catch {
10463
+ teardown("heartbeat-dead-controller");
10464
+ }
10465
+ }, 2e4)
10466
+ );
10467
+ teardown = (reason) => {
10468
+ if (!lifecycle.teardown(reason)) return;
10305
10469
  watcher?.close();
10306
- clearInterval(poll);
10307
- clearInterval(heartbeat);
10308
10470
  if (actx.emittedHex !== null) {
10309
10471
  console.log(`[webchat-activity] op=clear key=${sessionKey} reason=stream-close`);
10310
10472
  }
10311
- console.log(`[wa-stream] op=close conn=${connId} ranMs=${Date.now() - startedAt} reason=client-abort`);
10473
+ console.log(`[wa-stream] op=close conn=${connId} ranMs=${Date.now() - startedAt} reason=${reason}`);
10312
10474
  try {
10313
10475
  controller.close();
10314
10476
  } catch {
10315
10477
  }
10316
- });
10478
+ };
10479
+ c.req.raw.signal.addEventListener("abort", () => teardown("client-abort"));
10480
+ },
10481
+ cancel() {
10482
+ teardown("client-cancel");
10317
10483
  }
10318
10484
  });
10319
10485
  return new Response(readable, {
@@ -10421,6 +10587,8 @@ app5.get("/store-stream", requireAdminSession, (c) => {
10421
10587
  }
10422
10588
  return turn;
10423
10589
  };
10590
+ let teardown = () => {
10591
+ };
10424
10592
  const readable = new ReadableStream({
10425
10593
  start(controller) {
10426
10594
  const send = (turn, id) => {
@@ -10518,23 +10686,30 @@ data: ${JSON.stringify(payload)}
10518
10686
  watcher = watch(file, drain);
10519
10687
  } catch {
10520
10688
  }
10521
- const poll = setInterval(drain, 1e3);
10522
- const heartbeat = setInterval(() => {
10523
- try {
10524
- controller.enqueue(encoder.encode(": ping\n\n"));
10525
- } catch {
10526
- }
10527
- }, 2e4);
10528
- c.req.raw.signal.addEventListener("abort", () => {
10689
+ const lifecycle = openStream(connId, "store", startedAt);
10690
+ lifecycle.arm(setInterval(drain, 1e3));
10691
+ lifecycle.arm(
10692
+ setInterval(() => {
10693
+ try {
10694
+ controller.enqueue(encoder.encode(": ping\n\n"));
10695
+ } catch {
10696
+ teardown("heartbeat-dead-controller");
10697
+ }
10698
+ }, 2e4)
10699
+ );
10700
+ teardown = (reason) => {
10701
+ if (!lifecycle.teardown(reason)) return;
10529
10702
  watcher?.close();
10530
- clearInterval(poll);
10531
- clearInterval(heartbeat);
10532
- console.log(`[wa-reader] op=store-close conn=${connId} ranMs=${Date.now() - startedAt}`);
10703
+ console.log(`[wa-reader] op=store-close conn=${connId} ranMs=${Date.now() - startedAt} reason=${reason}`);
10533
10704
  try {
10534
10705
  controller.close();
10535
10706
  } catch {
10536
10707
  }
10537
- });
10708
+ };
10709
+ c.req.raw.signal.addEventListener("abort", () => teardown("client-abort"));
10710
+ },
10711
+ cancel() {
10712
+ teardown("client-cancel");
10538
10713
  }
10539
10714
  });
10540
10715
  return new Response(readable, {
@@ -1,7 +1,12 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
2
  import {
3
+ D1_MAX_SQL_STATEMENT_BYTES,
4
+ D1_QUERY_MAX_BODY_BYTES,
5
+ JSON_STRING_WORST_CASE_EXPANSION,
6
+ R2_OBJECT_ENVELOPE_MAX_BODY_BYTES,
3
7
  R2_OBJECT_MAX_BYTES,
4
8
  R2_OBJECT_PUT_MAX_BODY_BYTES,
9
+ STORAGE_RESOURCE_NAME_MAX_BODY_BYTES,
5
10
  authorizeAccess,
6
11
  base64Ceiling,
7
12
  listResources,
@@ -15,11 +20,16 @@ import {
15
20
  stripAccountWideTokens,
16
21
  tooLargeMessage,
17
22
  validateMapping
18
- } from "./chunk-Q6W4U6HL.js";
23
+ } from "./chunk-JXWFVE5X.js";
19
24
  import "./chunk-PFF6I7KP.js";
20
25
  export {
26
+ D1_MAX_SQL_STATEMENT_BYTES,
27
+ D1_QUERY_MAX_BODY_BYTES,
28
+ JSON_STRING_WORST_CASE_EXPANSION,
29
+ R2_OBJECT_ENVELOPE_MAX_BODY_BYTES,
21
30
  R2_OBJECT_MAX_BYTES,
22
31
  R2_OBJECT_PUT_MAX_BODY_BYTES,
32
+ STORAGE_RESOURCE_NAME_MAX_BODY_BYTES,
23
33
  authorizeAccess,
24
34
  base64Ceiling,
25
35
  listResources,
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=pkce-flow.test.d.ts.map
@@ -1,215 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import { _internals, startPkceFlow } from "../auth/pkce-flow.js";
4
- const { sameLengthEqual } = _internals;
5
- // ---------------------------------------------------------------------------
6
- // sameLengthEqual: timing-safe state comparison
7
- // ---------------------------------------------------------------------------
8
- test("sameLengthEqual matches identical strings", () => {
9
- assert.equal(sameLengthEqual("abcdef0123456789", "abcdef0123456789"), true);
10
- });
11
- test("sameLengthEqual rejects different equal-length strings", () => {
12
- assert.equal(sameLengthEqual("abcdef0123456789", "abcdef0123456780"), false);
13
- });
14
- test("sameLengthEqual rejects length mismatch without throwing", () => {
15
- assert.equal(sameLengthEqual("short", "longerstring"), false);
16
- });
17
- function mockFetch(handler) {
18
- const calls = [];
19
- const original = globalThis.fetch;
20
- globalThis.fetch = (async (url, init) => {
21
- const urlStr = typeof url === "string" ? url : url instanceof URL ? url.toString() : url.url;
22
- // Pass loopback callbacks through to the real fetch — only the upstream
23
- // token endpoint is intercepted. Otherwise the test's own callback
24
- // request would loop back into the mock and never reach the bound server.
25
- if (urlStr.startsWith("http://127.0.0.1:") || urlStr.startsWith("http://localhost:")) {
26
- return original(url, init);
27
- }
28
- calls.push({ url: urlStr, init });
29
- return handler(urlStr, init);
30
- });
31
- return {
32
- calls,
33
- restore: () => {
34
- globalThis.fetch = original;
35
- },
36
- };
37
- }
38
- function tokenSuccess() {
39
- return new Response(JSON.stringify({
40
- access_token: "test-access",
41
- refresh_token: "test-refresh",
42
- expires_in: 3600,
43
- token_type: "Bearer",
44
- scope: "offline_access User.Read Mail.ReadWrite Mail.Send Calendars.ReadWrite Contacts.Read",
45
- }), { status: 200, headers: { "Content-Type": "application/json" } });
46
- }
47
- function extractStateFromAuthUrl(authUrl) {
48
- const url = new URL(authUrl);
49
- const state = url.searchParams.get("state");
50
- assert.ok(state, "auth URL must include state param");
51
- return state;
52
- }
53
- function extractRedirectUriPort(redirectUri) {
54
- const url = new URL(redirectUri);
55
- return Number(url.port);
56
- }
57
- test("PKCE happy path: state matches → tokens exchanged", async () => {
58
- const fetchMock = mockFetch(() => tokenSuccess());
59
- try {
60
- const flow = await startPkceFlow({
61
- clientId: "test-client",
62
- tenantId: "common",
63
- accountId: "acct-pkce-1",
64
- });
65
- const state = extractStateFromAuthUrl(flow.authUrl);
66
- const port = extractRedirectUriPort(flow.redirectUri);
67
- // Drive the callback synthetically, as Microsoft would after consent.
68
- const callbackResp = await fetch(`http://127.0.0.1:${port}/callback?code=fake-code&state=${state}`);
69
- assert.equal(callbackResp.status, 200);
70
- const result = await flow.result;
71
- assert.equal(result.tokenResponse.access_token, "test-access");
72
- assert.equal(result.tokenResponse.refresh_token, "test-refresh");
73
- assert.deepEqual(result.scopes.sort(), [
74
- "Calendars.ReadWrite",
75
- "Contacts.Read",
76
- "Mail.ReadWrite",
77
- "Mail.Send",
78
- "User.Read",
79
- "offline_access",
80
- ].sort());
81
- // Token endpoint was called with code + verifier + redirect_uri.
82
- assert.equal(fetchMock.calls.length, 1);
83
- const body = String(fetchMock.calls[0].init?.body ?? "");
84
- assert.match(body, /code=fake-code/);
85
- assert.match(body, /code_verifier=/);
86
- assert.match(body, /grant_type=authorization_code/);
87
- }
88
- finally {
89
- fetchMock.restore();
90
- }
91
- });
92
- test("PKCE state mismatch → flow rejects, token endpoint NOT called", async () => {
93
- const fetchMock = mockFetch(() => {
94
- throw new Error("token endpoint should not be called on state mismatch");
95
- });
96
- try {
97
- const flow = await startPkceFlow({
98
- clientId: "test-client",
99
- tenantId: "common",
100
- accountId: "acct-pkce-2",
101
- });
102
- // Subscribe BEFORE driving the callback — otherwise the rejection lands
103
- // before any handler is attached and Node flags it as unhandled.
104
- const rejection = assert.rejects(flow.result, /State mismatch/i);
105
- const port = extractRedirectUriPort(flow.redirectUri);
106
- const cbResp = await fetch(`http://127.0.0.1:${port}/callback?code=fake-code&state=wrong-state-value`);
107
- assert.equal(cbResp.status, 400);
108
- await rejection;
109
- assert.equal(fetchMock.calls.length, 0, "token endpoint must not be called");
110
- }
111
- finally {
112
- fetchMock.restore();
113
- }
114
- });
115
- test("PKCE OAuth error in callback → flow rejects, no token call", async () => {
116
- const fetchMock = mockFetch(() => {
117
- throw new Error("token endpoint should not be called on OAuth error");
118
- });
119
- try {
120
- const flow = await startPkceFlow({
121
- clientId: "test-client",
122
- tenantId: "common",
123
- accountId: "acct-pkce-3",
124
- });
125
- const rejection = assert.rejects(flow.result, /OAuth error: access_denied/);
126
- const state = extractStateFromAuthUrl(flow.authUrl);
127
- const port = extractRedirectUriPort(flow.redirectUri);
128
- const cbResp = await fetch(`http://127.0.0.1:${port}/callback?error=access_denied&error_description=user%20cancelled&state=${state}`);
129
- assert.equal(cbResp.status, 400);
130
- await rejection;
131
- assert.equal(fetchMock.calls.length, 0);
132
- }
133
- finally {
134
- fetchMock.restore();
135
- }
136
- });
137
- test("PKCE callback missing code → flow rejects", async () => {
138
- const fetchMock = mockFetch(() => {
139
- throw new Error("token endpoint should not be called");
140
- });
141
- try {
142
- const flow = await startPkceFlow({
143
- clientId: "test-client",
144
- tenantId: "common",
145
- accountId: "acct-pkce-4",
146
- });
147
- const rejection = assert.rejects(flow.result, /No authorization code received/);
148
- const state = extractStateFromAuthUrl(flow.authUrl);
149
- const port = extractRedirectUriPort(flow.redirectUri);
150
- const cbResp = await fetch(`http://127.0.0.1:${port}/callback?state=${state}`);
151
- assert.equal(cbResp.status, 400);
152
- await rejection;
153
- assert.equal(fetchMock.calls.length, 0);
154
- }
155
- finally {
156
- fetchMock.restore();
157
- }
158
- });
159
- test("PKCE auth URL has S256 challenge + correct scopes + prompt=select_account", async () => {
160
- // No mock needed — we assert URL structure and abort the flow without
161
- // exchanging tokens. Sending an OAuth error in the callback closes the
162
- // server and rejects flow.result loudly; we catch it explicitly.
163
- const flow = await startPkceFlow({
164
- clientId: "client-X",
165
- tenantId: "common",
166
- accountId: "acct-pkce-5",
167
- });
168
- const expectedRejection = assert.rejects(flow.result, /OAuth error/);
169
- try {
170
- const url = new URL(flow.authUrl);
171
- assert.equal(url.searchParams.get("client_id"), "client-X");
172
- assert.equal(url.searchParams.get("response_type"), "code");
173
- assert.equal(url.searchParams.get("code_challenge_method"), "S256");
174
- assert.equal(url.searchParams.get("prompt"), "select_account");
175
- const challenge = url.searchParams.get("code_challenge");
176
- assert.ok(challenge && challenge.length > 30, "challenge should be base64url-encoded SHA-256");
177
- const scope = url.searchParams.get("scope") ?? "";
178
- assert.match(scope, /offline_access/);
179
- assert.match(scope, /User\.Read/);
180
- assert.match(scope, /Mail\.ReadWrite/);
181
- assert.match(scope, /Mail\.Send/);
182
- assert.match(scope, /Calendars\.ReadWrite/);
183
- assert.match(scope, /Contacts\.Read/);
184
- // Abort the flow by sending an OAuth error. Server closes; result rejects.
185
- const port = extractRedirectUriPort(flow.redirectUri);
186
- const state = url.searchParams.get("state");
187
- await fetch(`http://127.0.0.1:${port}/callback?error=access_denied&state=${state}`);
188
- }
189
- finally {
190
- await expectedRejection;
191
- }
192
- });
193
- test("PKCE redirect URI uses ephemeral loopback port (not fixed 49152)", async () => {
194
- // No token-exchange mock — abort each flow with an OAuth error so the
195
- // server closes without invoking exchangeCode.
196
- const flow1 = await startPkceFlow({ clientId: "c", tenantId: "common", accountId: "a1" });
197
- const flow2 = await startPkceFlow({ clientId: "c", tenantId: "common", accountId: "a2" });
198
- const r1 = assert.rejects(flow1.result, /OAuth error/);
199
- const r2 = assert.rejects(flow2.result, /OAuth error/);
200
- try {
201
- const port1 = extractRedirectUriPort(flow1.redirectUri);
202
- const port2 = extractRedirectUriPort(flow2.redirectUri);
203
- assert.ok(port1 > 0 && port1 < 65536);
204
- assert.ok(port2 > 0 && port2 < 65536);
205
- assert.notEqual(port1, port2, "two parallel flows must allocate different ephemeral ports");
206
- const s1 = extractStateFromAuthUrl(flow1.authUrl);
207
- const s2 = extractStateFromAuthUrl(flow2.authUrl);
208
- await fetch(`http://127.0.0.1:${port1}/callback?error=access_denied&state=${s1}`);
209
- await fetch(`http://127.0.0.1:${port2}/callback?error=access_denied&state=${s2}`);
210
- }
211
- finally {
212
- await Promise.all([r1, r2]);
213
- }
214
- });
215
- //# sourceMappingURL=pkce-flow.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pkce-flow.test.js","sourceRoot":"","sources":["../../src/__tests__/pkce-flow.test.ts"],"names":[],"mappings":"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"}