@pithy-sh/core 0.1.4 → 0.1.5

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 (264) hide show
  1. package/dist/address/address.d.ts +2 -0
  2. package/dist/address/address.js +2 -0
  3. package/dist/audit/auditEvent.d.ts +2 -0
  4. package/dist/audit/auditEvent.js +2 -0
  5. package/dist/audit/recorder.d.ts +2 -0
  6. package/dist/audit/recorder.js +2 -0
  7. package/dist/capability/bindings.d.ts +2 -0
  8. package/dist/capability/bindings.js +2 -0
  9. package/dist/capability/capability.d.ts +2 -0
  10. package/dist/capability/capability.js +2 -0
  11. package/dist/capability/client.d.ts +2 -0
  12. package/dist/capability/client.js +2 -0
  13. package/dist/capability/compose.d.ts +2 -0
  14. package/dist/capability/compose.js +2 -0
  15. package/dist/capability/composition.d.ts +2 -0
  16. package/dist/capability/composition.js +2 -0
  17. package/dist/capability/config.d.ts +2 -0
  18. package/dist/capability/config.js +2 -0
  19. package/dist/capability/devSecret.d.ts +2 -0
  20. package/dist/capability/devSecret.js +2 -0
  21. package/dist/capability/manifest.d.ts +2 -0
  22. package/dist/capability/manifest.js +2 -0
  23. package/dist/capability/secretOrigin.d.ts +2 -0
  24. package/dist/capability/secretOrigin.js +2 -0
  25. package/dist/capability/settings.d.ts +2 -0
  26. package/dist/capability/settings.js +2 -0
  27. package/dist/capability/validateBindings.d.ts +2 -0
  28. package/dist/capability/validateBindings.js +2 -0
  29. package/dist/capability/vanishingKey.d.ts +2 -0
  30. package/dist/capability/vanishingKey.js +2 -0
  31. package/dist/controlPlane/audit/actions.d.ts +2 -0
  32. package/dist/controlPlane/audit/actions.js +2 -0
  33. package/dist/controlPlane/capability.d.ts +2 -0
  34. package/dist/controlPlane/capability.js +2 -0
  35. package/dist/controlPlane/config/config.d.ts +2 -0
  36. package/dist/controlPlane/config/config.js +2 -0
  37. package/dist/controlPlane/context.d.ts +2 -0
  38. package/dist/controlPlane/context.js +2 -0
  39. package/dist/controlPlane/data/connection.d.ts +2 -0
  40. package/dist/controlPlane/data/connection.js +2 -0
  41. package/dist/controlPlane/data/keyLifecycle.d.ts +2 -0
  42. package/dist/controlPlane/data/keyLifecycle.js +2 -0
  43. package/dist/controlPlane/data/replay.d.ts +2 -0
  44. package/dist/controlPlane/data/replay.js +2 -0
  45. package/dist/controlPlane/data/tables.d.ts +2 -0
  46. package/dist/controlPlane/data/tables.js +2 -0
  47. package/dist/controlPlane/discovery/adminRoute.d.ts +2 -0
  48. package/dist/controlPlane/discovery/adminRoute.js +2 -0
  49. package/dist/controlPlane/discovery/configuration.d.ts +2 -0
  50. package/dist/controlPlane/discovery/configuration.js +2 -0
  51. package/dist/controlPlane/discovery/drift.d.ts +2 -0
  52. package/dist/controlPlane/discovery/drift.js +2 -0
  53. package/dist/controlPlane/discovery/health.d.ts +2 -0
  54. package/dist/controlPlane/discovery/health.js +2 -0
  55. package/dist/controlPlane/discovery/healthSummary.d.ts +2 -0
  56. package/dist/controlPlane/discovery/healthSummary.js +2 -0
  57. package/dist/controlPlane/error/errors.d.ts +2 -0
  58. package/dist/controlPlane/error/errors.js +2 -0
  59. package/dist/controlPlane/http/cors.d.ts +2 -0
  60. package/dist/controlPlane/http/cors.js +2 -0
  61. package/dist/controlPlane/http/guard.d.ts +2 -0
  62. package/dist/controlPlane/http/guard.js +2 -0
  63. package/dist/controlPlane/http/handlers.d.ts +2 -0
  64. package/dist/controlPlane/http/handlers.js +2 -0
  65. package/dist/controlPlane/http/responses.d.ts +2 -0
  66. package/dist/controlPlane/http/responses.js +2 -0
  67. package/dist/controlPlane/http/routes.d.ts +2 -0
  68. package/dist/controlPlane/http/routes.js +2 -0
  69. package/dist/controlPlane/http/schemas.d.ts +2 -0
  70. package/dist/controlPlane/http/schemas.js +2 -0
  71. package/dist/controlPlane/http/verify.d.ts +2 -0
  72. package/dist/controlPlane/http/verify.js +2 -0
  73. package/dist/controlPlane/migrations/0001_init.d.ts +2 -0
  74. package/dist/controlPlane/migrations/0001_init.js +2 -0
  75. package/dist/controlPlane/replay/d1Guard.d.ts +2 -0
  76. package/dist/controlPlane/replay/d1Guard.js +2 -0
  77. package/dist/controlPlane/replay/guard.d.ts +2 -0
  78. package/dist/controlPlane/replay/guard.js +2 -0
  79. package/dist/controlPlane/replay/kvGuard.d.ts +2 -0
  80. package/dist/controlPlane/replay/kvGuard.js +2 -0
  81. package/dist/controlPlane/scope/scope.d.ts +2 -0
  82. package/dist/controlPlane/scope/scope.js +2 -0
  83. package/dist/controlPlane/token/base64url.d.ts +2 -0
  84. package/dist/controlPlane/token/base64url.js +2 -0
  85. package/dist/controlPlane/token/claims.d.ts +2 -0
  86. package/dist/controlPlane/token/claims.js +2 -0
  87. package/dist/controlPlane/token/digest.d.ts +2 -0
  88. package/dist/controlPlane/token/digest.js +2 -0
  89. package/dist/controlPlane/token/jws.d.ts +2 -0
  90. package/dist/controlPlane/token/jws.js +2 -0
  91. package/dist/controlPlane/token/mint.d.ts +2 -0
  92. package/dist/controlPlane/token/mint.js +2 -0
  93. package/dist/controlPlane/wire.d.ts +2 -0
  94. package/dist/controlPlane/wire.js +2 -0
  95. package/dist/createBackend.d.ts +2 -0
  96. package/dist/createBackend.js +2 -0
  97. package/dist/createEntrypoint.d.ts +2 -0
  98. package/dist/createEntrypoint.js +2 -0
  99. package/dist/data/boundParameters.d.ts +2 -0
  100. package/dist/data/boundParameters.js +2 -0
  101. package/dist/data/codecs.d.ts +2 -0
  102. package/dist/data/codecs.js +2 -0
  103. package/dist/data/cursor.d.ts +2 -0
  104. package/dist/data/cursor.js +2 -0
  105. package/dist/data/databases.d.ts +2 -0
  106. package/dist/data/databases.js +2 -0
  107. package/dist/data/db.d.ts +2 -0
  108. package/dist/data/db.js +2 -0
  109. package/dist/data/withD1Retry.d.ts +2 -0
  110. package/dist/data/withD1Retry.js +2 -0
  111. package/dist/entitlement/entitlement.d.ts +2 -0
  112. package/dist/entitlement/entitlement.js +2 -0
  113. package/dist/entitlement/gateScan.d.ts +2 -0
  114. package/dist/entitlement/gateScan.js +2 -0
  115. package/dist/entitlement/require.d.ts +2 -0
  116. package/dist/entitlement/require.js +2 -0
  117. package/dist/env/ambient.d.ts +2 -0
  118. package/dist/env/ambient.js +2 -0
  119. package/dist/env/ci.d.ts +2 -0
  120. package/dist/env/ci.js +2 -0
  121. package/dist/env/stem.d.ts +2 -0
  122. package/dist/env/stem.js +2 -0
  123. package/dist/error/cause.d.ts +68 -0
  124. package/dist/error/cause.d.ts.map +1 -1
  125. package/dist/error/cause.js +94 -1
  126. package/dist/error/client.d.ts +2 -0
  127. package/dist/error/client.js +2 -0
  128. package/dist/error/extend.d.ts +2 -0
  129. package/dist/error/extend.js +2 -0
  130. package/dist/error/http.d.ts +2 -0
  131. package/dist/error/http.js +2 -0
  132. package/dist/error/payload.d.ts +2 -0
  133. package/dist/error/payload.js +2 -0
  134. package/dist/error/pithyError.d.ts +2 -0
  135. package/dist/error/pithyError.js +2 -0
  136. package/dist/error/terminal.d.ts +2 -0
  137. package/dist/error/terminal.js +2 -0
  138. package/dist/http/authContext.d.ts +2 -0
  139. package/dist/http/authContext.js +2 -0
  140. package/dist/http/routeContract.d.ts +2 -0
  141. package/dist/http/routeContract.js +2 -0
  142. package/dist/http/sameOrigin.d.ts +2 -0
  143. package/dist/http/sameOrigin.js +2 -0
  144. package/dist/http/signedWebhook.d.ts +2 -0
  145. package/dist/http/signedWebhook.js +2 -0
  146. package/dist/http/validation.d.ts +2 -0
  147. package/dist/http/validation.js +2 -0
  148. package/dist/http/verification.d.ts +2 -0
  149. package/dist/http/verification.js +2 -0
  150. package/dist/i18n/acceptLanguage.d.ts +2 -0
  151. package/dist/i18n/acceptLanguage.js +2 -0
  152. package/dist/i18n/catalog.d.ts +2 -0
  153. package/dist/i18n/catalog.js +2 -0
  154. package/dist/i18n/locale.d.ts +2 -0
  155. package/dist/i18n/locale.js +2 -0
  156. package/dist/i18n/localeMarker.d.ts +2 -0
  157. package/dist/i18n/localeMarker.js +2 -0
  158. package/dist/i18n/match.d.ts +2 -0
  159. package/dist/i18n/match.js +2 -0
  160. package/dist/i18n/registry.d.ts +2 -0
  161. package/dist/i18n/registry.js +2 -0
  162. package/dist/i18n/translator.d.ts +2 -0
  163. package/dist/i18n/translator.js +2 -0
  164. package/dist/index.d.ts +2 -0
  165. package/dist/index.js +2 -0
  166. package/dist/kv/kv.d.ts +2 -0
  167. package/dist/kv/kv.js +2 -0
  168. package/dist/kv/namespaces.d.ts +2 -0
  169. package/dist/kv/namespaces.js +2 -0
  170. package/dist/logger/local.d.ts +2 -0
  171. package/dist/logger/local.js +2 -0
  172. package/dist/logger/logger.d.ts +2 -0
  173. package/dist/logger/logger.js +2 -0
  174. package/dist/logger/record.d.ts +2 -0
  175. package/dist/logger/record.js +2 -0
  176. package/dist/logger/worker.d.ts +2 -0
  177. package/dist/logger/worker.js +2 -0
  178. package/dist/migrations/batch.d.ts +2 -0
  179. package/dist/migrations/batch.js +2 -0
  180. package/dist/migrations/bookkeeping.d.ts +2 -0
  181. package/dist/migrations/bookkeeping.js +2 -0
  182. package/dist/migrations/owner.d.ts +2 -0
  183. package/dist/migrations/owner.js +2 -0
  184. package/dist/migrations/registry.d.ts +2 -0
  185. package/dist/migrations/registry.js +2 -0
  186. package/dist/migrations/runner.d.ts +2 -0
  187. package/dist/migrations/runner.js +2 -0
  188. package/dist/naming/domains.d.ts +2 -0
  189. package/dist/naming/domains.js +2 -0
  190. package/dist/naming/environment.d.ts +2 -0
  191. package/dist/naming/environment.js +2 -0
  192. package/dist/naming/feature.d.ts +2 -0
  193. package/dist/naming/feature.js +2 -0
  194. package/dist/naming/limits.d.ts +2 -0
  195. package/dist/naming/limits.js +2 -0
  196. package/dist/naming/provisionScope.d.ts +2 -0
  197. package/dist/naming/provisionScope.js +2 -0
  198. package/dist/naming/resource.d.ts +2 -0
  199. package/dist/naming/resource.js +2 -0
  200. package/dist/naming/resourceNames.d.ts +2 -0
  201. package/dist/naming/resourceNames.js +2 -0
  202. package/dist/naming/segment.d.ts +2 -0
  203. package/dist/naming/segment.js +2 -0
  204. package/dist/projection/asRead.d.ts +2 -0
  205. package/dist/projection/asRead.js +2 -0
  206. package/dist/projection/published.d.ts +2 -0
  207. package/dist/projection/published.js +2 -0
  208. package/dist/schema/describedness.d.ts +2 -0
  209. package/dist/schema/describedness.js +2 -0
  210. package/dist/seed/compose.d.ts +2 -0
  211. package/dist/seed/compose.js +2 -0
  212. package/dist/seed/devLogin.d.ts +2 -0
  213. package/dist/seed/devLogin.js +2 -0
  214. package/dist/seed/exampleIdentities.d.ts +2 -0
  215. package/dist/seed/exampleIdentities.js +2 -0
  216. package/dist/seed/metadata.d.ts +2 -0
  217. package/dist/seed/metadata.js +2 -0
  218. package/dist/seed/seed.d.ts +2 -0
  219. package/dist/seed/seed.js +2 -0
  220. package/dist/seed/seededRows.d.ts +2 -0
  221. package/dist/seed/seededRows.js +2 -0
  222. package/dist/seed/writeD1.d.ts +2 -0
  223. package/dist/seed/writeD1.js +2 -0
  224. package/dist/seed/writeKv.d.ts +2 -0
  225. package/dist/seed/writeKv.js +2 -0
  226. package/dist/semver/semver.d.ts +2 -0
  227. package/dist/semver/semver.js +2 -0
  228. package/dist/text/comments.d.ts +2 -0
  229. package/dist/text/comments.js +2 -0
  230. package/dist/version.generated.d.ts +3 -1
  231. package/dist/version.generated.js +3 -1
  232. package/dist/worker/health.d.ts +2 -0
  233. package/dist/worker/health.js +2 -0
  234. package/dist/worker/identity.d.ts +2 -0
  235. package/dist/worker/identity.js +2 -0
  236. package/dist/workflow/bindings.d.ts +2 -0
  237. package/dist/workflow/bindings.js +2 -0
  238. package/dist/workflow/dispatch.d.ts +2 -0
  239. package/dist/workflow/dispatch.js +2 -0
  240. package/dist/workflow/dispatchRoute.d.ts +2 -0
  241. package/dist/workflow/dispatchRoute.js +2 -0
  242. package/dist/workflow/faults.d.ts +2 -0
  243. package/dist/workflow/faults.js +2 -0
  244. package/dist/workflow/host.d.ts +2 -0
  245. package/dist/workflow/host.js +2 -0
  246. package/dist/workflow/hostEntry.d.ts +2 -0
  247. package/dist/workflow/hostEntry.js +2 -0
  248. package/dist/workflow/hostEnv.d.ts +2 -0
  249. package/dist/workflow/hostEnv.js +2 -0
  250. package/dist/workflow/loopback.d.ts +2 -0
  251. package/dist/workflow/loopback.js +2 -0
  252. package/dist/workflow/naming.d.ts +2 -0
  253. package/dist/workflow/naming.js +2 -0
  254. package/dist/workflow/register.d.ts +2 -0
  255. package/dist/workflow/register.js +2 -0
  256. package/dist/workflow/schemas.d.ts +2 -0
  257. package/dist/workflow/schemas.js +2 -0
  258. package/dist/workflow/spec.d.ts +2 -0
  259. package/dist/workflow/spec.js +2 -0
  260. package/dist/workflow/stepMessage.d.ts +2 -0
  261. package/dist/workflow/stepMessage.js +2 -0
  262. package/package.json +2 -2
  263. package/src/error/cause.ts +116 -0
  264. package/src/version.generated.ts +1 -1
@@ -1,7 +1,9 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  //#region src/version.generated.ts
2
4
  /** This package's npm name — the join key against a release feed. */
3
5
  const PACKAGE_NAME = "@pithy-sh/core";
4
6
  /** This package's version, stamped from its own package.json at generation time. */
5
- const PACKAGE_VERSION = "0.1.4";
7
+ const PACKAGE_VERSION = "0.1.5";
6
8
  //#endregion
7
9
  export { PACKAGE_NAME, PACKAGE_VERSION };
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * **Where every Pithy Worker answers liveness — written once, read by everyone who needs it.**
3
5
  *
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  //#region src/worker/health.ts
2
4
  /**
3
5
  * **Where every Pithy Worker answers liveness — written once, read by everyone who needs it.**
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * What a running Worker knows about itself — the three vars every Pithy Worker is scaffolded with, and
3
5
  * the one reader for them.
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  //#region src/worker/identity.ts
2
4
  /**
3
5
  * What a running Worker knows about itself — the three vars every Pithy Worker is scaffolded with, and
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import type { BindingSpecInput } from "../capability/bindings";
2
4
  import type { RegisteredWorkflow, WorkflowSpec, WorkflowSpecMap } from "./spec";
3
5
  /**
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  //#region src/workflow/bindings.ts
2
4
  /**
3
5
  * The one derivation from a durable job to the `workflow` binding that job needs.
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import type { Logger } from "../logger/logger";
2
4
  import { type LoopbackFetch } from "./loopback";
3
5
  import type { WorkflowBinding, WorkflowRegistry } from "./spec";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { PithyError, messageOf } from "../error/pithyError.js";
2
4
  import "../worker/identity.js";
3
5
  import { noopLogger } from "../logger/logger.js";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import type { Hono } from "hono";
2
4
  import type { PithyHonoEnv } from "../capability/capability";
3
5
  import { type AmbientEnv } from "../env/ambient";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { ForbiddenError, PithyError } from "../error/pithyError.js";
2
4
  import { validationHook } from "../http/validation.js";
3
5
  import { WORKFLOW_DISPATCH_ROUTE, WorkflowDispatchParams, WorkflowDispatchRequest } from "./schemas.js";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * **Every fault that reaches a durable step is classified — retryable or terminal — at a stated site.**
3
5
  *
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { PithyError } from "../error/pithyError.js";
2
4
  import { d1TransientFault } from "../data/withD1Retry.js";
3
5
  import { encodeWorkflowStepMessage } from "./stepMessage.js";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { type WorkflowHostNameParts } from "./naming";
2
4
  import type { WorkflowRegistry } from "./spec";
3
5
  /**
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { InternalError } from "../error/pithyError.js";
2
4
  import { ENVIRONMENT_VAR, PROJECT_VAR } from "../worker/identity.js";
3
5
  import { workflowHostName, workflowScriptName } from "./naming.js";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * The default export of a Workflow host that serves nothing over HTTP (#426).
3
5
  *
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { NotFoundError } from "../error/pithyError.js";
2
4
  import { HttpError } from "../error/http.js";
3
5
  //#region src/workflow/hostEntry.ts
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { z } from "zod";
2
4
  import type { Logger } from "../logger/logger";
3
5
  /**
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { InternalError } from "../error/pithyError.js";
2
4
  import { createWorkerLogger } from "../logger/worker.js";
3
5
  import { z } from "zod";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import type { WorkflowBinding } from "./spec";
2
4
  /**
3
5
  * The loopback dispatcher: the one-method dispatch seam, carried over a sibling's origin instead of
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { UpstreamError, UpstreamTimeoutError } from "../error/pithyError.js";
2
4
  import { workflowDispatchPath } from "./schemas.js";
3
5
  //#region src/workflow/loopback.ts
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * Every name a durable job answers to, in one module. The CLI writes these into a host worker's
3
5
  * resolved `wrangler.jsonc`, the provisioner deploys under them, and the dispatcher resolves
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { NAME_SEGMENT } from "../naming/segment.js";
2
4
  import { InternalError } from "../error/pithyError.js";
3
5
  import { NAMESPACE_LIMITS } from "../naming/limits.js";
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import type { Capability } from "../capability/capability";
2
4
  import type { RegisteredWorkflow, WorkflowRegistry } from "./spec";
3
5
  /**
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { InternalError } from "../error/pithyError.js";
2
4
  import { workflowKey } from "./naming.js";
3
5
  //#region src/workflow/register.ts
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { z } from "zod";
2
4
  /**
3
5
  * The request and response contract of the host's dispatch route ({@link ./dispatchRoute.ts}).
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import { z } from "zod";
2
4
  //#region src/workflow/schemas.ts
3
5
  /**
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  import type { z } from "zod";
2
4
  /**
3
5
  * The durable-job seam. A capability declares the Cloudflare Workflows it owns as a map of
@@ -0,0 +1,2 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * **The one statement of what a terminal Workflow step writes into its error text, and the one reader of it.**
3
5
  *
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
1
3
  //#region src/workflow/stepMessage.ts
2
4
  /**
3
5
  * **The one statement of what a terminal Workflow step writes into its error text, and the one reader of it.**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pithy-sh/core",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,7 +25,7 @@
25
25
  }
26
26
  },
27
27
  "scripts": {
28
- "build": "tsdown && tsc -p tsconfig.build.json",
28
+ "build": "tsdown && tsc -p tsconfig.build.json && bun ../../tooling/build/src/stampDeclarations.ts",
29
29
  "typecheck": "tsc -p tsconfig.json",
30
30
  "test": "vitest run",
31
31
  "test:node": "vitest run --project=node",
@@ -191,6 +191,63 @@ export function failurePosition(cause: unknown): FailurePosition | undefined {
191
191
  return { line: Number(match[1]), column: Number(match[2]) };
192
192
  }
193
193
 
194
+ /** What kind of thing failed to resolve. Three causes that wore one sentence until #489. */
195
+ export type UnresolvedKind =
196
+ /** A bare specifier for a package that is not installed. Installing dependencies is the remedy. */
197
+ | "package"
198
+ /** An installed package asked for a subpath it does not provide. Installing again changes nothing. */
199
+ | "package-subpath"
200
+ /** A relative import of a file in the project's own tree. Installing again changes nothing. */
201
+ | "local-file";
202
+
203
+ /** Whether a path sits inside an installed package. */
204
+ function insideNodeModules(path: string): boolean {
205
+ return path.split(/[\\/]/).includes("node_modules");
206
+ }
207
+
208
+ /**
209
+ * Which of the three unresolved-import causes this was, or `undefined` when it cannot be told.
210
+ *
211
+ * **The discriminator was already in the message and was being thrown away.** `unresolvedSpecifier`
212
+ * matches `Cannot find (?:package|module)` — and `package` versus `module` is exactly the fact that
213
+ * separates a missing dependency from the other two. It sat in a non-capturing group, so every cause
214
+ * arrived wearing one sentence, and for two of the three that sentence advised an install which is
215
+ * *guaranteed* to change nothing. That is #489's class exactly: guidance a caller cannot follow, worst
216
+ * for the caller it is written for, which has no human to shrug and try something else.
217
+ *
218
+ * Measured across Node 24.13.0 and Bun 1.3.14, because the two runtimes hand back different halves and
219
+ * each hands back exactly one usable one:
220
+ *
221
+ * | cause | Node says | Bun's `specifier` |
222
+ * |---|---|---|
223
+ * | package absent | `Cannot find package 'pkg'`, no `url` | `pkg` |
224
+ * | subpath missing | `Cannot find module '/abs/node_modules/pkg/src/nope.js'`, `url` under node_modules | `pkg/src/nope` |
225
+ * | adopter's file | `Cannot find module '/abs/apps/board/src/x'`, `url` outside node_modules | `./src/x` |
226
+ *
227
+ * Bun gives the **specifier as written**, so a leading `.` settles it. Node gives the **already-resolved
228
+ * path**, where being under `node_modules` settles it. Neither read works on both runtimes; the pair
229
+ * does, and it is the same predicate — *is this inside node_modules* — applied to whichever fact the
230
+ * runtime supplied.
231
+ */
232
+ export function unresolvedKind(cause: unknown): UnresolvedKind | undefined {
233
+ if (/Cannot find package /.test(causeMessage(cause) ?? "")) return "package";
234
+
235
+ const specifier = unresolvedSpecifier(cause);
236
+ if (specifier === undefined) return undefined;
237
+
238
+ // Bun's field is the specifier as written: relative means the adopter's own file.
239
+ if (/^(?:\.|\/|[A-Za-z]:[\\/])/.test(specifier)) {
240
+ return insideNodeModules(specifier) ? "package-subpath" : "local-file";
241
+ }
242
+
243
+ // Node states an already-resolved absolute path; a bare specifier reaching here is a package subpath.
244
+ const url = prop(cause, "url");
245
+ if (typeof url === "string" && url.length > 0) {
246
+ return insideNodeModules(url) ? "package-subpath" : "local-file";
247
+ }
248
+ return "package-subpath";
249
+ }
250
+
194
251
  /**
195
252
  * The specifier that did not resolve.
196
253
  *
@@ -206,3 +263,62 @@ export function unresolvedSpecifier(cause: unknown): string | undefined {
206
263
  const match = /Cannot find (?:package|module) ['"]([^'"]+)['"]/.exec(causeMessage(cause) ?? "");
207
264
  return match?.[1];
208
265
  }
266
+
267
+ /** A package name as npm allows one: an optional `@scope/`, and never a store's dot-directory. */
268
+ const PACKAGE_NAME = /^(?:@[a-z0-9][\w.-]*\/)?[a-z0-9][\w.-]*$/i;
269
+
270
+ /**
271
+ * The file the failing import was written in, as the runtime named it. **Module-private on purpose**: it
272
+ * is an absolute path, and {@link importingPackage} exists to make sure only its package half leaves here.
273
+ */
274
+ function importerPath(cause: unknown): string | undefined {
275
+ const field = prop(cause, "referrer");
276
+ if (typeof field === "string" && field.length > 0) return field;
277
+ const message = causeMessage(cause) ?? "";
278
+ // Node ends its sentence with the path, so it is taken to the end of the line — a directory may
279
+ // contain a space. Bun quotes it when it states one in prose, and always carries the field as well.
280
+ return (/ imported from (.+)$/.exec(message) ?? /\bfrom ['"]([^'"]+)['"]/.exec(message))?.[1];
281
+ }
282
+
283
+ /**
284
+ * The package whose own source contained the import that did not resolve — **never a path**.
285
+ *
286
+ * {@link unresolvedSpecifier} answers *what* did not resolve. This answers *where the import lives*, and
287
+ * the two are different facts whenever the failing import is not the adopter's own. #480 is that case
288
+ * verbatim: `pithy add email` on a fresh project refused with
289
+ *
290
+ * > Nothing resolves "@pithy-sh/core/src/capability/capability".
291
+ *
292
+ * while `@pithy-sh/core` resolved from the Worker at every step of the run, before and after. The
293
+ * specifier was honest — the runtime really could not resolve it — but the import belonged to
294
+ * `@pithy-sh/email`, which had just been installed and was the package genuinely not linked. So the
295
+ * refusal named the one dependency that was definitely fine, and an adopter following it ran `bun
296
+ * install` against a tree that already had core in it. The importer is the half that would have pointed
297
+ * at `email`, and both runtimes hand it over: **Bun's `ResolveMessage` carries `referrer` as a field**
298
+ * (measured on 1.3.14) and Node states it in prose as `imported from <path>`.
299
+ *
300
+ * **A package name, or nothing.** The referrer is an absolute path — our frame, and the reason
301
+ * {@link unresolvedSpecifier} drops the prose around the specifier — so what travels is the one part of
302
+ * it that is not a path: the package directory it sits under. A referrer outside `node_modules` is the
303
+ * adopter's own file, and there is nothing to say about it that the refusal does not already say by
304
+ * naming the config, so it answers `undefined` rather than a path. The path itself is never returned
305
+ * from this module, which is what makes leaking it impossible rather than merely discouraged.
306
+ *
307
+ * The **last** `node_modules` in the path, because every store layout nests: pnpm's
308
+ * `node_modules/.pnpm/<id>/node_modules/<pkg>` and Bun's isolated linker's
309
+ * `node_modules/.bun/<pkg>@<version>/node_modules/<pkg>` (both measured) put the real owner last, and so
310
+ * does an ordinary nested install. The name is then checked against what npm allows, so a store's own
311
+ * bookkeeping directory (`.bun`, `.pnpm`, `hono@4.6.3`) can only ever answer nothing.
312
+ *
313
+ * Whether a surface names it, and what it advises when it does, is that surface's policy and stays there.
314
+ */
315
+ export function importingPackage(cause: unknown): string | undefined {
316
+ const referrer = importerPath(cause);
317
+ if (referrer === undefined) return undefined;
318
+ const segments = referrer.split(/[\\/]/);
319
+ const at = segments.lastIndexOf("node_modules");
320
+ const head = at === -1 ? undefined : segments[at + 1];
321
+ if (head === undefined) return undefined;
322
+ const name = head.startsWith("@") ? `${head}/${segments[at + 2] ?? ""}` : head;
323
+ return PACKAGE_NAME.test(name) ? name : undefined;
324
+ }
@@ -13,4 +13,4 @@
13
13
  export const PACKAGE_NAME = "@pithy-sh/core";
14
14
 
15
15
  /** This package's version, stamped from its own package.json at generation time. */
16
- export const PACKAGE_VERSION = "0.1.4";
16
+ export const PACKAGE_VERSION = "0.1.5";