@aldus-runtime/gate-engine 0.1.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/LICENSE +201 -0
- package/NOTICE +21 -0
- package/dist/binding.d.ts +82 -0
- package/dist/binding.d.ts.map +1 -0
- package/dist/binding.js +129 -0
- package/dist/binding.js.map +1 -0
- package/dist/definition.d.ts +187 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +231 -0
- package/dist/definition.js.map +1 -0
- package/dist/engine.d.ts +194 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +361 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +61 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +57 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/money.d.ts +52 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/money.js +116 -0
- package/dist/money.js.map +1 -0
- package/dist/ports.d.ts +60 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +51 -0
- package/dist/ports.js.map +1 -0
- package/dist/spend.d.ts +127 -0
- package/dist/spend.d.ts.map +1 -0
- package/dist/spend.js +154 -0
- package/dist/spend.js.map +1 -0
- package/package.json +48 -0
- package/src/binding.ts +179 -0
- package/src/definition.ts +380 -0
- package/src/engine.ts +544 -0
- package/src/errors.ts +66 -0
- package/src/index.ts +102 -0
- package/src/money.ts +146 -0
- package/src/ports.ts +87 -0
- package/src/spend.ts +240 -0
package/dist/engine.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate evaluation, decision recording, and authorization (architecture contract §12, §13, §19.3).
|
|
3
|
+
*
|
|
4
|
+
* The central design choice: **invalidation is derived, never stored.**
|
|
5
|
+
*
|
|
6
|
+
* Contract §13.1 requires a content-changing edit to invalidate the Content Freeze "and
|
|
7
|
+
* downstream approvals". The obvious implementation writes invalidation records and walks the
|
|
8
|
+
* graph marking approvals dead. That implementation has a failure mode the contract cannot
|
|
9
|
+
* tolerate — if the cascade is ever interrupted, or a gate is added after the fact, some approval
|
|
10
|
+
* stays marked valid while the thing it approved has moved underneath it, and §13.2 forbids
|
|
11
|
+
* exactly that.
|
|
12
|
+
*
|
|
13
|
+
* So nothing is marked. A gate's state is computed on every evaluation from three inputs: its
|
|
14
|
+
* latest decision, the current digests of what it binds, and the state of the gates it depends
|
|
15
|
+
* on. A stale approval cannot survive because there is no stored "valid" flag for it to survive
|
|
16
|
+
* in. Adding a dependency edge invalidates downstream approvals immediately, with no migration.
|
|
17
|
+
*/
|
|
18
|
+
import { SCHEMA_VERSION, newEventId, newGateDecisionId, validate } from "@aldus-runtime/core";
|
|
19
|
+
import { assertSubjectsCover, detectDrift, } from "./binding.js";
|
|
20
|
+
import { GateEngineErrorCodes, gateEngineError } from "./errors.js";
|
|
21
|
+
import { checkSpend, grantLimitsDigest, } from "./spend.js";
|
|
22
|
+
/**
|
|
23
|
+
* What a gate currently is.
|
|
24
|
+
*
|
|
25
|
+
* `stale` is deliberately distinct from `pending`: a gate that was approved and then drifted is
|
|
26
|
+
* not the same operator situation as one nobody has looked at, and §13.1 wants the difference
|
|
27
|
+
* visible. `blocked_upstream` is likewise distinct from both — the gate itself may be perfectly
|
|
28
|
+
* approved while something it depends on is not.
|
|
29
|
+
*/
|
|
30
|
+
export const GATE_STATES = [
|
|
31
|
+
/** No decision has been recorded. */
|
|
32
|
+
"pending",
|
|
33
|
+
// NOTE: `blocked_upstream` below is used only when a gate is otherwise fine. A gate that is
|
|
34
|
+
// itself stale or rejected keeps that state and carries `blockedBy` alongside it, because the
|
|
35
|
+
// more specific label is the one an operator can act on.
|
|
36
|
+
/** Approved, and still bound to the current inputs. */
|
|
37
|
+
"satisfied",
|
|
38
|
+
/** Approved, but a bound value has changed since (§13.1, §13.2). */
|
|
39
|
+
"stale",
|
|
40
|
+
/** The operator rejected it. */
|
|
41
|
+
"rejected",
|
|
42
|
+
/** The operator asked for changes. */
|
|
43
|
+
"changes_requested",
|
|
44
|
+
/** The operator deliberately bypassed the check (§13, distinct from approval). */
|
|
45
|
+
"waived",
|
|
46
|
+
/** A blocking gate this one depends on is not satisfied (§13.1 cascade). */
|
|
47
|
+
"blocked_upstream",
|
|
48
|
+
];
|
|
49
|
+
/** True if two id lists hold the same ids in the same order. */
|
|
50
|
+
function sameIds(a, b) {
|
|
51
|
+
return a.length === b.length && a.every((id, index) => id === b[index]);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Evaluates gates, records decisions, and authorizes operations and spend.
|
|
55
|
+
*/
|
|
56
|
+
export class GateEngine {
|
|
57
|
+
#registry;
|
|
58
|
+
#decisions;
|
|
59
|
+
#events;
|
|
60
|
+
#costs;
|
|
61
|
+
constructor(options) {
|
|
62
|
+
this.#registry = options.registry;
|
|
63
|
+
this.#decisions = options.decisions;
|
|
64
|
+
this.#events = options.events;
|
|
65
|
+
this.#costs = options.costs;
|
|
66
|
+
}
|
|
67
|
+
/** The gate definitions this engine evaluates. */
|
|
68
|
+
get registry() {
|
|
69
|
+
return this.#registry;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Record a human decision (contract §3.6).
|
|
73
|
+
*
|
|
74
|
+
* §3.6: "Human review MUST create a durable `GateDecision`. A chat message saying 'looks good'
|
|
75
|
+
* is not enough unless it is translated into a recorded decision tied to exact inputs." This is
|
|
76
|
+
* that translation, and it refuses anything that would produce a decision tied to less than the
|
|
77
|
+
* gate binds.
|
|
78
|
+
*
|
|
79
|
+
* @throws {AldusError} `ALDUS_GATE_NOT_FOUND` if the gate is not registered.
|
|
80
|
+
* @throws {AldusError} `ALDUS_GATE_SUBJECTS_INCOMPLETE` if the subjects do not cover the gate.
|
|
81
|
+
* @throws {AldusError} `ALDUS_GATE_ACTOR_NOT_PERMITTED` if the actor may not decide this gate.
|
|
82
|
+
*/
|
|
83
|
+
async decide(input) {
|
|
84
|
+
const gate = this.#registry.require(input.gateId);
|
|
85
|
+
assertSubjectsCover(gate, input.subjects);
|
|
86
|
+
if (!gate.permittedActorKinds.includes(input.decidedBy.kind)) {
|
|
87
|
+
throw gateEngineError(GateEngineErrorCodes.GATE_ACTOR_NOT_PERMITTED, `Gate "${gate.gateId}" accepts decisions from [${gate.permittedActorKinds.join(", ")}], ` +
|
|
88
|
+
`but "${input.decidedBy.id}" is a ${input.decidedBy.kind}. Contract §12 forbids ` +
|
|
89
|
+
"presenting a machine pass as semantic correctness, and §13.3 keeps final performance " +
|
|
90
|
+
"approval human-owned.", {
|
|
91
|
+
category: "policy",
|
|
92
|
+
details: {
|
|
93
|
+
gateId: gate.gateId,
|
|
94
|
+
actorKind: input.decidedBy.kind,
|
|
95
|
+
permitted: [...gate.permittedActorKinds],
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const decision = {
|
|
100
|
+
schemaVersion: SCHEMA_VERSION,
|
|
101
|
+
decisionId: input.decisionId ?? newGateDecisionId(),
|
|
102
|
+
gateId: gate.gateId,
|
|
103
|
+
runId: input.runId,
|
|
104
|
+
decision: input.decision,
|
|
105
|
+
subjectHashes: [...input.subjects].map((subject) => subject.sha256).sort(),
|
|
106
|
+
decidedBy: input.decidedBy,
|
|
107
|
+
decidedAt: input.decidedAt,
|
|
108
|
+
...(input.comment !== undefined ? { comment: input.comment } : {}),
|
|
109
|
+
expiresOnChange: input.expiresOnChange ?? gate.expiresOnChange,
|
|
110
|
+
};
|
|
111
|
+
// Validate before persisting. A malformed decision written to the approvals log is worse
|
|
112
|
+
// than a rejected call, because §13 treats what is written there as authoritative.
|
|
113
|
+
const validated = validate("GateDecision", decision);
|
|
114
|
+
if (!validated.ok) {
|
|
115
|
+
throw gateEngineError(GateEngineErrorCodes.GATE_DEFINITION_INVALID, `The decision built for gate "${gate.gateId}" is not a valid GateDecision.`, { category: "internal", details: { issues: validated.error.details } });
|
|
116
|
+
}
|
|
117
|
+
await this.#decisions.append(input.runId, decision);
|
|
118
|
+
await this.#emitDecisionEvent(input, decision);
|
|
119
|
+
return decision;
|
|
120
|
+
}
|
|
121
|
+
/** Emit the §6.4 event for a recorded decision. */
|
|
122
|
+
async #emitDecisionEvent(input, decision) {
|
|
123
|
+
const event = {
|
|
124
|
+
schemaVersion: SCHEMA_VERSION,
|
|
125
|
+
eventId: input.eventId ?? newEventId(),
|
|
126
|
+
occurredAt: decision.decidedAt,
|
|
127
|
+
episodeId: input.episodeId,
|
|
128
|
+
runId: decision.runId,
|
|
129
|
+
action: `gate.${decision.decision}`,
|
|
130
|
+
actor: decision.decidedBy,
|
|
131
|
+
inputRefs: [],
|
|
132
|
+
outputRefs: [],
|
|
133
|
+
details: {
|
|
134
|
+
gateId: decision.gateId,
|
|
135
|
+
decisionId: decision.decisionId,
|
|
136
|
+
subjectCount: decision.subjectHashes.length,
|
|
137
|
+
expiresOnChange: decision.expiresOnChange,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
await this.#events.emit(event);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Evaluate every registered gate for a Run.
|
|
144
|
+
*
|
|
145
|
+
* `subjects` supplies the current digests of what each gate binds. A gate absent from it is
|
|
146
|
+
* evaluated as having no current inputs, which reads as `pending` — never as satisfied.
|
|
147
|
+
*/
|
|
148
|
+
async evaluate(runId, subjects) {
|
|
149
|
+
const decisions = await this.#decisions.list(runId);
|
|
150
|
+
return this.evaluateWith(decisions, subjects);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Evaluate against a decision list already in hand.
|
|
154
|
+
*
|
|
155
|
+
* Separated from {@link GateEngine.evaluate} so the whole cascade is a pure function of its
|
|
156
|
+
* inputs — which is what makes it testable without a store and impossible to get into a
|
|
157
|
+
* partially-updated state.
|
|
158
|
+
*/
|
|
159
|
+
evaluateWith(decisions, subjects) {
|
|
160
|
+
const own = new Map();
|
|
161
|
+
for (const gate of this.#registry.list()) {
|
|
162
|
+
own.set(gate.gateId, this.#evaluateOne(gate, decisions, subjects[gate.gateId] ?? []));
|
|
163
|
+
}
|
|
164
|
+
return this.#applyCascade(own);
|
|
165
|
+
}
|
|
166
|
+
/** A gate's state from its own decision and subjects, before the cascade. */
|
|
167
|
+
#evaluateOne(gate, decisions, subjects) {
|
|
168
|
+
const base = { gateId: gate.gateId, level: gate.level, enforcement: gate.enforcement };
|
|
169
|
+
const blocks = (state) => gate.enforcement === "blocking" && state !== "satisfied" && state !== "waived";
|
|
170
|
+
// Append order is authoritative, not `decidedAt`: the log is the durable fact, and two
|
|
171
|
+
// machines with disagreeing clocks must not be able to reorder which approval is current.
|
|
172
|
+
const latest = [...decisions].reverse().find((entry) => entry.gateId === gate.gateId);
|
|
173
|
+
if (latest === undefined) {
|
|
174
|
+
return {
|
|
175
|
+
...base,
|
|
176
|
+
state: "pending",
|
|
177
|
+
blocking: blocks("pending"),
|
|
178
|
+
explanation: `Gate "${gate.gateId}" has no recorded decision.`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (latest.decision === "rejected" || latest.decision === "changes_requested") {
|
|
182
|
+
return {
|
|
183
|
+
...base,
|
|
184
|
+
state: latest.decision,
|
|
185
|
+
decision: latest,
|
|
186
|
+
blocking: blocks(latest.decision),
|
|
187
|
+
explanation: latest.comment ?? `Gate "${gate.gateId}" was ${latest.decision.replace("_", " ")}.`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const drift = detectDrift(latest, subjects);
|
|
191
|
+
// A waiver records that a check was bypassed (§13). It still binds: waiving a gate for one
|
|
192
|
+
// version of the content says nothing about the next, so drift voids it exactly as it voids
|
|
193
|
+
// an approval.
|
|
194
|
+
if (drift !== undefined && latest.expiresOnChange) {
|
|
195
|
+
return {
|
|
196
|
+
...base,
|
|
197
|
+
state: "stale",
|
|
198
|
+
decision: latest,
|
|
199
|
+
drift,
|
|
200
|
+
blocking: blocks("stale"),
|
|
201
|
+
explanation: `Gate "${gate.gateId}" was ${latest.decision}, but ` +
|
|
202
|
+
`${drift.changed.length > 0 ? `[${drift.changed.join(", ")}] changed` : "its bound inputs changed"}` +
|
|
203
|
+
" since. Contract §13.1 voids an approval once what it approved has moved.",
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const state = latest.decision === "waived" ? "waived" : "satisfied";
|
|
207
|
+
return { ...base, state, decision: latest, blocking: blocks(state) };
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Propagate §13.1's cascade over the dependency graph.
|
|
211
|
+
*
|
|
212
|
+
* Only **blocking** gates propagate. §12 level 2 defines an advisory signal as one that
|
|
213
|
+
* "reports a possible issue without blocking", so an un-run advisory check must not halt the
|
|
214
|
+
* gates downstream of it — otherwise every advisory would be a hard gate wearing a different
|
|
215
|
+
* label, and §12's four levels would collapse into two.
|
|
216
|
+
*/
|
|
217
|
+
#applyCascade(own) {
|
|
218
|
+
const result = new Map(own);
|
|
219
|
+
// Registry construction already refused a cycle, so a fixpoint loop terminates. Bounding it
|
|
220
|
+
// by the gate count keeps a future graph bug from hanging an operator's session regardless.
|
|
221
|
+
for (let pass = 0; pass < result.size + 1; pass += 1) {
|
|
222
|
+
let changed = false;
|
|
223
|
+
for (const gate of this.#registry.list()) {
|
|
224
|
+
const current = result.get(gate.gateId);
|
|
225
|
+
if (current === undefined)
|
|
226
|
+
continue;
|
|
227
|
+
const blockedBy = gate.dependsOn.filter((dependency) => {
|
|
228
|
+
const upstream = result.get(dependency);
|
|
229
|
+
return upstream !== undefined && upstream.blocking;
|
|
230
|
+
});
|
|
231
|
+
if (blockedBy.length === 0)
|
|
232
|
+
continue;
|
|
233
|
+
if (current.blockedBy !== undefined && sameIds(current.blockedBy, blockedBy))
|
|
234
|
+
continue;
|
|
235
|
+
// A gate can be broken on its own account *and* blocked by something upstream. When it
|
|
236
|
+
// has a decision that is itself broken, that state wins: an operator told only "blocked
|
|
237
|
+
// upstream" would fix the upstream gate and be surprised this one still needs
|
|
238
|
+
// re-approving. `blockedBy` is set either way, so the cascade is never lost.
|
|
239
|
+
//
|
|
240
|
+
// A `pending` gate has no such decision to preserve, and there "blocked upstream" is the
|
|
241
|
+
// more useful label — it says the gate cannot even be started on yet, rather than merely
|
|
242
|
+
// that nobody has.
|
|
243
|
+
const ownStateIsInformative = current.state === "stale" ||
|
|
244
|
+
current.state === "rejected" ||
|
|
245
|
+
current.state === "changes_requested";
|
|
246
|
+
const state = ownStateIsInformative ? current.state : "blocked_upstream";
|
|
247
|
+
const upstreamNote = `[${blockedBy.join(", ")}] is not satisfied, so contract §13.1 invalidates this ` +
|
|
248
|
+
"approval along with the gate it depends on.";
|
|
249
|
+
result.set(gate.gateId, {
|
|
250
|
+
...current,
|
|
251
|
+
state,
|
|
252
|
+
blockedBy,
|
|
253
|
+
blocking: gate.enforcement === "blocking",
|
|
254
|
+
explanation: ownStateIsInformative
|
|
255
|
+
? `${current.explanation ?? `Gate "${gate.gateId}" is ${current.state}.`} Additionally, ${upstreamNote}`
|
|
256
|
+
: `Gate "${gate.gateId}" cannot be relied on because ${upstreamNote}`,
|
|
257
|
+
});
|
|
258
|
+
changed = true;
|
|
259
|
+
}
|
|
260
|
+
if (!changed)
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Whether an operation is authorized (contract §13.4).
|
|
267
|
+
*
|
|
268
|
+
* An approval authorizes exactly the operations its gate names in `grants` and nothing else.
|
|
269
|
+
* That is what keeps §13.4's "Uploading and making public SHOULD be separate operations"
|
|
270
|
+
* enforceable: they are two gates granting two operations, and approving one leaves the other
|
|
271
|
+
* refused.
|
|
272
|
+
*
|
|
273
|
+
* Returns a refusal rather than throwing, because a caller needs to display why an operation is
|
|
274
|
+
* unavailable.
|
|
275
|
+
*/
|
|
276
|
+
async authorize(runId, operation, subjects) {
|
|
277
|
+
const statuses = await this.evaluate(runId, subjects);
|
|
278
|
+
const candidates = this.#registry.list().filter((gate) => gate.grants.includes(operation));
|
|
279
|
+
if (candidates.length === 0) {
|
|
280
|
+
return {
|
|
281
|
+
authorized: false,
|
|
282
|
+
statuses: [],
|
|
283
|
+
explanation: `No registered gate grants "${operation}". An operation nobody authorizes is refused ` +
|
|
284
|
+
"rather than allowed, so that adding a gate is what enables an action, never omitting one.",
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
const relevant = candidates.flatMap((gate) => {
|
|
288
|
+
const status = statuses.get(gate.gateId);
|
|
289
|
+
return status === undefined ? [] : [status];
|
|
290
|
+
});
|
|
291
|
+
const granted = relevant.find((status) => status.state === "satisfied" && status.decision?.decision === "approved");
|
|
292
|
+
if (granted?.decision !== undefined) {
|
|
293
|
+
return { authorized: true, gateId: granted.gateId, decision: granted.decision };
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
authorized: false,
|
|
297
|
+
statuses: relevant,
|
|
298
|
+
explanation: `"${operation}" is not authorized. ` +
|
|
299
|
+
relevant
|
|
300
|
+
.map((status) => `${status.gateId}: ${status.state}${status.explanation === undefined ? "" : ` — ${status.explanation}`}`)
|
|
301
|
+
.join("; "),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Whether a paid request may proceed (contract §13.2, §19.3).
|
|
306
|
+
*
|
|
307
|
+
* Three things must hold, and all three are checked here because any one of them alone is
|
|
308
|
+
* insufficient:
|
|
309
|
+
*
|
|
310
|
+
* 1. the gate is satisfied — §13.2 forbids paid synthesis before the operator approves;
|
|
311
|
+
* 2. the grant's limits are among what that decision bound — otherwise the ceiling could be
|
|
312
|
+
* raised after approval without voiding it;
|
|
313
|
+
* 3. the spend fits the remaining budget — §19.3 stop-on-budget.
|
|
314
|
+
*/
|
|
315
|
+
async authorizeSpend(runId, grant, request, subjects, costs) {
|
|
316
|
+
const statuses = await this.evaluate(runId, subjects);
|
|
317
|
+
const status = statuses.get(grant.gateId);
|
|
318
|
+
if (status === undefined) {
|
|
319
|
+
return {
|
|
320
|
+
authorized: false,
|
|
321
|
+
explanation: `Gate "${grant.gateId}" is not registered, so it cannot authorize spend.`,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
if (status.state !== "satisfied" || status.decision?.decision !== "approved") {
|
|
325
|
+
return {
|
|
326
|
+
authorized: false,
|
|
327
|
+
statuses: [status],
|
|
328
|
+
explanation: `Paid work is refused: gate "${grant.gateId}" is ${status.state}. Contract §13.2 ` +
|
|
329
|
+
"forbids paid synthesis until the operator has approved, and voids that approval once " +
|
|
330
|
+
`any bound value changes.${status.explanation === undefined ? "" : ` ${status.explanation}`}`,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
const decision = status.decision;
|
|
334
|
+
if (decision.decisionId !== grant.decisionId) {
|
|
335
|
+
return {
|
|
336
|
+
authorized: false,
|
|
337
|
+
statuses: [status],
|
|
338
|
+
explanation: `The grant cites decision "${grant.decisionId}", but the current decision on gate ` +
|
|
339
|
+
`"${grant.gateId}" is "${decision.decisionId}". A grant from a superseded decision ` +
|
|
340
|
+
"does not carry forward (§13.2).",
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
if (!decision.subjectHashes.includes(grantLimitsDigest(grant))) {
|
|
344
|
+
return {
|
|
345
|
+
authorized: false,
|
|
346
|
+
statuses: [status],
|
|
347
|
+
explanation: `The authorized maximum of ${grant.maxTotal.amount} ${grant.maxTotal.currency} is not ` +
|
|
348
|
+
`among what decision "${decision.decisionId}" bound. Contract §13.2 requires the ` +
|
|
349
|
+
"operator to approve a maximum authorized cost; a limit the approval never covered is " +
|
|
350
|
+
"not an authorization.",
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const recorded = costs ?? (this.#costs === undefined ? [] : await this.#costs.list(runId));
|
|
354
|
+
const check = checkSpend(grant, recorded, request);
|
|
355
|
+
if (!check.allowed) {
|
|
356
|
+
return { authorized: false, explanation: check.explanation, statuses: [status], check };
|
|
357
|
+
}
|
|
358
|
+
return { authorized: true, gateId: grant.gateId, decision, check };
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failures specific to gate evaluation and spend authorization.
|
|
3
|
+
*
|
|
4
|
+
* Aldus Core deliberately keeps no central error-code registry, so that a package can name a new
|
|
5
|
+
* failure without forking Core. These codes are this package's contribution; they carry the same
|
|
6
|
+
* `ALDUS_` prefix and `SCREAMING_SNAKE_CASE` shape so production trace (contract §20) stays
|
|
7
|
+
* uniform across packages.
|
|
8
|
+
*/
|
|
9
|
+
import { AldusError, type ErrorCategory } from "@aldus-runtime/core";
|
|
10
|
+
/** Error codes raised by the gate engine. */
|
|
11
|
+
export declare const GateEngineErrorCodes: {
|
|
12
|
+
/** A gate was referenced that is not registered. */
|
|
13
|
+
readonly GATE_NOT_FOUND: "ALDUS_GATE_NOT_FOUND";
|
|
14
|
+
/** A gate definition is internally inconsistent and was refused at registration. */
|
|
15
|
+
readonly GATE_DEFINITION_INVALID: "ALDUS_GATE_DEFINITION_INVALID";
|
|
16
|
+
/**
|
|
17
|
+
* Gate dependencies form a cycle.
|
|
18
|
+
*
|
|
19
|
+
* A configuration fault, not a data fault: contract §13.1's cascade is only meaningful over a
|
|
20
|
+
* directed acyclic graph, and a cycle would make "what does this invalidate" unanswerable.
|
|
21
|
+
*/
|
|
22
|
+
readonly GATE_DEPENDENCY_CYCLE: "ALDUS_GATE_DEPENDENCY_CYCLE";
|
|
23
|
+
/**
|
|
24
|
+
* A decision was submitted by an actor the gate does not accept.
|
|
25
|
+
*
|
|
26
|
+
* Contract §13.3 keeps final performance approval human-owned, and §12 reserves the human
|
|
27
|
+
* oracle level for subjective and asymmetric-risk judgements. A machine actor satisfying such
|
|
28
|
+
* a gate would present a machine pass as semantic correctness, which §12 forbids outright.
|
|
29
|
+
*/
|
|
30
|
+
readonly GATE_ACTOR_NOT_PERMITTED: "ALDUS_GATE_ACTOR_NOT_PERMITTED";
|
|
31
|
+
/** A decision was submitted that does not bind the subjects its gate requires. */
|
|
32
|
+
readonly GATE_SUBJECTS_INCOMPLETE: "ALDUS_GATE_SUBJECTS_INCOMPLETE";
|
|
33
|
+
/**
|
|
34
|
+
* An operation requiring authorization was attempted without a valid one.
|
|
35
|
+
*
|
|
36
|
+
* Contract §13.2: paid TTS MUST NOT run until the operator approves. This is the refusal that
|
|
37
|
+
* enforces it.
|
|
38
|
+
*/
|
|
39
|
+
readonly AUTHORIZATION_MISSING: "ALDUS_AUTHORIZATION_MISSING";
|
|
40
|
+
/**
|
|
41
|
+
* An authorization exists but no longer binds the current inputs.
|
|
42
|
+
*
|
|
43
|
+
* Contract §13.2: "The authorization MUST be invalidated if any bound value changes."
|
|
44
|
+
*/
|
|
45
|
+
readonly AUTHORIZATION_STALE: "ALDUS_AUTHORIZATION_STALE";
|
|
46
|
+
/** A spend request would exceed the authorized maximum (contract §19.3 stop-on-budget). */
|
|
47
|
+
readonly SPEND_LIMIT_EXCEEDED: "ALDUS_SPEND_LIMIT_EXCEEDED";
|
|
48
|
+
/** Two monetary values in different currencies were combined or compared. */
|
|
49
|
+
readonly CURRENCY_MISMATCH: "ALDUS_CURRENCY_MISMATCH";
|
|
50
|
+
/** A monetary amount was not a well-formed decimal string. */
|
|
51
|
+
readonly MONEY_MALFORMED: "ALDUS_MONEY_MALFORMED";
|
|
52
|
+
};
|
|
53
|
+
/** @see GateEngineErrorCodes */
|
|
54
|
+
export type GateEngineErrorCode = (typeof GateEngineErrorCodes)[keyof typeof GateEngineErrorCodes];
|
|
55
|
+
/** Construct an {@link AldusError} with a gate-engine code. */
|
|
56
|
+
export declare function gateEngineError(code: GateEngineErrorCode, message: string, options: {
|
|
57
|
+
category: ErrorCategory;
|
|
58
|
+
retryable?: boolean;
|
|
59
|
+
details?: Record<string, unknown>;
|
|
60
|
+
}): AldusError;
|
|
61
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAErE,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB;IAC/B,oDAAoD;aACpD,cAAc,EAAE,sBAAsB;IACtC,oFAAoF;aACpF,uBAAuB,EAAE,+BAA+B;IACxD;;;;;OAKG;aACH,qBAAqB,EAAE,6BAA6B;IACpD;;;;;;OAMG;aACH,wBAAwB,EAAE,gCAAgC;IAC1D,kFAAkF;aAClF,wBAAwB,EAAE,gCAAgC;IAC1D;;;;;OAKG;aACH,qBAAqB,EAAE,6BAA6B;IACpD;;;;OAIG;aACH,mBAAmB,EAAE,2BAA2B;IAChD,2FAA2F;aAC3F,oBAAoB,EAAE,4BAA4B;IAClD,6EAA6E;aAC7E,iBAAiB,EAAE,yBAAyB;IAC5C,8DAA8D;aAC9D,eAAe,EAAE,uBAAuB;CAChC,CAAC;AAEX,gCAAgC;AAChC,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,OAAO,oBAAoB,CAAC,CAAC;AAEnG,+DAA+D;AAC/D,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC3F,UAAU,CAEZ"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failures specific to gate evaluation and spend authorization.
|
|
3
|
+
*
|
|
4
|
+
* Aldus Core deliberately keeps no central error-code registry, so that a package can name a new
|
|
5
|
+
* failure without forking Core. These codes are this package's contribution; they carry the same
|
|
6
|
+
* `ALDUS_` prefix and `SCREAMING_SNAKE_CASE` shape so production trace (contract §20) stays
|
|
7
|
+
* uniform across packages.
|
|
8
|
+
*/
|
|
9
|
+
import { AldusError } from "@aldus-runtime/core";
|
|
10
|
+
/** Error codes raised by the gate engine. */
|
|
11
|
+
export const GateEngineErrorCodes = {
|
|
12
|
+
/** A gate was referenced that is not registered. */
|
|
13
|
+
GATE_NOT_FOUND: "ALDUS_GATE_NOT_FOUND",
|
|
14
|
+
/** A gate definition is internally inconsistent and was refused at registration. */
|
|
15
|
+
GATE_DEFINITION_INVALID: "ALDUS_GATE_DEFINITION_INVALID",
|
|
16
|
+
/**
|
|
17
|
+
* Gate dependencies form a cycle.
|
|
18
|
+
*
|
|
19
|
+
* A configuration fault, not a data fault: contract §13.1's cascade is only meaningful over a
|
|
20
|
+
* directed acyclic graph, and a cycle would make "what does this invalidate" unanswerable.
|
|
21
|
+
*/
|
|
22
|
+
GATE_DEPENDENCY_CYCLE: "ALDUS_GATE_DEPENDENCY_CYCLE",
|
|
23
|
+
/**
|
|
24
|
+
* A decision was submitted by an actor the gate does not accept.
|
|
25
|
+
*
|
|
26
|
+
* Contract §13.3 keeps final performance approval human-owned, and §12 reserves the human
|
|
27
|
+
* oracle level for subjective and asymmetric-risk judgements. A machine actor satisfying such
|
|
28
|
+
* a gate would present a machine pass as semantic correctness, which §12 forbids outright.
|
|
29
|
+
*/
|
|
30
|
+
GATE_ACTOR_NOT_PERMITTED: "ALDUS_GATE_ACTOR_NOT_PERMITTED",
|
|
31
|
+
/** A decision was submitted that does not bind the subjects its gate requires. */
|
|
32
|
+
GATE_SUBJECTS_INCOMPLETE: "ALDUS_GATE_SUBJECTS_INCOMPLETE",
|
|
33
|
+
/**
|
|
34
|
+
* An operation requiring authorization was attempted without a valid one.
|
|
35
|
+
*
|
|
36
|
+
* Contract §13.2: paid TTS MUST NOT run until the operator approves. This is the refusal that
|
|
37
|
+
* enforces it.
|
|
38
|
+
*/
|
|
39
|
+
AUTHORIZATION_MISSING: "ALDUS_AUTHORIZATION_MISSING",
|
|
40
|
+
/**
|
|
41
|
+
* An authorization exists but no longer binds the current inputs.
|
|
42
|
+
*
|
|
43
|
+
* Contract §13.2: "The authorization MUST be invalidated if any bound value changes."
|
|
44
|
+
*/
|
|
45
|
+
AUTHORIZATION_STALE: "ALDUS_AUTHORIZATION_STALE",
|
|
46
|
+
/** A spend request would exceed the authorized maximum (contract §19.3 stop-on-budget). */
|
|
47
|
+
SPEND_LIMIT_EXCEEDED: "ALDUS_SPEND_LIMIT_EXCEEDED",
|
|
48
|
+
/** Two monetary values in different currencies were combined or compared. */
|
|
49
|
+
CURRENCY_MISMATCH: "ALDUS_CURRENCY_MISMATCH",
|
|
50
|
+
/** A monetary amount was not a well-formed decimal string. */
|
|
51
|
+
MONEY_MALFORMED: "ALDUS_MONEY_MALFORMED",
|
|
52
|
+
};
|
|
53
|
+
/** Construct an {@link AldusError} with a gate-engine code. */
|
|
54
|
+
export function gateEngineError(code, message, options) {
|
|
55
|
+
return new AldusError(code, message, options);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAsB,MAAM,qBAAqB,CAAC;AAErE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,oDAAoD;IACpD,cAAc,EAAE,sBAAsB;IACtC,oFAAoF;IACpF,uBAAuB,EAAE,+BAA+B;IACxD;;;;;OAKG;IACH,qBAAqB,EAAE,6BAA6B;IACpD;;;;;;OAMG;IACH,wBAAwB,EAAE,gCAAgC;IAC1D,kFAAkF;IAClF,wBAAwB,EAAE,gCAAgC;IAC1D;;;;;OAKG;IACH,qBAAqB,EAAE,6BAA6B;IACpD;;;;OAIG;IACH,mBAAmB,EAAE,2BAA2B;IAChD,2FAA2F;IAC3F,oBAAoB,EAAE,4BAA4B;IAClD,6EAA6E;IAC7E,iBAAiB,EAAE,yBAAyB;IAC5C,8DAA8D;IAC9D,eAAe,EAAE,uBAAuB;CAChC,CAAC;AAKX,+DAA+D;AAC/D,MAAM,UAAU,eAAe,CAC7B,IAAyB,EACzB,OAAe,EACf,OAA4F;IAE5F,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@aldus-runtime/gate-engine` — hash-bound human gates, cascading invalidation, and spend authorization.
|
|
3
|
+
*
|
|
4
|
+
* Implements architecture contract §22 **WP-05**, covering §12 (quality levels), §13 (human gates
|
|
5
|
+
* and freezes), and §19.3 (cost governance).
|
|
6
|
+
*
|
|
7
|
+
* What this package is for, in one sentence: making it impossible to spend money or publish
|
|
8
|
+
* anything on the strength of an approval that no longer describes what is about to happen.
|
|
9
|
+
*
|
|
10
|
+
* Three properties carry that weight:
|
|
11
|
+
*
|
|
12
|
+
* - **A decision binds to digests.** §3.6 requires human review to produce a durable record "tied
|
|
13
|
+
* to exact inputs", and §13.2 voids an authorization if any bound value changes.
|
|
14
|
+
* - **Invalidation is derived, never stored.** A gate's state is recomputed from its decision,
|
|
15
|
+
* its current inputs, and its dependencies. There is no "valid" flag for a stale approval to
|
|
16
|
+
* survive in, so §13.1's cascade cannot be half-applied.
|
|
17
|
+
* - **A grant's ceiling is itself bound.** §13.2 requires the operator to approve a maximum
|
|
18
|
+
* authorized cost, so the limits' digest sits among the decision's subject hashes and raising
|
|
19
|
+
* the ceiling voids the approval that permitted the spend.
|
|
20
|
+
*
|
|
21
|
+
* What it deliberately does not do: run any check that feeds a gate. §12's evaluators, §12.1's
|
|
22
|
+
* calibration metrics (WP-10), the TTS ledger (WP-07), and the release adapters (WP-12) are
|
|
23
|
+
* elsewhere. This package models the decisions; it does not make them.
|
|
24
|
+
*
|
|
25
|
+
* Contract §13 names four gates — Content Freeze, Performance Freeze, Human Ear, Final Release —
|
|
26
|
+
* and none is hardcoded. They are the definitions an adopter is most likely to write (§4.2, §4.3).
|
|
27
|
+
*
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
export { GATE_ENFORCEMENTS, GATE_LEVELS, GateRegistry, validateGateDefinition, type GateDefinition, type GateEnforcement, type GateLevel, type PromotionEvidence, type ResolvedGateDefinition, } from "./definition.js";
|
|
31
|
+
export { assertSubjectsCover, detectDrift, digestBytes, digestSubjectValue, toSubjectHashes, type GateSubject, type SubjectDrift, } from "./binding.js";
|
|
32
|
+
export { GATE_STATES, GateEngine, type AuthorizationGrant, type AuthorizationRefusal, type AuthorizationResult, type DecideInput, type GateEngineOptions, type GateState, type GateStatus, type SpendAuthorization, type SubjectsByGate, } from "./engine.js";
|
|
33
|
+
export { SPEND_LIMIT_SUBJECT_KEY, checkSpend, computeLedger, consumesBudget, costRecordDraw, grantLimitsDigest, type SpendCheck, type SpendGrant, type SpendLedger, type SpendRefusalReason, type SpendRequest, } from "./spend.js";
|
|
34
|
+
export { addMoney, assertMoney, compareMoney, formatMoney, isNegativeMoney, isPositiveMoney, subtractMoney, sumMoney, zeroMoney, } from "./money.js";
|
|
35
|
+
export { MemoryCostReader, MemoryGateDecisionStore, MemoryGateEventSink, type CostReader, type GateDecisionStore, type GateEventSink, } from "./ports.js";
|
|
36
|
+
export { GateEngineErrorCodes, gateEngineError, type GateEngineErrorCode } from "./errors.js";
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,WAAW,EACX,eAAe,EACf,eAAe,EACf,aAAa,EACb,QAAQ,EACR,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@aldus-runtime/gate-engine` — hash-bound human gates, cascading invalidation, and spend authorization.
|
|
3
|
+
*
|
|
4
|
+
* Implements architecture contract §22 **WP-05**, covering §12 (quality levels), §13 (human gates
|
|
5
|
+
* and freezes), and §19.3 (cost governance).
|
|
6
|
+
*
|
|
7
|
+
* What this package is for, in one sentence: making it impossible to spend money or publish
|
|
8
|
+
* anything on the strength of an approval that no longer describes what is about to happen.
|
|
9
|
+
*
|
|
10
|
+
* Three properties carry that weight:
|
|
11
|
+
*
|
|
12
|
+
* - **A decision binds to digests.** §3.6 requires human review to produce a durable record "tied
|
|
13
|
+
* to exact inputs", and §13.2 voids an authorization if any bound value changes.
|
|
14
|
+
* - **Invalidation is derived, never stored.** A gate's state is recomputed from its decision,
|
|
15
|
+
* its current inputs, and its dependencies. There is no "valid" flag for a stale approval to
|
|
16
|
+
* survive in, so §13.1's cascade cannot be half-applied.
|
|
17
|
+
* - **A grant's ceiling is itself bound.** §13.2 requires the operator to approve a maximum
|
|
18
|
+
* authorized cost, so the limits' digest sits among the decision's subject hashes and raising
|
|
19
|
+
* the ceiling voids the approval that permitted the spend.
|
|
20
|
+
*
|
|
21
|
+
* What it deliberately does not do: run any check that feeds a gate. §12's evaluators, §12.1's
|
|
22
|
+
* calibration metrics (WP-10), the TTS ledger (WP-07), and the release adapters (WP-12) are
|
|
23
|
+
* elsewhere. This package models the decisions; it does not make them.
|
|
24
|
+
*
|
|
25
|
+
* Contract §13 names four gates — Content Freeze, Performance Freeze, Human Ear, Final Release —
|
|
26
|
+
* and none is hardcoded. They are the definitions an adopter is most likely to write (§4.2, §4.3).
|
|
27
|
+
*
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
export { GATE_ENFORCEMENTS, GATE_LEVELS, GateRegistry, validateGateDefinition, } from "./definition.js";
|
|
31
|
+
export { assertSubjectsCover, detectDrift, digestBytes, digestSubjectValue, toSubjectHashes, } from "./binding.js";
|
|
32
|
+
export { GATE_STATES, GateEngine, } from "./engine.js";
|
|
33
|
+
export { SPEND_LIMIT_SUBJECT_KEY, checkSpend, computeLedger, consumesBudget, costRecordDraw, grantLimitsDigest, } from "./spend.js";
|
|
34
|
+
export { addMoney, assertMoney, compareMoney, formatMoney, isNegativeMoney, isPositiveMoney, subtractMoney, sumMoney, zeroMoney, } from "./money.js";
|
|
35
|
+
export { MemoryCostReader, MemoryGateDecisionStore, MemoryGateEventSink, } from "./ports.js";
|
|
36
|
+
export { GateEngineErrorCodes, gateEngineError } from "./errors.js";
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,sBAAsB,GAMvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,eAAe,GAGhB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,UAAU,GAUX,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACd,iBAAiB,GAMlB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,WAAW,EACX,eAAe,EACf,eAAe,EACf,aAAa,EACb,QAAQ,EACR,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,GAIpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAA4B,MAAM,aAAa,CAAC"}
|
package/dist/money.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exact decimal arithmetic on {@link Money}.
|
|
3
|
+
*
|
|
4
|
+
* Contract §19.3 requires per-request and per-run limits, actual cost recording, and
|
|
5
|
+
* stop-on-budget behaviour. All three are comparisons and sums over money, and Core deliberately
|
|
6
|
+
* models an amount as a decimal *string* because TTS costs are fractional-cent and IEEE-754
|
|
7
|
+
* accumulation silently corrupts the totals an operator authorises spend against.
|
|
8
|
+
*
|
|
9
|
+
* Honouring that decision means never converting an amount to `number`. Every operation here
|
|
10
|
+
* scales both operands to a common exponent and works in `bigint`, so a sum of ten thousand
|
|
11
|
+
* ten-thousandth-of-a-cent charges is exact rather than approximately exact.
|
|
12
|
+
*/
|
|
13
|
+
import type { Money } from "@aldus-runtime/core";
|
|
14
|
+
/** A zero amount in the given currency. */
|
|
15
|
+
export declare function zeroMoney(currency: string): Money;
|
|
16
|
+
/**
|
|
17
|
+
* Sum two amounts exactly.
|
|
18
|
+
*
|
|
19
|
+
* @throws {AldusError} `ALDUS_CURRENCY_MISMATCH` if the currencies differ.
|
|
20
|
+
*/
|
|
21
|
+
export declare function addMoney(a: Money, b: Money): Money;
|
|
22
|
+
/**
|
|
23
|
+
* Subtract `b` from `a` exactly. The result may be negative.
|
|
24
|
+
*
|
|
25
|
+
* @throws {AldusError} `ALDUS_CURRENCY_MISMATCH` if the currencies differ.
|
|
26
|
+
*/
|
|
27
|
+
export declare function subtractMoney(a: Money, b: Money): Money;
|
|
28
|
+
/**
|
|
29
|
+
* Total a list of amounts exactly.
|
|
30
|
+
*
|
|
31
|
+
* @throws {AldusError} `ALDUS_CURRENCY_MISMATCH` if the amounts are not all one currency.
|
|
32
|
+
*/
|
|
33
|
+
export declare function sumMoney(amounts: readonly Money[], currency: string): Money;
|
|
34
|
+
/**
|
|
35
|
+
* Compare two amounts: `-1` if `a < b`, `0` if equal, `1` if `a > b`.
|
|
36
|
+
*
|
|
37
|
+
* Numerically equal amounts written differently — `"1.5"` and `"1.50"` — compare equal, because
|
|
38
|
+
* trailing zeros are a presentation choice and treating them as a difference would make a budget
|
|
39
|
+
* check depend on how a provider happened to format its invoice.
|
|
40
|
+
*
|
|
41
|
+
* @throws {AldusError} `ALDUS_CURRENCY_MISMATCH` if the currencies differ.
|
|
42
|
+
*/
|
|
43
|
+
export declare function compareMoney(a: Money, b: Money): -1 | 0 | 1;
|
|
44
|
+
/** True if the amount is greater than zero. */
|
|
45
|
+
export declare function isPositiveMoney(money: Money): boolean;
|
|
46
|
+
/** True if the amount is below zero. */
|
|
47
|
+
export declare function isNegativeMoney(money: Money): boolean;
|
|
48
|
+
/** Validate an amount, raising `ALDUS_MONEY_MALFORMED` if it is not an exact decimal. */
|
|
49
|
+
export declare function assertMoney(money: Money, context?: Record<string, unknown>): Money;
|
|
50
|
+
/** Render an amount for an operator-facing message. */
|
|
51
|
+
export declare function formatMoney(money: Money): string;
|
|
52
|
+
//# sourceMappingURL=money.d.ts.map
|