@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.
- package/dist/seed/seed.d.ts +25 -0
- package/dist/seed/seed.d.ts.map +1 -1
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/workflow/faults.d.ts +34 -2
- package/dist/workflow/faults.d.ts.map +1 -1
- package/dist/workflow/faults.js +42 -18
- package/package.json +1 -1
- package/src/seed/seed.ts +25 -0
- package/src/version.generated.ts +1 -1
- package/src/workflow/faults.ts +61 -4
package/dist/seed/seed.d.ts
CHANGED
|
@@ -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
|
package/dist/seed/seed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/seed/seed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,WAAW,WAAW,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;IAC9D,mGAAmG;IACnG,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,IAAI,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW,CAC1B,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,EAC/B,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,EACnC,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;IAE/B,wEAAwE;IACxE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW,CAC1B,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,EAC/B,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,EACnC,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;IAE/B,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,yFAAyF;IACzF,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACP,iDAAiD;QACjD,QAAQ,EAAE,MAAM,CAAC;QACjB,6CAA6C;QAC7C,KAAK,EAAE,MAAM,CAAC;QACd,8EAA8E;QAC9E,GAAG,EAAE,OAAO,CAAC;KACd,CAAC;CACH;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,sFAAsF;IACtF,GAAG,EAAE,MAAM,CAAC;IACZ,kGAAkG;IAClG,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;;OAMG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD;;;;;;OAMG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,EAAE,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5B,6CAA6C;IAC7C,EAAE,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5B,iFAAiF;IACjF,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,YAAY,EAAE,SAAS,OAAO,EAAE,CAAC;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sGAAsG;IACtG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qBAAqB;IACrB,EAAE,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5B,uBAAuB;IACvB,EAAE,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5B,kBAAkB;IAClB,EAAE,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC3B,yDAAyD;IACzD,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;CACrE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,EACjD,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAC/B,WAAW,CAAC,KAAK,CAAC,CAGpB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC,OAAO,EACzF,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GACvC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAGtB"}
|
|
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.
|
|
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
|
+
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
|
-
/**
|
|
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):
|
|
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
|
|
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"}
|
package/dist/workflow/faults.js
CHANGED
|
@@ -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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
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
|
package/src/version.generated.ts
CHANGED
package/src/workflow/faults.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
-
):
|
|
193
|
-
|
|
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
|
}
|