@pithy-sh/core 0.7.4 → 0.8.0

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.
@@ -178,6 +178,31 @@ export interface SeedPrepareContext {
178
178
  * can write and never read.
179
179
  */
180
180
  secret: (name: string) => Promise<string | undefined>;
181
+ /**
182
+ * The value **this run just minted** for a secret, or `undefined` — never what the environment holds.
183
+ *
184
+ * `pithy provision` creates a random value for every `cf-secrets-store` secret the registry declares
185
+ * mintable, writes it into the account's Secrets Store, and lets it go. The Secrets Store is write-only
186
+ * from the CLI, so that write is the only moment the value exists anywhere the toolchain can see it —
187
+ * and provisioning migrates and seeds in the same process, a few steps later. A fixture that must
188
+ * *seal* something at creation time (encrypt a private key under the environment's key-encryption
189
+ * secret, derive an id that the running app will re-derive) can only do it then. Afterwards the value
190
+ * is unrecoverable by design.
191
+ *
192
+ * **This is not {@link secret}, and the two are not interchangeable.** `secret` answers what the
193
+ * environment holds and refuses outside `dev`, absolutely (#159); that rule is untouched. This answers
194
+ * the strictly narrower question *did this run create one, a moment ago, in memory*. A set asking here
195
+ * for a secret this run did not mint gets `undefined` wherever it runs, in `dev` or anywhere else.
196
+ *
197
+ * **Synchronous, because it cannot fetch.** There is no file to open and no request to make; a promise
198
+ * in this signature would suggest otherwise.
199
+ *
200
+ * **Empty is ordinary.** A re-run mints nothing — absence is checked before anything is generated — and
201
+ * a standalone `pithy seed` mints nothing at all. Both answer `undefined` for every name, and neither
202
+ * is an error. A set that needs a minted value and is handed none says so itself; nothing is invented
203
+ * on its behalf.
204
+ */
205
+ mintedThisRun: (name: string) => string | undefined;
181
206
  /**
182
207
  * The developer's machine-local preferences for this project, read from the Pithy config directory
183
208
  * (`~/.config/pithy/<project>/dev.json`, or `%APPDATA%\pithy\<project>\dev.json` on Windows), parsed but
@@ -1 +1 @@
1
- {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/seed/seed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/seed/seed.ts"],"names":[],"mappings":"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"}
@@ -3,5 +3,5 @@
3
3
  /** This package's npm name — the join key against a release feed. */
4
4
  export declare const PACKAGE_NAME = "@pithy-sh/core";
5
5
  /** This package's version, stamped from its own package.json at generation time. */
6
- export declare const PACKAGE_VERSION = "0.7.4";
6
+ export declare const PACKAGE_VERSION = "0.8.0";
7
7
  //# sourceMappingURL=version.generated.d.ts.map
@@ -4,6 +4,6 @@
4
4
  /** This package's npm name — the join key against a release feed. */
5
5
  const PACKAGE_NAME = "@pithy-sh/core";
6
6
  /** This package's version, stamped from its own package.json at generation time. */
7
- const PACKAGE_VERSION = "0.7.4";
7
+ const PACKAGE_VERSION = "0.8.0";
8
8
  //#endregion
9
9
  export { PACKAGE_NAME, PACKAGE_VERSION };
@@ -65,10 +65,42 @@ export interface WorkflowFault {
65
65
  * test rather than a claim — and so the same function decides in a test, in Miniflare, and in production.
66
66
  */
67
67
  export declare function classifyWorkflowFault(error: unknown, policy: WorkflowRetryPolicy): WorkflowFault;
68
- /** The half of a Workflow step this kit uses: run a named body, or serve its journalled result. */
68
+ /**
69
+ * The half of a Workflow step this kit uses: run a named body, or serve its journalled result.
70
+ *
71
+ * **`sleep` is optional here and required on what {@link classifiedSteps} hands back, and the asymmetry
72
+ * is the truth rather than a convenience.** The platform's own `WorkflowStep` always offers one. What
73
+ * does not are this kit's hand-written test doubles, which exist to exercise the classification and
74
+ * nothing else — and demanding a primitive the classifier never classifies would cost every one of them
75
+ * a line of noise. Handing an optional one back instead would push a null check into the one caller that
76
+ * genuinely pauses.
77
+ */
69
78
  export interface WorkflowStepLike {
70
79
  /** Run a named step, or return its journalled result if this instance already completed it. */
71
80
  do<T>(name: string, fn: () => Promise<T>): Promise<T>;
81
+ /**
82
+ * Pause the instance for `durationMs` and resume it afterwards — possibly in a fresh isolate, which
83
+ * is the whole reason a caller reaches for it rather than for a timer. Absent only on a test double.
84
+ */
85
+ sleep?(name: string, durationMs: number): Promise<void>;
86
+ }
87
+ /**
88
+ * A step runner that can pause — what {@link classifiedSteps} hands back, always.
89
+ *
90
+ * The durable pause is why this type exists rather than being a convenience over the one above. A `sleep`
91
+ * is journalled, so a wait survives the instance being evicted during it; a `setTimeout` inside one step
92
+ * burns that step's wall clock and dies with the instance holding it.
93
+ *
94
+ * **It was introduced on a stronger claim, and the claim did not survive contact (pithy-sh/pithy#647).** The
95
+ * argument was that a Secrets Store binding answers the same for its isolate's whole life, so only a resume
96
+ * into a fresh isolate could ever see a write land. Measured against a real store on 2026-09-25, that is
97
+ * false: a binding refreshes inside a live isolate roughly 1.3-1.5s after the REST write, proved by holding
98
+ * two isolates warm through a write and watching each serve the old value before it and the new one after,
99
+ * over 328 samples. The durability argument above is the true one and is sufficient on its own.
100
+ */
101
+ export interface DurableStepLike extends WorkflowStepLike {
102
+ /** Pause the instance for `durationMs`, then resume. */
103
+ sleep(name: string, durationMs: number): Promise<void>;
72
104
  }
73
105
  /**
74
106
  * The platform's terminal-error class — `NonRetryableError` from `cloudflare:workflows`, taken as a
@@ -95,5 +127,5 @@ export interface TerminalErrorConstructor {
95
127
  * `runSendBatch`, `runAtRestKeyRotation`) takes this instead with no change: the classification is
96
128
  * declared once, at the entrypoint, and every step below it inherits the decision.
97
129
  */
98
- export declare function classifiedSteps(step: WorkflowStepLike, policy: WorkflowRetryPolicy, terminalError: TerminalErrorConstructor): WorkflowStepLike;
130
+ export declare function classifiedSteps(step: WorkflowStepLike, policy: WorkflowRetryPolicy, terminalError: TerminalErrorConstructor): DurableStepLike;
99
131
  //# sourceMappingURL=faults.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"faults.d.ts","sourceRoot":"","sources":["../../src/workflow/faults.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2FAA2F;AAC3F,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,UAAU,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,iHAAiH;IACjH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C;AAED,2FAA2F;AAC3F,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,WAAW,EAAE,wBAAwB,CAAC;IACtC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAsDD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA0BhG;AAED,mGAAmG;AACnG,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,EAAE,wBAAwB,GACtC,gBAAgB,CA2BlB"}
1
+ {"version":3,"file":"faults.d.ts","sourceRoot":"","sources":["../../src/workflow/faults.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2FAA2F;AAC3F,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,UAAU,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,iHAAiH;IACjH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C;AAED,2FAA2F;AAC3F,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,WAAW,EAAE,wBAAwB,CAAC;IACtC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAsDD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA0BhG;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtD;;;OAGG;IACH,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,wDAAwD;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,EAAE,wBAAwB,GACtC,eAAe,CAmDjB"}
@@ -1,6 +1,6 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
- import { PithyError } from "../error/pithyError.js";
3
+ import { InternalError, PithyError } from "../error/pithyError.js";
4
4
  import { d1TransientFault } from "../data/withD1Retry.js";
5
5
  import { encodeWorkflowStepMessage } from "./stepMessage.js";
6
6
  //#region src/workflow/faults.ts
@@ -91,23 +91,47 @@ function classifyWorkflowFault(error, policy) {
91
91
  * declared once, at the entrypoint, and every step below it inherits the decision.
92
92
  */
93
93
  function classifiedSteps(step, policy, terminalError) {
94
- return { do(name, fn) {
95
- return step.do(name, async () => {
96
- try {
97
- return await fn();
98
- } catch (error) {
99
- const fault = classifyWorkflowFault(error, policy);
100
- if (fault.disposition === "retry") throw error;
101
- const terminal = new terminalError(encodeWorkflowStepMessage({
102
- code: fault.code,
103
- message: messageOf(error),
104
- action: pithyActionOf(error)
105
- }));
106
- terminal.cause = error;
107
- throw terminal;
108
- }
109
- });
110
- } };
94
+ const runner = {
95
+ do(name, fn) {
96
+ return step.do(name, async () => {
97
+ try {
98
+ return await fn();
99
+ } catch (error) {
100
+ const fault = classifyWorkflowFault(error, policy);
101
+ if (fault.disposition === "retry") throw error;
102
+ const terminal = new terminalError(encodeWorkflowStepMessage({
103
+ code: fault.code,
104
+ message: messageOf(error),
105
+ action: pithyActionOf(error)
106
+ }));
107
+ terminal.cause = error;
108
+ throw terminal;
109
+ }
110
+ });
111
+ },
112
+ /**
113
+ * Forwarded, and deliberately unclassified. A pause raises no fault of the capability's — the
114
+ * instance either resumes or it is gone — so there is nothing here for a policy to decide.
115
+ *
116
+ * A runner that cannot pause is refused, and the refusal is raised **through `do`** rather than
117
+ * thrown from here. A throw from here is a throw the engine never classifies, so it is free to
118
+ * re-drive the instance — and re-driving is the unbounded loop the caller is spending its sleeps to
119
+ * avoid. Going through `do` makes the refusal terminal on its first attempt, like every other
120
+ * answer that cannot change.
121
+ */
122
+ sleep(name, durationMs) {
123
+ const pause = step.sleep;
124
+ if (pause === void 0) return runner.do(`${name}/cannot-pause`, async () => {
125
+ throw new InternalError({
126
+ message: "This Workflow step runner cannot pause.",
127
+ action: "Give the step runner a `sleep`; the platform's own `WorkflowStep` always has one.",
128
+ detail: `step '${name}' asked to pause ${durationMs}ms through a runner that declares no sleep`
129
+ });
130
+ });
131
+ return pause.call(step, name, durationMs);
132
+ }
133
+ };
134
+ return runner;
111
135
  }
112
136
  //#endregion
113
137
  export { classifiedSteps, classifyWorkflowFault };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pithy-sh/core",
3
- "version": "0.7.4",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
package/src/seed/seed.ts CHANGED
@@ -196,6 +196,31 @@ export interface SeedPrepareContext {
196
196
  * can write and never read.
197
197
  */
198
198
  secret: (name: string) => Promise<string | undefined>;
199
+ /**
200
+ * The value **this run just minted** for a secret, or `undefined` — never what the environment holds.
201
+ *
202
+ * `pithy provision` creates a random value for every `cf-secrets-store` secret the registry declares
203
+ * mintable, writes it into the account's Secrets Store, and lets it go. The Secrets Store is write-only
204
+ * from the CLI, so that write is the only moment the value exists anywhere the toolchain can see it —
205
+ * and provisioning migrates and seeds in the same process, a few steps later. A fixture that must
206
+ * *seal* something at creation time (encrypt a private key under the environment's key-encryption
207
+ * secret, derive an id that the running app will re-derive) can only do it then. Afterwards the value
208
+ * is unrecoverable by design.
209
+ *
210
+ * **This is not {@link secret}, and the two are not interchangeable.** `secret` answers what the
211
+ * environment holds and refuses outside `dev`, absolutely (#159); that rule is untouched. This answers
212
+ * the strictly narrower question *did this run create one, a moment ago, in memory*. A set asking here
213
+ * for a secret this run did not mint gets `undefined` wherever it runs, in `dev` or anywhere else.
214
+ *
215
+ * **Synchronous, because it cannot fetch.** There is no file to open and no request to make; a promise
216
+ * in this signature would suggest otherwise.
217
+ *
218
+ * **Empty is ordinary.** A re-run mints nothing — absence is checked before anything is generated — and
219
+ * a standalone `pithy seed` mints nothing at all. Both answer `undefined` for every name, and neither
220
+ * is an error. A set that needs a minted value and is handed none says so itself; nothing is invented
221
+ * on its behalf.
222
+ */
223
+ mintedThisRun: (name: string) => string | undefined;
199
224
  /**
200
225
  * The developer's machine-local preferences for this project, read from the Pithy config directory
201
226
  * (`~/.config/pithy/<project>/dev.json`, or `%APPDATA%\pithy\<project>\dev.json` on Windows), parsed but
@@ -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.7.4";
16
+ export const PACKAGE_VERSION = "0.8.0";
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
 
4
4
  import { d1TransientFault } from "../data/withD1Retry";
5
- import { PithyError } from "../error/pithyError";
5
+ import { InternalError, PithyError } from "../error/pithyError";
6
6
  import { encodeWorkflowStepMessage } from "./stepMessage";
7
7
 
8
8
  /**
@@ -153,10 +153,43 @@ export function classifyWorkflowFault(error: unknown, policy: WorkflowRetryPolic
153
153
  };
154
154
  }
155
155
 
156
- /** The half of a Workflow step this kit uses: run a named body, or serve its journalled result. */
156
+ /**
157
+ * The half of a Workflow step this kit uses: run a named body, or serve its journalled result.
158
+ *
159
+ * **`sleep` is optional here and required on what {@link classifiedSteps} hands back, and the asymmetry
160
+ * is the truth rather than a convenience.** The platform's own `WorkflowStep` always offers one. What
161
+ * does not are this kit's hand-written test doubles, which exist to exercise the classification and
162
+ * nothing else — and demanding a primitive the classifier never classifies would cost every one of them
163
+ * a line of noise. Handing an optional one back instead would push a null check into the one caller that
164
+ * genuinely pauses.
165
+ */
157
166
  export interface WorkflowStepLike {
158
167
  /** Run a named step, or return its journalled result if this instance already completed it. */
159
168
  do<T>(name: string, fn: () => Promise<T>): Promise<T>;
169
+ /**
170
+ * Pause the instance for `durationMs` and resume it afterwards — possibly in a fresh isolate, which
171
+ * is the whole reason a caller reaches for it rather than for a timer. Absent only on a test double.
172
+ */
173
+ sleep?(name: string, durationMs: number): Promise<void>;
174
+ }
175
+
176
+ /**
177
+ * A step runner that can pause — what {@link classifiedSteps} hands back, always.
178
+ *
179
+ * The durable pause is why this type exists rather than being a convenience over the one above. A `sleep`
180
+ * is journalled, so a wait survives the instance being evicted during it; a `setTimeout` inside one step
181
+ * burns that step's wall clock and dies with the instance holding it.
182
+ *
183
+ * **It was introduced on a stronger claim, and the claim did not survive contact (pithy-sh/pithy#647).** The
184
+ * argument was that a Secrets Store binding answers the same for its isolate's whole life, so only a resume
185
+ * into a fresh isolate could ever see a write land. Measured against a real store on 2026-09-25, that is
186
+ * false: a binding refreshes inside a live isolate roughly 1.3-1.5s after the REST write, proved by holding
187
+ * two isolates warm through a write and watching each serve the old value before it and the new one after,
188
+ * over 328 samples. The durability argument above is the true one and is sufficient on its own.
189
+ */
190
+ export interface DurableStepLike extends WorkflowStepLike {
191
+ /** Pause the instance for `durationMs`, then resume. */
192
+ sleep(name: string, durationMs: number): Promise<void>;
160
193
  }
161
194
 
162
195
  /**
@@ -189,8 +222,8 @@ export function classifiedSteps(
189
222
  step: WorkflowStepLike,
190
223
  policy: WorkflowRetryPolicy,
191
224
  terminalError: TerminalErrorConstructor,
192
- ): WorkflowStepLike {
193
- return {
225
+ ): DurableStepLike {
226
+ const runner: DurableStepLike = {
194
227
  do<T>(name: string, fn: () => Promise<T>): Promise<T> {
195
228
  return step.do(name, async () => {
196
229
  try {
@@ -215,5 +248,29 @@ export function classifiedSteps(
215
248
  }
216
249
  });
217
250
  },
251
+ /**
252
+ * Forwarded, and deliberately unclassified. A pause raises no fault of the capability's — the
253
+ * instance either resumes or it is gone — so there is nothing here for a policy to decide.
254
+ *
255
+ * A runner that cannot pause is refused, and the refusal is raised **through `do`** rather than
256
+ * thrown from here. A throw from here is a throw the engine never classifies, so it is free to
257
+ * re-drive the instance — and re-driving is the unbounded loop the caller is spending its sleeps to
258
+ * avoid. Going through `do` makes the refusal terminal on its first attempt, like every other
259
+ * answer that cannot change.
260
+ */
261
+ sleep(name: string, durationMs: number): Promise<void> {
262
+ const pause = step.sleep;
263
+ if (pause === undefined) {
264
+ return runner.do<void>(`${name}/cannot-pause`, async () => {
265
+ throw new InternalError({
266
+ message: "This Workflow step runner cannot pause.",
267
+ action: "Give the step runner a `sleep`; the platform's own `WorkflowStep` always has one.",
268
+ detail: `step '${name}' asked to pause ${durationMs}ms through a runner that declares no sleep`,
269
+ });
270
+ });
271
+ }
272
+ return pause.call(step, name, durationMs);
273
+ },
218
274
  };
275
+ return runner;
219
276
  }