@affiant/core 0.1.0-alpha.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 +202 -0
- package/README.md +354 -0
- package/dist/context.d.ts +136 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +30 -0
- package/dist/context.js.map +1 -0
- package/dist/docket/entry.d.ts +421 -0
- package/dist/docket/entry.d.ts.map +1 -0
- package/dist/docket/entry.js +155 -0
- package/dist/docket/entry.js.map +1 -0
- package/dist/docket/expiry.d.ts +82 -0
- package/dist/docket/expiry.d.ts.map +1 -0
- package/dist/docket/expiry.js +106 -0
- package/dist/docket/expiry.js.map +1 -0
- package/dist/docket/memory.d.ts +163 -0
- package/dist/docket/memory.d.ts.map +1 -0
- package/dist/docket/memory.js +528 -0
- package/dist/docket/memory.js.map +1 -0
- package/dist/docket/store.d.ts +387 -0
- package/dist/docket/store.d.ts.map +1 -0
- package/dist/docket/store.js +51 -0
- package/dist/docket/store.js.map +1 -0
- package/dist/errors.d.ts +153 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +164 -0
- package/dist/errors.js.map +1 -0
- package/dist/gate/coverage.d.ts +152 -0
- package/dist/gate/coverage.d.ts.map +1 -0
- package/dist/gate/coverage.js +114 -0
- package/dist/gate/coverage.js.map +1 -0
- package/dist/gate/decide.d.ts +207 -0
- package/dist/gate/decide.d.ts.map +1 -0
- package/dist/gate/decide.js +559 -0
- package/dist/gate/decide.js.map +1 -0
- package/dist/gate/gate.d.ts +212 -0
- package/dist/gate/gate.d.ts.map +1 -0
- package/dist/gate/gate.js +175 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/pipeline.d.ts +285 -0
- package/dist/gate/pipeline.d.ts.map +1 -0
- package/dist/gate/pipeline.js +515 -0
- package/dist/gate/pipeline.js.map +1 -0
- package/dist/gate/policy.d.ts +272 -0
- package/dist/gate/policy.d.ts.map +1 -0
- package/dist/gate/policy.js +396 -0
- package/dist/gate/policy.js.map +1 -0
- package/dist/gate/wrap.d.ts +107 -0
- package/dist/gate/wrap.d.ts.map +1 -0
- package/dist/gate/wrap.js +164 -0
- package/dist/gate/wrap.js.map +1 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -0
- package/dist/model/affidavit.d.ts +354 -0
- package/dist/model/affidavit.d.ts.map +1 -0
- package/dist/model/affidavit.js +417 -0
- package/dist/model/affidavit.js.map +1 -0
- package/dist/model/amendments.d.ts +160 -0
- package/dist/model/amendments.d.ts.map +1 -0
- package/dist/model/amendments.js +183 -0
- package/dist/model/amendments.js.map +1 -0
- package/dist/model/canonical.d.ts +311 -0
- package/dist/model/canonical.d.ts.map +1 -0
- package/dist/model/canonical.js +665 -0
- package/dist/model/canonical.js.map +1 -0
- package/dist/model/money.d.ts +127 -0
- package/dist/model/money.d.ts.map +1 -0
- package/dist/model/money.js +177 -0
- package/dist/model/money.js.map +1 -0
- package/dist/model/provenance.d.ts +315 -0
- package/dist/model/provenance.d.ts.map +1 -0
- package/dist/model/provenance.js +223 -0
- package/dist/model/provenance.js.map +1 -0
- package/dist/ports.d.ts +269 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +34 -0
- package/dist/ports.js.map +1 -0
- package/dist/store-memory.d.ts +21 -0
- package/dist/store-memory.d.ts.map +1 -0
- package/dist/store-memory.js +20 -0
- package/dist/store-memory.js.map +1 -0
- package/dist/telemetry-keys.d.ts +65 -0
- package/dist/telemetry-keys.d.ts.map +1 -0
- package/dist/telemetry-keys.js +72 -0
- package/dist/telemetry-keys.js.map +1 -0
- package/dist/telemetry.d.ts +77 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +43 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/testing.d.ts +574 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +1291 -0
- package/dist/testing.js.map +1 -0
- package/package.json +75 -0
- package/telemetry-keys.json +92 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../src/model/provenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance: the seven-source ladder, the tag, the binding that makes a tag
|
|
3
|
+
* checkable, the chain that keeps every superseded tag, and the merge rule.
|
|
4
|
+
*
|
|
5
|
+
* **Rules served: PV-1** (the ladder, the chain, confidence-first /
|
|
6
|
+
* determinism-second merge, confidence clamped into `[0, 1]`), **PV-2** (a tag
|
|
7
|
+
* above `Conversation` carries a binding, and the binding kinds are a fixed set),
|
|
8
|
+
* **PV-3** (an implementation's own inference never mints `UserStated`), **PV-5**
|
|
9
|
+
* (no wire type raises a grade: an asserted grade above `Conversation` with no
|
|
10
|
+
* binding is carried on the record but is not honourable).
|
|
11
|
+
*
|
|
12
|
+
* The idea in one paragraph: a value on an Affidavit is worth exactly what its
|
|
13
|
+
* evidence is worth. A provenance tag says where the value came from
|
|
14
|
+
* ({@link ProvenanceSource}), how confident its producer was, and — for the grades
|
|
15
|
+
* that claim more than "a model read it in the conversation" — a {@link Binding}:
|
|
16
|
+
* a pointer at something an auditor can go and check years later. A tag with no
|
|
17
|
+
* binding is not a lie, it is a weaker claim, and the framework's job is to keep
|
|
18
|
+
* the difference visible rather than to average it away.
|
|
19
|
+
*
|
|
20
|
+
* Nothing here reads a clock. Every function that stamps a time takes the instant
|
|
21
|
+
* as a parameter, so a fixture can pin it (RT-1, and the same reason the clock is
|
|
22
|
+
* a port rather than a call to `Date.now()`).
|
|
23
|
+
*
|
|
24
|
+
* @packageDocumentation
|
|
25
|
+
*/
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// The ladder (PV-1)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* The seven provenance sources, **most deterministic first**.
|
|
31
|
+
*
|
|
32
|
+
* This order is not a preference, it is the tie-breaker: when two tags carry equal
|
|
33
|
+
* confidence the one nearer the front of this list wins the merge (PV-1). Read it
|
|
34
|
+
* as a claim about who could re-derive the value — the person said it; a system of
|
|
35
|
+
* record holds it; a named rule computes it; it was literally present in the
|
|
36
|
+
* conversation; a model reasoned to it; a default filled it in; nobody knows.
|
|
37
|
+
*
|
|
38
|
+
* Spelled out here rather than re-exported from `@affiant/contract` so the gate's
|
|
39
|
+
* ordering is a fact of the gate. `test/provenance.test.ts` asserts the two lists
|
|
40
|
+
* are identical, which is what keeps them from drifting apart.
|
|
41
|
+
*/
|
|
42
|
+
export const PROVENANCE_LADDER = [
|
|
43
|
+
"UserStated",
|
|
44
|
+
"External",
|
|
45
|
+
"Computed",
|
|
46
|
+
"Conversation",
|
|
47
|
+
"Inferred",
|
|
48
|
+
"Default",
|
|
49
|
+
"Empty",
|
|
50
|
+
];
|
|
51
|
+
/** Rank by position in {@link PROVENANCE_LADDER}, computed once. */
|
|
52
|
+
const RANK = Object.freeze(Object.fromEntries(PROVENANCE_LADDER.map((source, index) => [source, index])));
|
|
53
|
+
/**
|
|
54
|
+
* How deterministic `source` is: `0` for `UserStated`, `6` for `Empty`.
|
|
55
|
+
*
|
|
56
|
+
* **Lower is more deterministic.** The number is an index into
|
|
57
|
+
* {@link PROVENANCE_LADDER}, so it is a comparison key and nothing else — never a
|
|
58
|
+
* score, never a weight, never something to multiply a confidence by.
|
|
59
|
+
*/
|
|
60
|
+
export function determinismRank(source) {
|
|
61
|
+
return RANK[source];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Whether a tag with this source must carry a {@link Binding} to be worth its grade
|
|
65
|
+
* (PV-2): the three sources **above** `Conversation` — `UserStated`, `External`,
|
|
66
|
+
* `Computed`.
|
|
67
|
+
*
|
|
68
|
+
* At or below `Conversation` the grade already says "this came from the turn, or
|
|
69
|
+
* from a model reading the turn", and the turn is itself the artifact. Above it,
|
|
70
|
+
* the tag claims an artifact outside the conversation, and a claim with no pointer
|
|
71
|
+
* at that artifact is not checkable — see {@link isBound} and PV-4, where the pair
|
|
72
|
+
* decides whether a person-free approval may rest on the tag.
|
|
73
|
+
*/
|
|
74
|
+
export function requiresBinding(source) {
|
|
75
|
+
return determinismRank(source) < determinismRank("Conversation");
|
|
76
|
+
}
|
|
77
|
+
/** Every {@link Binding} kind, as data. */
|
|
78
|
+
export const BINDING_KINDS = [
|
|
79
|
+
"utterance-span",
|
|
80
|
+
"reviewer-act",
|
|
81
|
+
"form-input",
|
|
82
|
+
"external-ref",
|
|
83
|
+
"computation-ref",
|
|
84
|
+
];
|
|
85
|
+
/**
|
|
86
|
+
* Clamp a producer-reported confidence into `[0, 1]` (PV-1).
|
|
87
|
+
*
|
|
88
|
+
* `NaN` becomes `0`: a number that is not a number is not a claim, and the shipped
|
|
89
|
+
* .NET inference step floors at 0 without capping, which is the defect this closes.
|
|
90
|
+
*/
|
|
91
|
+
function clampConfidence(confidence) {
|
|
92
|
+
if (Number.isNaN(confidence))
|
|
93
|
+
return 0;
|
|
94
|
+
if (confidence < 0)
|
|
95
|
+
return 0;
|
|
96
|
+
if (confidence > 1)
|
|
97
|
+
return 1;
|
|
98
|
+
return confidence;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Mint a tag for any source, clamping the confidence into `[0, 1]` (PV-1).
|
|
102
|
+
*
|
|
103
|
+
* A tag whose source is `Empty` is forced to confidence `0`: "nobody knows where
|
|
104
|
+
* this came from" cannot also be a confident claim, and AF-2 counts every `Empty`
|
|
105
|
+
* field as `0` in the aggregate anyway — forcing it here means the two can never
|
|
106
|
+
* disagree.
|
|
107
|
+
*
|
|
108
|
+
* This is the general minting surface, used by deterministic interceptors, by the
|
|
109
|
+
* projection step and by a reviewer's amendment. **It is not the surface the
|
|
110
|
+
* inference step gets:** PV-3 forbids an implementation's own inference from
|
|
111
|
+
* minting `UserStated`, so the inference step is handed {@link mintInference},
|
|
112
|
+
* whose source parameter is typed {@link InferenceSource} and cannot name it.
|
|
113
|
+
*/
|
|
114
|
+
export function mintTag(options) {
|
|
115
|
+
const confidence = options.source === "Empty" ? 0 : clampConfidence(options.confidence);
|
|
116
|
+
return {
|
|
117
|
+
source: options.source,
|
|
118
|
+
confidence,
|
|
119
|
+
note: options.note ?? null,
|
|
120
|
+
at: options.at,
|
|
121
|
+
conversationTurn: options.conversationTurn ?? null,
|
|
122
|
+
binding: options.binding ?? null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Mint a tag from the inference step. The source parameter is
|
|
127
|
+
* {@link InferenceSource}, so `UserStated` is a compile error here (PV-3).
|
|
128
|
+
*
|
|
129
|
+
* The runtime guard exists for callers with no type-checker — a JavaScript host, a
|
|
130
|
+
* value cast at the boundary — because PV-3 is a rule about what the record may
|
|
131
|
+
* say, not about what TypeScript can see.
|
|
132
|
+
*
|
|
133
|
+
* @throws RangeError if `source` is anything but `Conversation` or `Inferred`.
|
|
134
|
+
*/
|
|
135
|
+
export function mintInference(source, options) {
|
|
136
|
+
if (source !== "Conversation" && source !== "Inferred") {
|
|
137
|
+
throw new RangeError(`PV-3: inference may mint only "Conversation" or "Inferred", not ${JSON.stringify(source)}; ` +
|
|
138
|
+
`"UserStated" is an observation of a person's act, never the host vouching for its own value`);
|
|
139
|
+
}
|
|
140
|
+
return mintTag({ ...options, source });
|
|
141
|
+
}
|
|
142
|
+
/** {@link mintInference} with source `Conversation`: the value was literally in the turn. */
|
|
143
|
+
export function mintConversation(options) {
|
|
144
|
+
return mintInference("Conversation", options);
|
|
145
|
+
}
|
|
146
|
+
/** {@link mintInference} with source `Inferred`: the model reasoned to the value. */
|
|
147
|
+
export function mintInferred(options) {
|
|
148
|
+
return mintInference("Inferred", options);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The tag a field carries when nobody knows where its value came from: source
|
|
152
|
+
* `Empty`, confidence `0` (AF-1 — present and tagged, never omitted).
|
|
153
|
+
*/
|
|
154
|
+
export function emptyTag(at, note = null) {
|
|
155
|
+
return mintTag({ source: "Empty", confidence: 0, at, note });
|
|
156
|
+
}
|
|
157
|
+
/** Whether `tag` points at something an auditor can check (PV-2). */
|
|
158
|
+
export function isBound(tag) {
|
|
159
|
+
return tag.binding !== null && tag.binding !== undefined;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Whether `tag`'s grade is one a person-free verdict may rest on: either the grade
|
|
163
|
+
* needs no binding, or it has one (PV-4, PV-5).
|
|
164
|
+
*
|
|
165
|
+
* The unhonourable case is exactly the one PV-5 names: a caller asserts
|
|
166
|
+
* `UserStated` on the wire and points at nothing. The tag is still recorded — the
|
|
167
|
+
* record says what the caller claimed — but a Standing Order that predicates on it
|
|
168
|
+
* falls back to asking a person.
|
|
169
|
+
*/
|
|
170
|
+
export function isHonourable(tag) {
|
|
171
|
+
return !requiresBinding(tag.source) || isBound(tag);
|
|
172
|
+
}
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Chains and the merge rule (PV-1)
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
/** A fresh chain holding one tag and no history. */
|
|
177
|
+
export function chainOf(tag) {
|
|
178
|
+
return { current: tag, prior: [] };
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Whether `challenger` beats `incumbent`: higher confidence first, ties broken
|
|
182
|
+
* toward the more deterministic source (PV-1).
|
|
183
|
+
*
|
|
184
|
+
* An exact tie — same confidence, same source — leaves the incumbent in force. It
|
|
185
|
+
* was there first and the challenger brings nothing new; the challenger is still
|
|
186
|
+
* preserved in the chain, so the fact that two producers agreed is on the record.
|
|
187
|
+
*/
|
|
188
|
+
function beats(challenger, incumbent) {
|
|
189
|
+
if (challenger.confidence !== incumbent.confidence) {
|
|
190
|
+
return challenger.confidence > incumbent.confidence;
|
|
191
|
+
}
|
|
192
|
+
return determinismRank(challenger.source) < determinismRank(incumbent.source);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Merge `incoming` into `chain` (PV-1): the higher confidence wins, ties break
|
|
196
|
+
* toward the more deterministic source, **and the loser is preserved** at the head
|
|
197
|
+
* of `prior`.
|
|
198
|
+
*
|
|
199
|
+
* This is the step where a deterministic interceptor's `External` value displaces
|
|
200
|
+
* a model's guess, or fails to. Either way both tags survive, so a card can show a
|
|
201
|
+
* reviewer that the model said one thing and the system of record said another.
|
|
202
|
+
*/
|
|
203
|
+
export function merge(chain, incoming) {
|
|
204
|
+
if (beats(incoming, chain.current)) {
|
|
205
|
+
return { current: incoming, prior: [chain.current, ...chain.prior] };
|
|
206
|
+
}
|
|
207
|
+
return { current: chain.current, prior: [incoming, ...chain.prior] };
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Put `tag` in force unconditionally, pushing the tag it displaces onto `prior`.
|
|
211
|
+
*
|
|
212
|
+
* Not a merge: a reviewer's amendment is not a confidence contest it might lose
|
|
213
|
+
* (AF-4, PV-2). When a person corrects a field, their act is the provenance of the
|
|
214
|
+
* new value even if the machine was more sure of the old one.
|
|
215
|
+
*/
|
|
216
|
+
export function supersede(chain, tag) {
|
|
217
|
+
return { current: tag, prior: [chain.current, ...chain.prior] };
|
|
218
|
+
}
|
|
219
|
+
/** Every tag in `chain`, in force first and then oldest-displaced last. */
|
|
220
|
+
export function tagsOf(chain) {
|
|
221
|
+
return [chain.current, ...chain.prior];
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../src/model/provenance.ts"],"names":[],"mappings":"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"}
|
package/dist/ports.d.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ports a host supplies. Types only — this module has no runtime behaviour
|
|
3
|
+
* beyond {@link defaultClock}.
|
|
4
|
+
*
|
|
5
|
+
* **Rules served: GT-1** (the pipeline runs in protocol order, and every step it
|
|
6
|
+
* cannot do itself is a port), **GT-5** (a Standing Order that declares a risk
|
|
7
|
+
* threshold is compared against a host-supplied scorer), **AZ-2** (decision
|
|
8
|
+
* authorization is the host's answer, and the gate fails closed on it), **CV-1**
|
|
9
|
+
* (a port the gate needs and does not have is a wire-up failure, not a runtime
|
|
10
|
+
* surprise), **GT-2** (every port method that needs to know who is asking is
|
|
11
|
+
* handed the {@link TurnContext}; none of them may go looking).
|
|
12
|
+
*
|
|
13
|
+
* The shape of this file is the framework's central claim: **the core ships no
|
|
14
|
+
* model client, no scoring formula, no executor and no store.** It decides *what
|
|
15
|
+
* must be sworn to and who must agree*, and it asks the host for everything else.
|
|
16
|
+
* That is what lets one gate sit in front of any model, any database and any
|
|
17
|
+
* approval surface — and it is why a host cannot accidentally end up with a gate
|
|
18
|
+
* that scores its own risk or executes its own writes.
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
import type { Principal, TurnContext, Turn } from "./context.js";
|
|
23
|
+
import type { DocketEntry } from "./docket/entry.js";
|
|
24
|
+
import type { Affidavit, JsonValue } from "./model/affidavit.js";
|
|
25
|
+
import type { InterceptorBinding } from "./model/provenance.js";
|
|
26
|
+
export type { TelemetryPort, TelemetryEvent, TelemetryAttributes } from "./telemetry.js";
|
|
27
|
+
/**
|
|
28
|
+
* The bindings a deterministic interceptor may mint, re-exported from the model.
|
|
29
|
+
*
|
|
30
|
+
* The type lives in `model/provenance.ts` with the other four binding kinds (PV-2);
|
|
31
|
+
* it is re-exported here because an interceptor is a port, and a host writing one
|
|
32
|
+
* should not have to know which module the binding came from.
|
|
33
|
+
*/
|
|
34
|
+
export type { InterceptorBinding };
|
|
35
|
+
/**
|
|
36
|
+
* The write being proposed, named the way the host names it.
|
|
37
|
+
*
|
|
38
|
+
* `create` carries no `entityId` because none exists yet; `update` always carries
|
|
39
|
+
* one. That is the distinction the projection step turns into `previousValue:
|
|
40
|
+
* null` on every field of a create (AF-3), so it is spelled as a discriminated
|
|
41
|
+
* union rather than a nullable string a caller could get wrong.
|
|
42
|
+
*/
|
|
43
|
+
export type Operation = {
|
|
44
|
+
/** A new entity. */
|
|
45
|
+
readonly kind: "create";
|
|
46
|
+
/** The kind of domain entity being written, named by the host. */
|
|
47
|
+
readonly entityType: string;
|
|
48
|
+
/** Always `null` for a create — no identifier exists yet. */
|
|
49
|
+
readonly entityId: null;
|
|
50
|
+
/** The names of the fields being proposed. */
|
|
51
|
+
readonly fields: readonly string[];
|
|
52
|
+
} | {
|
|
53
|
+
/** An existing entity. */
|
|
54
|
+
readonly kind: "update";
|
|
55
|
+
/** The kind of domain entity being written, named by the host. */
|
|
56
|
+
readonly entityType: string;
|
|
57
|
+
/** The identifier of the entity being written. Never `null` for an update. */
|
|
58
|
+
readonly entityId: string;
|
|
59
|
+
/** The names of the fields being proposed. */
|
|
60
|
+
readonly fields: readonly string[];
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* What a single field is, as far as the inference port needs to know: enough to ask
|
|
64
|
+
* a model for a value and to reject one that does not fit.
|
|
65
|
+
*
|
|
66
|
+
* `kind` is the wire's rendering hint, reused here so the description a model is
|
|
67
|
+
* given and the control a reviewer sees cannot drift apart.
|
|
68
|
+
*/
|
|
69
|
+
export interface FieldSchemaEntry {
|
|
70
|
+
/** The field's name on the target entity. The key everything else is keyed by. */
|
|
71
|
+
readonly name: string;
|
|
72
|
+
/** What sort of value this is. */
|
|
73
|
+
readonly kind: "text" | "number" | "date" | "enum";
|
|
74
|
+
/** What the field means, for the model and for the reviewer. `null` when the name says it. */
|
|
75
|
+
readonly description: string | null;
|
|
76
|
+
/** Whether the target entity requires the field. */
|
|
77
|
+
readonly required: boolean;
|
|
78
|
+
/** The closed set a value must come from when {@link FieldSchemaEntry.kind} is `"enum"`; `null` otherwise. */
|
|
79
|
+
readonly allowedValues: readonly string[] | null;
|
|
80
|
+
/**
|
|
81
|
+
* The regular expression a reviewer surface constrains the amendment input with,
|
|
82
|
+
* or `null` for no constraint.
|
|
83
|
+
*
|
|
84
|
+
* The wire Affidavit carries a `pattern` per field and `@affiant/evidence-card`
|
|
85
|
+
* sets it as the amendment input's `pattern` attribute, so without a way for a
|
|
86
|
+
* host to say what the pattern is the slot could never be filled by anything the
|
|
87
|
+
* gate produced. It is a presentation constraint, not sworn substance: the gate
|
|
88
|
+
* carries it onto the card and never validates a value against it.
|
|
89
|
+
*/
|
|
90
|
+
readonly pattern: string | null;
|
|
91
|
+
}
|
|
92
|
+
/** The fields one inference call is asked to fill, and the entity they belong to. */
|
|
93
|
+
export interface FieldSchema {
|
|
94
|
+
/** The kind of domain entity being written. */
|
|
95
|
+
readonly entityType: string;
|
|
96
|
+
/** The fields to extract, in the order the host declared them. */
|
|
97
|
+
readonly fields: readonly FieldSchemaEntry[];
|
|
98
|
+
}
|
|
99
|
+
/** Where in the utterance a value was found, as character offsets into {@link Turn.utterance}. */
|
|
100
|
+
export interface UtteranceSpan {
|
|
101
|
+
/** Inclusive start offset. */
|
|
102
|
+
readonly start: number;
|
|
103
|
+
/** Exclusive end offset. */
|
|
104
|
+
readonly end: number;
|
|
105
|
+
}
|
|
106
|
+
/** One field an inference port filled in. */
|
|
107
|
+
export interface StructuredField {
|
|
108
|
+
/** The extracted value. Any JSON value, including `null`. */
|
|
109
|
+
readonly value: JsonValue;
|
|
110
|
+
/**
|
|
111
|
+
* How confident the port is, `0.0` to `1.0`. The pipeline clamps whatever
|
|
112
|
+
* arrives into that range rather than trusting it (PV-1).
|
|
113
|
+
*/
|
|
114
|
+
readonly confidence: number;
|
|
115
|
+
/**
|
|
116
|
+
* Whether the value is literally present in the utterance (`"literal"`, tagged
|
|
117
|
+
* `Conversation`) or was reasoned to (`"inferred"`, tagged `Inferred`). The
|
|
118
|
+
* distinction is provenance, not confidence: a reviewer reads them differently.
|
|
119
|
+
*/
|
|
120
|
+
readonly presence: "literal" | "inferred";
|
|
121
|
+
/**
|
|
122
|
+
* Where in the utterance the value was found, when the port can say. `null` when
|
|
123
|
+
* it cannot — the pipeline then records the tag without an `utterance-span`
|
|
124
|
+
* binding rather than inventing offsets.
|
|
125
|
+
*/
|
|
126
|
+
readonly utteranceSpan: UtteranceSpan | null;
|
|
127
|
+
}
|
|
128
|
+
/** What one inference call returns: the fields it could fill, keyed by name. */
|
|
129
|
+
export interface StructuredResult {
|
|
130
|
+
/** The filled fields. A field the port could not fill is absent, not `null`. */
|
|
131
|
+
readonly fields: {
|
|
132
|
+
readonly [fieldName: string]: StructuredField;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* One tool-free structured extraction over the unmodified turn.
|
|
137
|
+
*
|
|
138
|
+
* "Tool-free" is the point: the gate asks the model for *values*, never for an
|
|
139
|
+
* action, so nothing the model returns can execute. The host owns the model
|
|
140
|
+
* client, the prompt and the cost.
|
|
141
|
+
*/
|
|
142
|
+
export interface InferencePort {
|
|
143
|
+
/**
|
|
144
|
+
* Extract `schema`'s fields from `turn`, verbatim as the host received it.
|
|
145
|
+
*
|
|
146
|
+
* @param turn The turn, unmodified — same object as `ctx.turn`.
|
|
147
|
+
* @param schema The fields to fill.
|
|
148
|
+
*/
|
|
149
|
+
infer(turn: Turn, schema: FieldSchema): Promise<StructuredResult>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* What the target entity holds *now*, so the Affidavit can swear to what a write
|
|
153
|
+
* would replace rather than only to what it would set.
|
|
154
|
+
*
|
|
155
|
+
* The gate never reads the host's database itself; a card that shows "was £40,
|
|
156
|
+
* becomes £4,000" only exists because the host answered this.
|
|
157
|
+
*/
|
|
158
|
+
export interface ProjectionPort {
|
|
159
|
+
/**
|
|
160
|
+
* The current values of `op.fields` on the entity `op` names.
|
|
161
|
+
*
|
|
162
|
+
* @returns A map keyed by field name, or `null` when there is nothing to project
|
|
163
|
+
* — a create, or an entity that no longer exists. A field the host
|
|
164
|
+
* cannot supply is absent from the map, which is not the same as `null`
|
|
165
|
+
* under its key (`null` means "the field is currently empty").
|
|
166
|
+
*/
|
|
167
|
+
previousValues(op: Operation, ctx: TurnContext): Promise<Record<string, JsonValue> | null>;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Whether this principal may decide this entry. The host's answer, and the gate
|
|
171
|
+
* fails closed on it (AZ-2).
|
|
172
|
+
*
|
|
173
|
+
* The gate has already refused an unresolved principal and a cross-tenant entry
|
|
174
|
+
* before it asks; this port answers the host's own question — role, ownership,
|
|
175
|
+
* separation of duties. A port that throws is a refusal, never an approval.
|
|
176
|
+
*/
|
|
177
|
+
export interface AuthorizationPort {
|
|
178
|
+
/** Whether `principal` may decide `entry`. */
|
|
179
|
+
mayDecide(principal: Principal, entry: DocketEntry): Promise<boolean>;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* How risky this write is, on the host's own scale.
|
|
183
|
+
*
|
|
184
|
+
* There is no default formula, deliberately: a number the framework invented would
|
|
185
|
+
* be compared against a threshold the operator chose, and the operator would have
|
|
186
|
+
* no way to know what they had agreed to. A policy that declares a threshold with
|
|
187
|
+
* no scorer wired is a wire-up failure (`wireup-invalid`, CV-1), not a policy that
|
|
188
|
+
* quietly never fires.
|
|
189
|
+
*/
|
|
190
|
+
export interface RiskScorer {
|
|
191
|
+
/** Score `affidavit`. The scale is the host's; the policy's threshold is on the same scale (GT-5). */
|
|
192
|
+
score(affidavit: Affidavit, ctx: TurnContext): Promise<number>;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Where "now" comes from.
|
|
196
|
+
*
|
|
197
|
+
* A port rather than a call to `Date.now()` inside the gate, for two reasons: a
|
|
198
|
+
* fixture has to be able to pin an expiry to the millisecond, and the core owns no
|
|
199
|
+
* timer of its own (DK-3) — expiry is state the host sweeps, not a callback the
|
|
200
|
+
* gate schedules.
|
|
201
|
+
*/
|
|
202
|
+
export interface Clock {
|
|
203
|
+
/** The current instant, as an ISO 8601 string in UTC. */
|
|
204
|
+
now(): string;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The clock used when a host supplies none: the Web-standard `Date`, formatted as
|
|
208
|
+
* an ISO 8601 instant in UTC.
|
|
209
|
+
*
|
|
210
|
+
* `Date` and `toISOString` are ECMAScript, present on Node, Bun and workerd alike
|
|
211
|
+
* (RT-1). No Node API, no timer, no interval — one reading, on demand.
|
|
212
|
+
*/
|
|
213
|
+
export declare const defaultClock: Clock;
|
|
214
|
+
/**
|
|
215
|
+
* The binding that makes a deterministic value checkable: which external record or
|
|
216
|
+
* computation the value came from.
|
|
217
|
+
*
|
|
218
|
+
* PV-4 is why it is mandatory on an {@link InterceptedField} rather than optional:
|
|
219
|
+
* a Standing Order — an approval with no person present — is honoured only if every
|
|
220
|
+
* provenance input the policy declares carries a binding. An `External` value with
|
|
221
|
+
* no binding is a claim nobody can re-derive, so a policy that would auto-approve
|
|
222
|
+
* on it falls back to asking a person.
|
|
223
|
+
*
|
|
224
|
+
* {@link InterceptorBinding} is the two-kind restriction of the model's `Binding`
|
|
225
|
+
* union: `external-ref` (a system of record) and `computation-ref` (a named,
|
|
226
|
+
* re-runnable rule). The other three kinds all point at something a *person* did,
|
|
227
|
+
* and PV-3 forbids a machine from minting those.
|
|
228
|
+
*/
|
|
229
|
+
/** One field a {@link FieldInterceptor} resolved. */
|
|
230
|
+
export interface InterceptedField {
|
|
231
|
+
/** The resolved value. */
|
|
232
|
+
readonly value: JsonValue;
|
|
233
|
+
/**
|
|
234
|
+
* Where it came from. Only these two: **PV-3** forbids an interceptor from
|
|
235
|
+
* minting `UserStated`, because a machine may not put words in a person's mouth.
|
|
236
|
+
*/
|
|
237
|
+
readonly source: "External" | "Computed";
|
|
238
|
+
/** How to check the value. Never absent (PV-4). */
|
|
239
|
+
readonly binding: InterceptorBinding;
|
|
240
|
+
/**
|
|
241
|
+
* How confident the interceptor is, `0.0` to `1.0`. A deterministic resolver
|
|
242
|
+
* normally says `1`; the merge step clamps whatever arrives (PV-1).
|
|
243
|
+
*/
|
|
244
|
+
readonly confidence: number;
|
|
245
|
+
/** A human-readable line for the reviewer, or `null`. */
|
|
246
|
+
readonly evidence: string | null;
|
|
247
|
+
}
|
|
248
|
+
/** The fields one interceptor resolved, keyed by field name. */
|
|
249
|
+
export type InterceptedFields = {
|
|
250
|
+
readonly [fieldName: string]: InterceptedField;
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* A host-supplied resolver that fills fields deterministically, before any model is
|
|
254
|
+
* asked (GT-1 step 2).
|
|
255
|
+
*
|
|
256
|
+
* Interceptors run first because a value read from a system of record beats a value
|
|
257
|
+
* a model guessed, and running them first means the model is never asked for
|
|
258
|
+
* something the host already knows.
|
|
259
|
+
*/
|
|
260
|
+
export interface FieldInterceptor {
|
|
261
|
+
/** A name for the record and for telemetry. */
|
|
262
|
+
readonly name: string;
|
|
263
|
+
/**
|
|
264
|
+
* Resolve whichever of `op.fields` this interceptor can. Returning `{}` is normal
|
|
265
|
+
* — an interceptor that has nothing to say says nothing.
|
|
266
|
+
*/
|
|
267
|
+
resolve(op: Operation, ctx: TurnContext): Promise<InterceptedFields> | InterceptedFields;
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"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"}
|
package/dist/ports.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ports a host supplies. Types only — this module has no runtime behaviour
|
|
3
|
+
* beyond {@link defaultClock}.
|
|
4
|
+
*
|
|
5
|
+
* **Rules served: GT-1** (the pipeline runs in protocol order, and every step it
|
|
6
|
+
* cannot do itself is a port), **GT-5** (a Standing Order that declares a risk
|
|
7
|
+
* threshold is compared against a host-supplied scorer), **AZ-2** (decision
|
|
8
|
+
* authorization is the host's answer, and the gate fails closed on it), **CV-1**
|
|
9
|
+
* (a port the gate needs and does not have is a wire-up failure, not a runtime
|
|
10
|
+
* surprise), **GT-2** (every port method that needs to know who is asking is
|
|
11
|
+
* handed the {@link TurnContext}; none of them may go looking).
|
|
12
|
+
*
|
|
13
|
+
* The shape of this file is the framework's central claim: **the core ships no
|
|
14
|
+
* model client, no scoring formula, no executor and no store.** It decides *what
|
|
15
|
+
* must be sworn to and who must agree*, and it asks the host for everything else.
|
|
16
|
+
* That is what lets one gate sit in front of any model, any database and any
|
|
17
|
+
* approval surface — and it is why a host cannot accidentally end up with a gate
|
|
18
|
+
* that scores its own risk or executes its own writes.
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The clock used when a host supplies none: the Web-standard `Date`, formatted as
|
|
24
|
+
* an ISO 8601 instant in UTC.
|
|
25
|
+
*
|
|
26
|
+
* `Date` and `toISOString` are ECMAScript, present on Node, Bun and workerd alike
|
|
27
|
+
* (RT-1). No Node API, no timer, no interval — one reading, on demand.
|
|
28
|
+
*/
|
|
29
|
+
export const defaultClock = {
|
|
30
|
+
now() {
|
|
31
|
+
return new Date().toISOString();
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=ports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgNH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,GAAG;QACD,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@affiant/core/store-memory` — the reference Docket and Session stores, in
|
|
3
|
+
* memory.
|
|
4
|
+
*
|
|
5
|
+
* They are a separate entry point because a host in production imports the gate and
|
|
6
|
+
* a *durable* store, and should never be one careless import away from an approval
|
|
7
|
+
* record that lives only in an isolate that is about to be recycled. Keeping them
|
|
8
|
+
* out of the main entry point makes the choice visible in the import line.
|
|
9
|
+
*
|
|
10
|
+
* The in-memory store is nonetheless the **reference** implementation, not a toy: it
|
|
11
|
+
* is what the store-semantics fixtures are written against, and a production store
|
|
12
|
+
* earns the name by passing the same ones. What it enforces — idempotent filing, the
|
|
13
|
+
* guarded compare-and-set, the deadline applied on every read, opaque paging on every
|
|
14
|
+
* list, the bounded sweep, retention, purge, export, and a tenant partition a query
|
|
15
|
+
* cannot cross — is the DK area of the rulebook, in code.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
export { InMemoryDocketStore, InMemorySessionStore } from "./docket/memory.js";
|
|
20
|
+
export type { InMemoryDocketStoreOptions } from "./docket/memory.js";
|
|
21
|
+
//# sourceMappingURL=store-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-memory.d.ts","sourceRoot":"","sources":["../src/store-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@affiant/core/store-memory` — the reference Docket and Session stores, in
|
|
3
|
+
* memory.
|
|
4
|
+
*
|
|
5
|
+
* They are a separate entry point because a host in production imports the gate and
|
|
6
|
+
* a *durable* store, and should never be one careless import away from an approval
|
|
7
|
+
* record that lives only in an isolate that is about to be recycled. Keeping them
|
|
8
|
+
* out of the main entry point makes the choice visible in the import line.
|
|
9
|
+
*
|
|
10
|
+
* The in-memory store is nonetheless the **reference** implementation, not a toy: it
|
|
11
|
+
* is what the store-semantics fixtures are written against, and a production store
|
|
12
|
+
* earns the name by passing the same ones. What it enforces — idempotent filing, the
|
|
13
|
+
* guarded compare-and-set, the deadline applied on every read, opaque paging on every
|
|
14
|
+
* list, the bounded sweep, retention, purge, export, and a tenant partition a query
|
|
15
|
+
* cannot cross — is the DK area of the rulebook, in code.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
export { InMemoryDocketStore, InMemorySessionStore } from "./docket/memory.js";
|
|
20
|
+
//# sourceMappingURL=store-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-memory.js","sourceRoot":"","sources":["../src/store-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
|