@clossys/butler 0.1.1
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/CHANGELOG.md +85 -0
- package/LICENSE +21 -0
- package/README.md +260 -0
- package/dist/audit-shape.check.d.ts +32 -0
- package/dist/audit-shape.check.d.ts.map +1 -0
- package/dist/audit-shape.check.js +7 -0
- package/dist/audit-shape.check.js.map +1 -0
- package/dist/cli.d.ts +54 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +426 -0
- package/dist/cli.js.map +1 -0
- package/dist/contract.d.ts +256 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +377 -0
- package/dist/contract.js.map +1 -0
- package/dist/inbound/index.d.ts +120 -0
- package/dist/inbound/index.d.ts.map +1 -0
- package/dist/inbound/index.js +125 -0
- package/dist/inbound/index.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.d.ts +374 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +304 -0
- package/dist/schema.js.map +1 -0
- package/dist/validation.d.ts +74 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +140 -0
- package/dist/validation.js.map +1 -0
- package/dist/web/index.d.ts +5 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +25 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/internal/peer-version.d.ts +53 -0
- package/dist/web/internal/peer-version.d.ts.map +1 -0
- package/dist/web/internal/peer-version.js +136 -0
- package/dist/web/internal/peer-version.js.map +1 -0
- package/dist/web/useStandingWants.d.ts +75 -0
- package/dist/web/useStandingWants.d.ts.map +1 -0
- package/dist/web/useStandingWants.js +66 -0
- package/dist/web/useStandingWants.js.map +1 -0
- package/package.json +93 -0
- package/src/audit-shape.check.ts +37 -0
- package/src/cli.ts +445 -0
- package/src/contract.ts +534 -0
- package/src/inbound/index.ts +190 -0
- package/src/index.ts +113 -0
- package/src/schema.ts +622 -0
- package/src/validation.ts +172 -0
- package/src/web/index.ts +27 -0
- package/src/web/internal/peer-version.ts +159 -0
- package/src/web/useStandingWants.ts +139 -0
package/dist/schema.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The want contract: what a person asked for right now, and what they told
|
|
3
|
+
* us to keep doing.
|
|
4
|
+
*
|
|
5
|
+
* Two record families live here and they are deliberately not merged. An
|
|
6
|
+
* INTENT is a single request, interpreted, carrying a confidence, and true
|
|
7
|
+
* only until it has been acted on. A STANDING INSTRUCTION is a durable
|
|
8
|
+
* answer that keeps speaking for the person until it expires or the policy
|
|
9
|
+
* it answered is superseded. Both are consumer-authored data; nothing in
|
|
10
|
+
* this package ships a value, a topic vocabulary, a jurisdiction rule, or
|
|
11
|
+
* an obligation of its own.
|
|
12
|
+
*
|
|
13
|
+
* THE THREE-STATE MODEL, PRESERVED
|
|
14
|
+
* ---------------------------------
|
|
15
|
+
* `StandingState` is three states, not two. `"absent"` (never asked) is a
|
|
16
|
+
* distinct value from `"denied"` (asked, refused), and neither is a
|
|
17
|
+
* boolean. Collapsing them would make "never asked" indistinguishable from
|
|
18
|
+
* a passing signal — the same absence-of-signal-looks-like-a-passing-signal
|
|
19
|
+
* failure this repository already writes down for gate exit codes (see
|
|
20
|
+
* this repository's own contribution guide, "Gate CLIs exit `0` clean,
|
|
21
|
+
* `1` findings, `2` could not run"). `"granted"` and `"denied"` each carry
|
|
22
|
+
* the policy version they answered and when; a bare boolean can carry
|
|
23
|
+
* neither, which is exactly what turns a stored answer into an unauditable
|
|
24
|
+
* guess instead of a record.
|
|
25
|
+
*
|
|
26
|
+
* A fourth value, `"stale"`, exists only as an EVALUATION status
|
|
27
|
+
* (`StandingEvaluation`), never as a stored state — staleness is computed
|
|
28
|
+
* by comparing a stored record against the policy in force and the clock,
|
|
29
|
+
* so writing it down would be storing a derivation that starts rotting the
|
|
30
|
+
* moment it is written.
|
|
31
|
+
*
|
|
32
|
+
* IDENTIFIERS
|
|
33
|
+
* ------------
|
|
34
|
+
* `subjectId` is the person the want belongs to; `actorId` is whoever or
|
|
35
|
+
* whatever is acting. They are separate fields in every signature in this
|
|
36
|
+
* package and are never unified, because "the system acted on its own
|
|
37
|
+
* reading" and "the person asked for this" are the two things this whole
|
|
38
|
+
* package exists to keep apart. Both are opaque host-owned references —
|
|
39
|
+
* never an email address, a name, a phone number, or an IP. See
|
|
40
|
+
* `audit-shape.check.ts` for the compile-time proof that the audit event
|
|
41
|
+
* carries nothing else.
|
|
42
|
+
*
|
|
43
|
+
* Validation here is hand-rolled over `unknown`, with no schema library,
|
|
44
|
+
* matching every other package in this workspace (see the root
|
|
45
|
+
* `AGENTS.md`). These validators exist for the boundary where records
|
|
46
|
+
* arrive as untyped JSON — a preference-centre route body, a file the CLI
|
|
47
|
+
* reads, a value read back out of a host's own store — before anything
|
|
48
|
+
* downstream is allowed to trust them.
|
|
49
|
+
*/
|
|
50
|
+
import { isOneOf, isPlainObject, pushIssue, optionalTimestamp, requireArrayOf, requireBoolean, requireNumber, requireString, requireTimestamp, } from "./validation.js";
|
|
51
|
+
/** Every provenance value, for a caller validating untyped input. */
|
|
52
|
+
export const STANDING_PROVENANCES = ["stated", "inferred"];
|
|
53
|
+
/** Every audit event type, for a caller validating untyped input. */
|
|
54
|
+
export const STANDING_AUDIT_EVENT_TYPES = [
|
|
55
|
+
"granted",
|
|
56
|
+
"denied",
|
|
57
|
+
"withdrawn",
|
|
58
|
+
"reopened",
|
|
59
|
+
"policy-superseded",
|
|
60
|
+
"window-elapsed",
|
|
61
|
+
"confirmed",
|
|
62
|
+
"misread",
|
|
63
|
+
];
|
|
64
|
+
/** Every disposition, for a caller validating untyped input. */
|
|
65
|
+
export const INTENT_DISPOSITIONS = ["acted", "handed-off", "awaiting-confirmation"];
|
|
66
|
+
/** Every verdict, for a caller validating untyped input. */
|
|
67
|
+
export const CONFIRMATION_VERDICTS = ["confirmed", "misread", "unclear"];
|
|
68
|
+
// ------------------------------------------------------------------ validators
|
|
69
|
+
function result(value, issues) {
|
|
70
|
+
if (value === undefined || issues.length > 0)
|
|
71
|
+
return { ok: false, issues };
|
|
72
|
+
return { ok: true, value };
|
|
73
|
+
}
|
|
74
|
+
function readPolicyVersion(value, path, issues) {
|
|
75
|
+
if (!isPlainObject(value)) {
|
|
76
|
+
pushIssue(issues, path, "must be an object with policyId and version");
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
const before = issues.length;
|
|
80
|
+
const policyId = requireString(value.policyId, `${path}.policyId`, issues, { minLength: 1 });
|
|
81
|
+
const version = requireString(value.version, `${path}.version`, issues, { minLength: 1 });
|
|
82
|
+
if (issues.length > before || policyId === undefined || version === undefined)
|
|
83
|
+
return undefined;
|
|
84
|
+
return { policyId, version };
|
|
85
|
+
}
|
|
86
|
+
function readCurrencyWindow(value, path, issues) {
|
|
87
|
+
if (!isPlainObject(value)) {
|
|
88
|
+
pushIssue(issues, path, "must be an object with a whole-number days field");
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const days = requireNumber(value.days, `${path}.days`, issues, { min: 0, integer: true });
|
|
92
|
+
if (days === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
return { days };
|
|
95
|
+
}
|
|
96
|
+
function readStandingState(value, path, issues) {
|
|
97
|
+
if (!isPlainObject(value)) {
|
|
98
|
+
pushIssue(issues, path, "must be an object with a kind of absent, denied, or granted");
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const kind = value.kind;
|
|
102
|
+
if (kind === "absent")
|
|
103
|
+
return { kind: "absent" };
|
|
104
|
+
if (kind !== "denied" && kind !== "granted") {
|
|
105
|
+
pushIssue(issues, `${path}.kind`, 'must be "absent", "denied", or "granted"');
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const before = issues.length;
|
|
109
|
+
const policyVersion = readPolicyVersion(value.policyVersion, `${path}.policyVersion`, issues);
|
|
110
|
+
const decidedAt = requireTimestamp(value.decidedAt, `${path}.decidedAt`, issues);
|
|
111
|
+
if (issues.length > before || policyVersion === undefined || decidedAt === undefined)
|
|
112
|
+
return undefined;
|
|
113
|
+
return { kind, policyVersion, decidedAt };
|
|
114
|
+
}
|
|
115
|
+
function readStandingInstruction(value, path, issues) {
|
|
116
|
+
if (!isPlainObject(value)) {
|
|
117
|
+
pushIssue(issues, path, "must be an object");
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
const before = issues.length;
|
|
121
|
+
const instructionId = requireString(value.instructionId, `${path}.instructionId`, issues, { minLength: 1 });
|
|
122
|
+
const subjectId = requireString(value.subjectId, `${path}.subjectId`, issues, { minLength: 1 });
|
|
123
|
+
const topic = requireString(value.topic, `${path}.topic`, issues, { minLength: 1 });
|
|
124
|
+
const state = readStandingState(value.state, `${path}.state`, issues);
|
|
125
|
+
const currency = readCurrencyWindow(value.currency, `${path}.currency`, issues);
|
|
126
|
+
const confirmedAt = optionalTimestamp(value.confirmedAt, `${path}.confirmedAt`, issues);
|
|
127
|
+
if (!isOneOf(value.provenance, STANDING_PROVENANCES)) {
|
|
128
|
+
pushIssue(issues, `${path}.provenance`, 'must be "stated" or "inferred"');
|
|
129
|
+
}
|
|
130
|
+
if (issues.length > before)
|
|
131
|
+
return undefined;
|
|
132
|
+
if (instructionId === undefined || subjectId === undefined || topic === undefined || state === undefined || currency === undefined)
|
|
133
|
+
return undefined;
|
|
134
|
+
return {
|
|
135
|
+
instructionId,
|
|
136
|
+
subjectId,
|
|
137
|
+
topic,
|
|
138
|
+
state,
|
|
139
|
+
provenance: value.provenance,
|
|
140
|
+
currency,
|
|
141
|
+
...(confirmedAt !== undefined ? { confirmedAt } : {}),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function readIntentRecord(value, path, issues) {
|
|
145
|
+
if (!isPlainObject(value)) {
|
|
146
|
+
pushIssue(issues, path, "must be an object");
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
const before = issues.length;
|
|
150
|
+
const intentId = requireString(value.intentId, `${path}.intentId`, issues, { minLength: 1 });
|
|
151
|
+
const subjectId = requireString(value.subjectId, `${path}.subjectId`, issues, { minLength: 1 });
|
|
152
|
+
const actorId = requireString(value.actorId, `${path}.actorId`, issues, { minLength: 1 });
|
|
153
|
+
const interpretation = requireString(value.interpretation, `${path}.interpretation`, issues, { minLength: 1 });
|
|
154
|
+
const confidence = requireNumber(value.confidence, `${path}.confidence`, issues, { min: 0, max: 1 });
|
|
155
|
+
const observedAt = requireTimestamp(value.observedAt, `${path}.observedAt`, issues);
|
|
156
|
+
if (!isOneOf(value.disposition, INTENT_DISPOSITIONS)) {
|
|
157
|
+
pushIssue(issues, `${path}.disposition`, 'must be "acted", "handed-off", or "awaiting-confirmation"');
|
|
158
|
+
}
|
|
159
|
+
if (issues.length > before)
|
|
160
|
+
return undefined;
|
|
161
|
+
if (intentId === undefined ||
|
|
162
|
+
subjectId === undefined ||
|
|
163
|
+
actorId === undefined ||
|
|
164
|
+
interpretation === undefined ||
|
|
165
|
+
confidence === undefined ||
|
|
166
|
+
observedAt === undefined) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
return { intentId, subjectId, actorId, interpretation, confidence, observedAt, disposition: value.disposition };
|
|
170
|
+
}
|
|
171
|
+
function readConfirmationRecord(value, path, issues) {
|
|
172
|
+
if (!isPlainObject(value)) {
|
|
173
|
+
pushIssue(issues, path, "must be an object");
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
const before = issues.length;
|
|
177
|
+
const intentId = requireString(value.intentId, `${path}.intentId`, issues, { minLength: 1 });
|
|
178
|
+
const subjectId = requireString(value.subjectId, `${path}.subjectId`, issues, { minLength: 1 });
|
|
179
|
+
const confirmedAt = requireTimestamp(value.confirmedAt, `${path}.confirmedAt`, issues);
|
|
180
|
+
if (!isOneOf(value.verdict, CONFIRMATION_VERDICTS)) {
|
|
181
|
+
pushIssue(issues, `${path}.verdict`, 'must be "confirmed", "misread", or "unclear"');
|
|
182
|
+
}
|
|
183
|
+
if (issues.length > before)
|
|
184
|
+
return undefined;
|
|
185
|
+
if (intentId === undefined || subjectId === undefined || confirmedAt === undefined)
|
|
186
|
+
return undefined;
|
|
187
|
+
return { intentId, subjectId, verdict: value.verdict, confirmedAt };
|
|
188
|
+
}
|
|
189
|
+
function readInstructionUsage(value, path, issues) {
|
|
190
|
+
if (!isPlainObject(value)) {
|
|
191
|
+
pushIssue(issues, path, "must be an object");
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
const before = issues.length;
|
|
195
|
+
const instructionId = requireString(value.instructionId, `${path}.instructionId`, issues, { minLength: 1 });
|
|
196
|
+
const actorId = requireString(value.actorId, `${path}.actorId`, issues, { minLength: 1 });
|
|
197
|
+
const usedAt = requireTimestamp(value.usedAt, `${path}.usedAt`, issues);
|
|
198
|
+
const currentPolicyVersion = readPolicyVersion(value.currentPolicyVersion, `${path}.currentPolicyVersion`, issues);
|
|
199
|
+
if (issues.length > before)
|
|
200
|
+
return undefined;
|
|
201
|
+
if (instructionId === undefined || actorId === undefined || usedAt === undefined || currentPolicyVersion === undefined)
|
|
202
|
+
return undefined;
|
|
203
|
+
return { instructionId, actorId, usedAt, currentPolicyVersion };
|
|
204
|
+
}
|
|
205
|
+
function readPathCost(value, path, issues) {
|
|
206
|
+
if (!isPlainObject(value)) {
|
|
207
|
+
pushIssue(issues, path, "must be an object with steps, requiresContact and requiresAccount");
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
const before = issues.length;
|
|
211
|
+
const steps = requireNumber(value.steps, `${path}.steps`, issues, { min: 0, integer: true });
|
|
212
|
+
const requiresContact = requireBoolean(value.requiresContact, `${path}.requiresContact`, issues);
|
|
213
|
+
const requiresAccount = requireBoolean(value.requiresAccount, `${path}.requiresAccount`, issues);
|
|
214
|
+
if (issues.length > before || steps === undefined || requiresContact === undefined || requiresAccount === undefined)
|
|
215
|
+
return undefined;
|
|
216
|
+
return { steps, requiresContact, requiresAccount };
|
|
217
|
+
}
|
|
218
|
+
function readPreferencePath(value, path, issues) {
|
|
219
|
+
if (!isPlainObject(value)) {
|
|
220
|
+
pushIssue(issues, path, "must be an object");
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
const before = issues.length;
|
|
224
|
+
const surfaceId = requireString(value.surfaceId, `${path}.surfaceId`, issues, { minLength: 1 });
|
|
225
|
+
const topic = requireString(value.topic, `${path}.topic`, issues, { minLength: 1 });
|
|
226
|
+
const grant = readPathCost(value.grant, `${path}.grant`, issues);
|
|
227
|
+
const withdraw = value.withdraw === undefined ? undefined : readPathCost(value.withdraw, `${path}.withdraw`, issues);
|
|
228
|
+
if (issues.length > before || surfaceId === undefined || topic === undefined || grant === undefined)
|
|
229
|
+
return undefined;
|
|
230
|
+
return { surfaceId, topic, grant, ...(withdraw !== undefined ? { withdraw } : {}) };
|
|
231
|
+
}
|
|
232
|
+
/** Validates one untyped `StandingInstruction`. Never throws. */
|
|
233
|
+
export function validateStandingInstruction(value) {
|
|
234
|
+
const issues = [];
|
|
235
|
+
return result(readStandingInstruction(value, "(root)", issues), issues);
|
|
236
|
+
}
|
|
237
|
+
/** Validates an untyped array of `StandingInstruction`s. Never throws. */
|
|
238
|
+
export function validateStandingInstructions(value) {
|
|
239
|
+
const issues = [];
|
|
240
|
+
return result(requireArrayOf(value, "(root)", issues, readStandingInstruction), issues);
|
|
241
|
+
}
|
|
242
|
+
/** Validates one untyped `IntentRecord`. Never throws. */
|
|
243
|
+
export function validateIntentRecord(value) {
|
|
244
|
+
const issues = [];
|
|
245
|
+
return result(readIntentRecord(value, "(root)", issues), issues);
|
|
246
|
+
}
|
|
247
|
+
/** Validates an untyped array of `IntentRecord`s. Never throws. */
|
|
248
|
+
export function validateIntentRecords(value) {
|
|
249
|
+
const issues = [];
|
|
250
|
+
return result(requireArrayOf(value, "(root)", issues, readIntentRecord), issues);
|
|
251
|
+
}
|
|
252
|
+
/** Validates one untyped `ConfirmationRecord`. Never throws. */
|
|
253
|
+
export function validateConfirmationRecord(value) {
|
|
254
|
+
const issues = [];
|
|
255
|
+
return result(readConfirmationRecord(value, "(root)", issues), issues);
|
|
256
|
+
}
|
|
257
|
+
/** Validates an untyped array of `ConfirmationRecord`s. Never throws. */
|
|
258
|
+
export function validateConfirmationRecords(value) {
|
|
259
|
+
const issues = [];
|
|
260
|
+
return result(requireArrayOf(value, "(root)", issues, readConfirmationRecord), issues);
|
|
261
|
+
}
|
|
262
|
+
/** Validates an untyped array of `InstructionUsage`s. Never throws. */
|
|
263
|
+
export function validateInstructionUsages(value) {
|
|
264
|
+
const issues = [];
|
|
265
|
+
return result(requireArrayOf(value, "(root)", issues, readInstructionUsage), issues);
|
|
266
|
+
}
|
|
267
|
+
/** Validates an untyped array of `PreferencePath`s. Never throws. */
|
|
268
|
+
export function validatePreferencePaths(value) {
|
|
269
|
+
const issues = [];
|
|
270
|
+
return result(requireArrayOf(value, "(root)", issues, readPreferencePath), issues);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Validates an untyped `ConfidenceFloor`. Separate from the record
|
|
274
|
+
* validators because the floor is not a record: it is the one declared
|
|
275
|
+
* value the confirmation gate reads, and a run that cannot validate it
|
|
276
|
+
* must decline rather than substitute one.
|
|
277
|
+
*/
|
|
278
|
+
export function validateConfidenceFloor(value) {
|
|
279
|
+
const issues = [];
|
|
280
|
+
if (!isPlainObject(value)) {
|
|
281
|
+
pushIssue(issues, "(root)", "must be an object with a minimumConfidence field");
|
|
282
|
+
return { ok: false, issues };
|
|
283
|
+
}
|
|
284
|
+
const minimumConfidence = requireNumber(value.minimumConfidence, "(root).minimumConfidence", issues, { min: 0, max: 1 });
|
|
285
|
+
return result(minimumConfidence === undefined ? undefined : { minimumConfidence }, issues);
|
|
286
|
+
}
|
|
287
|
+
/** Validates an untyped `PolicyVersion`. Never throws. */
|
|
288
|
+
export function validatePolicyVersion(value) {
|
|
289
|
+
const issues = [];
|
|
290
|
+
return result(readPolicyVersion(value, "(root)", issues), issues);
|
|
291
|
+
}
|
|
292
|
+
/** Convenience guard over `validateStandingInstruction`, for callers that only need the boolean answer at a type boundary. */
|
|
293
|
+
export function isStandingInstruction(value) {
|
|
294
|
+
return validateStandingInstruction(value).ok;
|
|
295
|
+
}
|
|
296
|
+
/** Convenience guard over `validateIntentRecord`. */
|
|
297
|
+
export function isIntentRecord(value) {
|
|
298
|
+
return validateIntentRecord(value).ok;
|
|
299
|
+
}
|
|
300
|
+
/** Convenience guard over `validateConfirmationRecord`. */
|
|
301
|
+
export function isConfirmationRecord(value) {
|
|
302
|
+
return validateConfirmationRecord(value).ok;
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, dependency-free validation primitives for `schema.ts`. This
|
|
3
|
+
* package hand-rolls its entity validation rather than depending on a
|
|
4
|
+
* schema library — see `schema.ts`'s top-level doc comment for why, and
|
|
5
|
+
* `@clossys/strategist`'s `validation.ts` for the precedent this
|
|
6
|
+
* file follows: plain type guards over `unknown`, accumulating findings
|
|
7
|
+
* into an array, never throwing.
|
|
8
|
+
*
|
|
9
|
+
* Every `require*` helper below takes the same three leading arguments —
|
|
10
|
+
* `value` (the candidate, still `unknown`), `path` (an absolute,
|
|
11
|
+
* human-readable location like `"instructions[2].currency.days"`), and
|
|
12
|
+
* `issues` (the caller's shared, mutated-in-place array) — and returns
|
|
13
|
+
* either the narrowed value or `undefined`. A caller never has to inspect
|
|
14
|
+
* the return value to know whether something went wrong: every failure is
|
|
15
|
+
* also recorded into `issues` at the moment it is discovered, so the
|
|
16
|
+
* standard pattern (used throughout `schema.ts`) is to snapshot
|
|
17
|
+
* `issues.length` before validating an object's fields and compare it
|
|
18
|
+
* after — if it grew, something in this object failed, regardless of which
|
|
19
|
+
* field.
|
|
20
|
+
*/
|
|
21
|
+
export interface ValidationIssue {
|
|
22
|
+
/** Absolute, dot/bracket-joined location, e.g. `"intents[0].confidence"`, or `"(root)"` for a whole-value shape problem. */
|
|
23
|
+
path: string;
|
|
24
|
+
message: string;
|
|
25
|
+
}
|
|
26
|
+
export type ValidationResult<T> = {
|
|
27
|
+
ok: true;
|
|
28
|
+
value: T;
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
issues: ValidationIssue[];
|
|
32
|
+
};
|
|
33
|
+
/** A hand-rolled validator: takes an unknown value, returns a `ValidationResult<T>`. Never throws. */
|
|
34
|
+
export type Validator<T> = (value: unknown) => ValidationResult<T>;
|
|
35
|
+
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
36
|
+
/** A closed-vocabulary check. Membership is decided by the caller's own literal list, never by a shape heuristic. */
|
|
37
|
+
export declare function isOneOf<T extends string>(value: unknown, list: readonly T[]): value is T;
|
|
38
|
+
/** A short, readable description of an arbitrary value for an error message — never the value's full (potentially huge, potentially person-attributable) content. */
|
|
39
|
+
export declare function describeValue(value: unknown): string;
|
|
40
|
+
export declare function pushIssue(issues: ValidationIssue[], path: string, message: string): void;
|
|
41
|
+
export declare function requireString(value: unknown, path: string, issues: ValidationIssue[], opts?: {
|
|
42
|
+
minLength?: number;
|
|
43
|
+
}): string | undefined;
|
|
44
|
+
/** Same as `requireString`, except `undefined` is valid (the field is optional) and produces no issue. */
|
|
45
|
+
export declare function optionalString(value: unknown, path: string, issues: ValidationIssue[], opts?: {
|
|
46
|
+
minLength?: number;
|
|
47
|
+
}): string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* A timestamp this package can actually order and subtract. A record whose
|
|
50
|
+
* time cannot be parsed is a validation failure, never a record silently
|
|
51
|
+
* treated as "now" — the currency gate's whole job is arithmetic on these
|
|
52
|
+
* values, and a fabricated one would make an expired instruction read as
|
|
53
|
+
* current.
|
|
54
|
+
*/
|
|
55
|
+
export declare function requireTimestamp(value: unknown, path: string, issues: ValidationIssue[]): string | undefined;
|
|
56
|
+
/** Same as `requireTimestamp`, except `undefined` is valid (the field is optional) and produces no issue. */
|
|
57
|
+
export declare function optionalTimestamp(value: unknown, path: string, issues: ValidationIssue[]): string | undefined;
|
|
58
|
+
export declare function requireNumber(value: unknown, path: string, issues: ValidationIssue[], opts?: {
|
|
59
|
+
min?: number;
|
|
60
|
+
max?: number;
|
|
61
|
+
integer?: boolean;
|
|
62
|
+
}): number | undefined;
|
|
63
|
+
/** A real boolean, never a truthy string or number — the same discipline the donor's `isGpcSignal` applies to `present`. */
|
|
64
|
+
export declare function requireBoolean(value: unknown, path: string, issues: ValidationIssue[]): boolean | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* An array where each item is read by `itemReader` — the same
|
|
67
|
+
* `(value, path, issues) => T | undefined` shape every function in this
|
|
68
|
+
* file follows, so an entity's own per-object reader (e.g. `readIntent` in
|
|
69
|
+
* `schema.ts`) plugs directly into this without an adapter.
|
|
70
|
+
*/
|
|
71
|
+
export declare function requireArrayOf<T>(value: unknown, path: string, issues: ValidationIssue[], itemReader: (item: unknown, itemPath: string, issues: ValidationIssue[]) => T | undefined): T[] | undefined;
|
|
72
|
+
/** Joins `ValidationIssue[]` into one-line-per-issue text a CLI can print directly. */
|
|
73
|
+
export declare function summarizeIssues(issues: readonly ValidationIssue[]): string;
|
|
74
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, dependency-free validation primitives for `schema.ts`. This
|
|
3
|
+
* package hand-rolls its entity validation rather than depending on a
|
|
4
|
+
* schema library — see `schema.ts`'s top-level doc comment for why, and
|
|
5
|
+
* `@clossys/strategist`'s `validation.ts` for the precedent this
|
|
6
|
+
* file follows: plain type guards over `unknown`, accumulating findings
|
|
7
|
+
* into an array, never throwing.
|
|
8
|
+
*
|
|
9
|
+
* Every `require*` helper below takes the same three leading arguments —
|
|
10
|
+
* `value` (the candidate, still `unknown`), `path` (an absolute,
|
|
11
|
+
* human-readable location like `"instructions[2].currency.days"`), and
|
|
12
|
+
* `issues` (the caller's shared, mutated-in-place array) — and returns
|
|
13
|
+
* either the narrowed value or `undefined`. A caller never has to inspect
|
|
14
|
+
* the return value to know whether something went wrong: every failure is
|
|
15
|
+
* also recorded into `issues` at the moment it is discovered, so the
|
|
16
|
+
* standard pattern (used throughout `schema.ts`) is to snapshot
|
|
17
|
+
* `issues.length` before validating an object's fields and compare it
|
|
18
|
+
* after — if it grew, something in this object failed, regardless of which
|
|
19
|
+
* field.
|
|
20
|
+
*/
|
|
21
|
+
export function isPlainObject(value) {
|
|
22
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
+
}
|
|
24
|
+
/** A closed-vocabulary check. Membership is decided by the caller's own literal list, never by a shape heuristic. */
|
|
25
|
+
export function isOneOf(value, list) {
|
|
26
|
+
return typeof value === "string" && list.includes(value);
|
|
27
|
+
}
|
|
28
|
+
/** A short, readable description of an arbitrary value for an error message — never the value's full (potentially huge, potentially person-attributable) content. */
|
|
29
|
+
export function describeValue(value) {
|
|
30
|
+
if (value === undefined)
|
|
31
|
+
return "undefined";
|
|
32
|
+
if (value === null)
|
|
33
|
+
return "null";
|
|
34
|
+
if (Array.isArray(value))
|
|
35
|
+
return `an array (${value.length} item(s))`;
|
|
36
|
+
const t = typeof value;
|
|
37
|
+
if (t === "object")
|
|
38
|
+
return "an object";
|
|
39
|
+
if (t === "string")
|
|
40
|
+
return JSON.stringify(value);
|
|
41
|
+
return String(value);
|
|
42
|
+
}
|
|
43
|
+
export function pushIssue(issues, path, message) {
|
|
44
|
+
issues.push({ path, message });
|
|
45
|
+
}
|
|
46
|
+
export function requireString(value, path, issues, opts) {
|
|
47
|
+
if (typeof value !== "string") {
|
|
48
|
+
pushIssue(issues, path, `must be a string, got ${describeValue(value)}`);
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const minLength = opts?.minLength ?? 0;
|
|
52
|
+
if (value.trim().length < minLength) {
|
|
53
|
+
pushIssue(issues, path, `must be at least ${minLength} non-whitespace character(s) long`);
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
/** Same as `requireString`, except `undefined` is valid (the field is optional) and produces no issue. */
|
|
59
|
+
export function optionalString(value, path, issues, opts) {
|
|
60
|
+
if (value === undefined)
|
|
61
|
+
return undefined;
|
|
62
|
+
return requireString(value, path, issues, opts);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A timestamp this package can actually order and subtract. A record whose
|
|
66
|
+
* time cannot be parsed is a validation failure, never a record silently
|
|
67
|
+
* treated as "now" — the currency gate's whole job is arithmetic on these
|
|
68
|
+
* values, and a fabricated one would make an expired instruction read as
|
|
69
|
+
* current.
|
|
70
|
+
*/
|
|
71
|
+
export function requireTimestamp(value, path, issues) {
|
|
72
|
+
const asString = requireString(value, path, issues, { minLength: 1 });
|
|
73
|
+
if (asString === undefined)
|
|
74
|
+
return undefined;
|
|
75
|
+
if (Number.isNaN(Date.parse(asString))) {
|
|
76
|
+
pushIssue(issues, path, `must be a parseable timestamp, got ${describeValue(value)}`);
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
return asString;
|
|
80
|
+
}
|
|
81
|
+
/** Same as `requireTimestamp`, except `undefined` is valid (the field is optional) and produces no issue. */
|
|
82
|
+
export function optionalTimestamp(value, path, issues) {
|
|
83
|
+
if (value === undefined)
|
|
84
|
+
return undefined;
|
|
85
|
+
return requireTimestamp(value, path, issues);
|
|
86
|
+
}
|
|
87
|
+
export function requireNumber(value, path, issues, opts) {
|
|
88
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
89
|
+
pushIssue(issues, path, `must be a finite number, got ${describeValue(value)}`);
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
if (opts?.integer === true && !Number.isInteger(value)) {
|
|
93
|
+
pushIssue(issues, path, `must be a whole number, got ${describeValue(value)}`);
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
if (opts?.min !== undefined && value < opts.min) {
|
|
97
|
+
pushIssue(issues, path, `must be at least ${opts.min}, got ${describeValue(value)}`);
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
if (opts?.max !== undefined && value > opts.max) {
|
|
101
|
+
pushIssue(issues, path, `must be at most ${opts.max}, got ${describeValue(value)}`);
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
/** A real boolean, never a truthy string or number — the same discipline the donor's `isGpcSignal` applies to `present`. */
|
|
107
|
+
export function requireBoolean(value, path, issues) {
|
|
108
|
+
if (typeof value !== "boolean") {
|
|
109
|
+
pushIssue(issues, path, `must be a boolean, got ${describeValue(value)}`);
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* An array where each item is read by `itemReader` — the same
|
|
116
|
+
* `(value, path, issues) => T | undefined` shape every function in this
|
|
117
|
+
* file follows, so an entity's own per-object reader (e.g. `readIntent` in
|
|
118
|
+
* `schema.ts`) plugs directly into this without an adapter.
|
|
119
|
+
*/
|
|
120
|
+
export function requireArrayOf(value, path, issues, itemReader) {
|
|
121
|
+
if (!Array.isArray(value)) {
|
|
122
|
+
pushIssue(issues, path, `must be an array, got ${describeValue(value)}`);
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
const out = [];
|
|
126
|
+
let ok = true;
|
|
127
|
+
value.forEach((item, i) => {
|
|
128
|
+
const result = itemReader(item, `${path}[${i}]`, issues);
|
|
129
|
+
if (result === undefined)
|
|
130
|
+
ok = false;
|
|
131
|
+
else
|
|
132
|
+
out.push(result);
|
|
133
|
+
});
|
|
134
|
+
return ok ? out : undefined;
|
|
135
|
+
}
|
|
136
|
+
/** Joins `ValidationIssue[]` into one-line-per-issue text a CLI can print directly. */
|
|
137
|
+
export function summarizeIssues(issues) {
|
|
138
|
+
return issues.map((issue) => `${issue.path}: ${issue.message}`).join("; ");
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Must match package.json's `peerDependencies.react` exactly — `peer-guard.test.ts` asserts that directly. */
|
|
2
|
+
export declare const REACT_DECLARED_RANGE = ">=18";
|
|
3
|
+
export { useStandingWants } from "./useStandingWants.js";
|
|
4
|
+
export type { StandingWantsClient, UseStandingWantsOptions, UseStandingWantsResult } from "./useStandingWants.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAqBA,+GAA+G;AAC/G,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAG3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clossys/butler/web — preference-surface state, built entirely on
|
|
3
|
+
* the root package's pure functions.
|
|
4
|
+
*
|
|
5
|
+
* `react`/`react-dom` are OPTIONAL peers of this subpath specifically (see
|
|
6
|
+
* package.json's `peerDependenciesMeta`) — importing
|
|
7
|
+
* `@clossys/butler` (the root) or `@clossys/butler/inbound`
|
|
8
|
+
* never pulls in React; only importing `@clossys/butler/web` does.
|
|
9
|
+
* This module asserts the installed `react` version against this package's
|
|
10
|
+
* declared range at import time, so an absent or incompatible React fails
|
|
11
|
+
* loudly here instead of crashing later inside a hook with no version named
|
|
12
|
+
* as the cause. See `internal/peer-version.ts` for the guard itself.
|
|
13
|
+
*
|
|
14
|
+
* This subpath ships no rendering and no copy. What a preference surface
|
|
15
|
+
* says to a person, and what it looks like, are the consumer's own values;
|
|
16
|
+
* what is offered here is the state machine underneath it, including the
|
|
17
|
+
* structural half of withdrawal parity — see `useStandingWants`.
|
|
18
|
+
*/
|
|
19
|
+
import { version as reactVersion } from "react";
|
|
20
|
+
import { assertPeerVersion } from "./internal/peer-version.js";
|
|
21
|
+
/** Must match package.json's `peerDependencies.react` exactly — `peer-guard.test.ts` asserts that directly. */
|
|
22
|
+
export const REACT_DECLARED_RANGE = ">=18";
|
|
23
|
+
assertPeerVersion({ peer: "react", declaredRange: REACT_DECLARED_RANGE, foundVersion: reactVersion });
|
|
24
|
+
export { useStandingWants } from "./useStandingWants.js";
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,+GAA+G;AAC/G,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAC3C,iBAAiB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;AAEtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `assertPeerVersion` — the runtime half of `./web`'s "optional peer, no
|
|
3
|
+
* install-time signal in either direction" problem. `react`/`react-dom` are
|
|
4
|
+
* declared `peerDependenciesMeta: { optional: true }` (see package.json) so
|
|
5
|
+
* a consumer can install `@clossys/butler` (the root, provider-
|
|
6
|
+
* neutral core) without ever installing React — only `./web` needs it. But
|
|
7
|
+
* an ABSENT or OUT-OF-RANGE `react` produces no signal of any kind without
|
|
8
|
+
* this guard: a consumer on an incompatible React version would otherwise
|
|
9
|
+
* learn about it from whatever `./web` happened to crash on deep inside
|
|
10
|
+
* React itself, with nothing naming a version range as the cause. See
|
|
11
|
+
* `web/index.ts`'s own guard call, evaluated once at import time via
|
|
12
|
+
* `react`'s own exported `version`, for where this is wired in.
|
|
13
|
+
*
|
|
14
|
+
* This is the same obligation this repository's own contribution guide
|
|
15
|
+
* states for every requirement this workspace takes on: requiring a
|
|
16
|
+
* prerequisite is legitimate; failing silently when it is unmet is not,
|
|
17
|
+
* because that turns a setup error into a debugging session inside
|
|
18
|
+
* somebody else's codebase.
|
|
19
|
+
*
|
|
20
|
+
* PORTED, NOT SHARED, from `packages/consent/src/web/internal/peer-version.ts`
|
|
21
|
+
* — identical algorithm, copied rather than imported across a package
|
|
22
|
+
* boundary for the structural reason that file's own header gives: that
|
|
23
|
+
* package does not expose this as part of its public API surface, and even
|
|
24
|
+
* if it did, `@clossys/butler` would gain nothing by taking a real
|
|
25
|
+
* runtime dependency on a sibling just to reach one shared utility, and its
|
|
26
|
+
* "zero runtime dependencies" claim would then be wrong. Keep the copies in
|
|
27
|
+
* sync by hand if the ported range algorithm ever changes.
|
|
28
|
+
*
|
|
29
|
+
* DELIBERATELY PURE — NO `node:*` IMPORTS IN THIS FILE. `./web`'s entry
|
|
30
|
+
* point is reachable from a browser bundle (a client component rendering
|
|
31
|
+
* a preference surface), not just a Node process, so the version check reads
|
|
32
|
+
* `react`'s own exported `version` directly rather than any Node-only
|
|
33
|
+
* fs-based resolver.
|
|
34
|
+
*/
|
|
35
|
+
export interface AssertPeerVersionInput {
|
|
36
|
+
/** The optional peer's package name, e.g. `"react"`. */
|
|
37
|
+
peer: string;
|
|
38
|
+
/** This package's own `peerDependencies` range for `peer`. */
|
|
39
|
+
declaredRange: string;
|
|
40
|
+
/** The peer's real installed version, or `undefined` if it could not be resolved at all. */
|
|
41
|
+
foundVersion: string | undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Throws a named, actionable error naming the package, the declared range,
|
|
45
|
+
* and the version actually found. Never returns a boolean — a guard must
|
|
46
|
+
* state where control goes when it declines. A missing peer and an
|
|
47
|
+
* out-of-range peer throw genuinely DIFFERENT messages — "not installed"
|
|
48
|
+
* and "installed but incompatible" are different problems with different
|
|
49
|
+
* fixes. An unparseable declared range or installed version is a third,
|
|
50
|
+
* equally loud error, never an assumed pass.
|
|
51
|
+
*/
|
|
52
|
+
export declare function assertPeerVersion(input: AssertPeerVersionInput): void;
|
|
53
|
+
//# sourceMappingURL=peer-version.d.ts.map
|