@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,515 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate pipeline: everything between a tool call and a Docket row, in the order
|
|
3
|
+
* the protocol fixes.
|
|
4
|
+
*
|
|
5
|
+
* **Rules served: GT-1** (the order itself), **GT-3** (runtime substance refusal),
|
|
6
|
+
* **GT-4** (TTL stamped from the policy result, after the chain; a re-file keeps the
|
|
7
|
+
* existing deadline), **PV-1** (confidence clamped, merge by confidence then
|
|
8
|
+
* determinism), **PV-3** (the inference step cannot mint `UserStated`), **AF-1**
|
|
9
|
+
* (every proposed field present, unknown provenance recorded as `Empty`), **AF-3**
|
|
10
|
+
* (create carries no previous values; update carries the key on every field),
|
|
11
|
+
* **AZ-1** (a Standing Order writes its attestation in the same operation as the
|
|
12
|
+
* filing), **AZ-4** (a requirement this version does not run is filed blocked),
|
|
13
|
+
* **CV-4** (a declared-uncovered tool's proposal is filed blocked), **SR-4** (the
|
|
14
|
+
* card names the protocol version it conforms to), **TL-1** (the events).
|
|
15
|
+
*
|
|
16
|
+
* ## The order, and why it is this order (GT-1)
|
|
17
|
+
*
|
|
18
|
+
* 1. **Turn context** arrives as a parameter. Nothing here reads a global, and the
|
|
19
|
+
* accumulators below are function-local, so two conversations interleaved in one
|
|
20
|
+
* isolate cannot see each other's fields (GT-2).
|
|
21
|
+
* 2. **Deterministic interceptors** first, because a value a host can look up is
|
|
22
|
+
* better evidence than a value a model can guess, and running them first means the
|
|
23
|
+
* merge in step 4 is comparing against something rather than filling a blank.
|
|
24
|
+
* 3. **One tool-free structured inference** against the *unmodified* turn. One,
|
|
25
|
+
* because a second pass over a turn a previous pass has already been told about is
|
|
26
|
+
* a model agreeing with itself. Tool-free, because a model that can call tools
|
|
27
|
+
* while being asked what a person said can go and find out.
|
|
28
|
+
* 4. **Merge** (PV-1): higher confidence wins, ties toward the more deterministic
|
|
29
|
+
* source, the loser kept in the chain so a card can show a reviewer that the model
|
|
30
|
+
* and the system of record disagreed.
|
|
31
|
+
* 5. **Projection**, then the Affidavit is built (AF-1, AF-3, AF-2).
|
|
32
|
+
* 6. **Substance refusal** (GT-3) — *before* the policy chain. A proposal that swears
|
|
33
|
+
* to nothing must not reach a policy that might approve it, and must not be filed,
|
|
34
|
+
* counted or broadcast.
|
|
35
|
+
* 7. **Policy** (AZ-4, PV-4, GT-5).
|
|
36
|
+
* 8. **TTL** (GT-4) — *after* the policy, because the deadline is part of what the
|
|
37
|
+
* policy decided, and a global default stamped before the chain is the
|
|
38
|
+
* non-conformant shape the rule names.
|
|
39
|
+
* 9. **File** (DK-1), idempotent by entry id.
|
|
40
|
+
*
|
|
41
|
+
* ## Entry ids are derived, not minted
|
|
42
|
+
*
|
|
43
|
+
* The id is a SHA-256 over the tenant, the conversation, the tool name and the
|
|
44
|
+
* canonical form of the operation and its arguments, laid out as a UUID. So a retry
|
|
45
|
+
* of the same call in the same conversation is the *same* entry: `store.file` returns
|
|
46
|
+
* the row that is already there, with its **existing** `expiresAt` (GT-4), and the
|
|
47
|
+
* card the model gets back is the card a reviewer is already looking at. A random id
|
|
48
|
+
* would file a second row for a retried call and start a second clock, which is the
|
|
49
|
+
* shape GT-4 names as wrong.
|
|
50
|
+
*
|
|
51
|
+
* A resubmission adds the id of the entry it supersedes to that material, so it is a
|
|
52
|
+
* different entry from the one it replaces (DK-1) and resubmitting the same expired
|
|
53
|
+
* entry twice is still one row.
|
|
54
|
+
*
|
|
55
|
+
* @packageDocumentation
|
|
56
|
+
*/
|
|
57
|
+
import { newEntry } from "../docket/entry.js";
|
|
58
|
+
import { instantMs } from "../docket/expiry.js";
|
|
59
|
+
import { AffiantError } from "../errors.js";
|
|
60
|
+
import { buildAffidavit, isJsonValue, presentationToWire, toWire } from "../model/affidavit.js";
|
|
61
|
+
import { canonicalJson, sha256Hex } from "../model/canonical.js";
|
|
62
|
+
import { chainOf, merge, mintConversation, mintInferred, mintTag } from "../model/provenance.js";
|
|
63
|
+
import { coverageRefusedMarker } from "./coverage.js";
|
|
64
|
+
import { evaluatePolicies } from "./policy.js";
|
|
65
|
+
/**
|
|
66
|
+
* Run steps 2 through 9 for `proposal` in `ctx` and return the filed entry with its
|
|
67
|
+
* card.
|
|
68
|
+
*
|
|
69
|
+
* @throws AffiantError `"substance-refused"` when the proposal swears to nothing
|
|
70
|
+
* (GT-3). Nothing is filed, nothing is broadcast, and the refusal is on the
|
|
71
|
+
* telemetry port before the throw.
|
|
72
|
+
* @throws RangeError when a port hands back something that is not a JSON value, or
|
|
73
|
+
* an interceptor claims a field the operation does not propose. Neither is a
|
|
74
|
+
* refusal the gate hands back to a model: they are host programming errors,
|
|
75
|
+
* and an `AffiantError` code would invite a host to catch and continue.
|
|
76
|
+
*/
|
|
77
|
+
export async function runPipeline(proposal, ctx, deps) {
|
|
78
|
+
const now = deps.clock.now();
|
|
79
|
+
const op = proposal.operation;
|
|
80
|
+
const proposed = new Set(op.fields);
|
|
81
|
+
const schemaByName = new Map((proposal.schema?.fields ?? []).map((entry) => [entry.name, entry]));
|
|
82
|
+
// Function-local, so nothing survives the call and nothing is shared between two
|
|
83
|
+
// interleaved conversations (GT-2).
|
|
84
|
+
const states = new Map();
|
|
85
|
+
/** Admit a tag and its value, merging by PV-1 and keeping the loser in the chain. */
|
|
86
|
+
const admit = (name, tag, value) => {
|
|
87
|
+
const state = states.get(name);
|
|
88
|
+
if (state === undefined) {
|
|
89
|
+
states.set(name, { chain: chainOf(tag), value });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const chain = merge(state.chain, tag);
|
|
93
|
+
// `merge` returns the winner as `current`; identity tells us whose value is now
|
|
94
|
+
// in force without re-deciding the contest here.
|
|
95
|
+
states.set(name, { chain, value: chain.current === tag ? value : state.value });
|
|
96
|
+
};
|
|
97
|
+
if (proposal.preparedFields === null) {
|
|
98
|
+
// ---- step 2: deterministic interceptors (PV-2) -------------------------
|
|
99
|
+
for (const interceptor of deps.interceptors) {
|
|
100
|
+
const produced = await interceptor.resolve(op, ctx);
|
|
101
|
+
for (const [name, intercepted] of Object.entries(produced)) {
|
|
102
|
+
if (!proposed.has(name)) {
|
|
103
|
+
throw new RangeError(`AF-1: interceptor ${JSON.stringify(interceptor.name)} resolved field ` +
|
|
104
|
+
`${JSON.stringify(name)}, which operation ${op.kind} on ${op.entityType} does not ` +
|
|
105
|
+
`propose; a field the operation does not propose is absent from the Affidavit`);
|
|
106
|
+
}
|
|
107
|
+
// `InterceptedField.source` is `"External" | "Computed"`, so PV-3's other
|
|
108
|
+
// half — a host resolver cannot claim the person said it — is a type, not a
|
|
109
|
+
// check. A binding is required by the same type (PV-2).
|
|
110
|
+
admit(name, mintTag({
|
|
111
|
+
source: intercepted.source,
|
|
112
|
+
confidence: intercepted.confidence,
|
|
113
|
+
at: now,
|
|
114
|
+
note: intercepted.evidence,
|
|
115
|
+
binding: intercepted.binding,
|
|
116
|
+
}), requireJsonValue(intercepted.value, `interceptor ${interceptor.name} field ${name}`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ---- step 3: one tool-free structured inference; step 4: merge ---------
|
|
120
|
+
if (proposal.schema !== null) {
|
|
121
|
+
const inferred = await deps.inference.infer(ctx.turn, proposal.schema);
|
|
122
|
+
for (const [name, structured] of Object.entries(inferred.fields)) {
|
|
123
|
+
// A model naming a field the operation does not propose is the model being
|
|
124
|
+
// a model, not the host being wrong: the extra field is dropped, and AF-1
|
|
125
|
+
// still holds because the Affidavit is built from `op.fields`.
|
|
126
|
+
if (!proposed.has(name))
|
|
127
|
+
continue;
|
|
128
|
+
const value = requireJsonValue(structured.value, `inferred field ${name}`);
|
|
129
|
+
// PV-3: `mintConversation` and `mintInferred` are the only two mints reachable
|
|
130
|
+
// from here, and neither can name `UserStated` — the parameter type forbids it
|
|
131
|
+
// and the runtime guard in `mintInference` catches an untyped caller.
|
|
132
|
+
const tag = structured.presence === "literal"
|
|
133
|
+
? mintConversation({
|
|
134
|
+
confidence: structured.confidence,
|
|
135
|
+
at: now,
|
|
136
|
+
note: `Literally present in the turn: ${name}`,
|
|
137
|
+
binding: await utteranceSpanBinding(ctx.turn.utterance, structured.utteranceSpan),
|
|
138
|
+
})
|
|
139
|
+
: mintInferred({
|
|
140
|
+
confidence: structured.confidence,
|
|
141
|
+
at: now,
|
|
142
|
+
note: `Inferred from the turn: ${name}`,
|
|
143
|
+
});
|
|
144
|
+
admit(name, tag, value);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
for (const prepared of proposal.preparedFields) {
|
|
150
|
+
if (!proposed.has(prepared.name)) {
|
|
151
|
+
throw new RangeError(`AF-1: prepared field ${JSON.stringify(prepared.name)} is not proposed by the ` +
|
|
152
|
+
`operation; a field the operation does not propose is absent from the Affidavit`);
|
|
153
|
+
}
|
|
154
|
+
if (prepared.provenance !== undefined) {
|
|
155
|
+
states.set(prepared.name, { chain: prepared.provenance, value: prepared.value });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// ---- step 5: projection, then the Affidavit (AF-1, AF-3, AF-2) -----------
|
|
160
|
+
// The port is consulted for an update only: AF-3 says a create carries
|
|
161
|
+
// `previousValue: null` on every field, and there is nothing for a host to look up
|
|
162
|
+
// for an entity that does not exist yet.
|
|
163
|
+
const previous = op.kind === "update" ? ((await deps.projection.previousValues(op, ctx)) ?? {}) : {};
|
|
164
|
+
const preparedByName = new Map((proposal.preparedFields ?? []).map((prepared) => [prepared.name, prepared]));
|
|
165
|
+
const inputs = op.fields.map((name) => {
|
|
166
|
+
const state = states.get(name);
|
|
167
|
+
const prepared = preparedByName.get(name);
|
|
168
|
+
const schemaEntry = schemaByName.get(name);
|
|
169
|
+
const previousValue = op.kind === "update"
|
|
170
|
+
? requireJsonValue(previous[name] ?? null, `previous value of ${name}`)
|
|
171
|
+
: null;
|
|
172
|
+
return {
|
|
173
|
+
name,
|
|
174
|
+
kind: prepared?.kind ?? schemaEntry?.kind ?? "text",
|
|
175
|
+
value: state?.value ?? prepared?.value ?? null,
|
|
176
|
+
previousValue,
|
|
177
|
+
isMandatory: prepared?.isMandatory ?? schemaEntry?.required ?? false,
|
|
178
|
+
// Absent, not `undefined`: `buildAffidavit` reads the absence as "provenance
|
|
179
|
+
// unknown" and writes an `Empty` tag (AF-1).
|
|
180
|
+
...(state === undefined ? {} : { provenance: state.chain }),
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
const affidavit = buildAffidavit(op, inputs, { createdAt: now });
|
|
184
|
+
// ---- step 6: runtime substance refusal (GT-3) ----------------------------
|
|
185
|
+
refuseHollow(affidavit, proposal, ctx, deps, now);
|
|
186
|
+
// ---- step 7: the policy chain (AZ-4, PV-4, GT-5) -------------------------
|
|
187
|
+
const outcome = await evaluatePolicies(deps.policies, affidavit, ctx, {
|
|
188
|
+
riskScorer: deps.riskScorer,
|
|
189
|
+
telemetry: deps.telemetry,
|
|
190
|
+
now,
|
|
191
|
+
});
|
|
192
|
+
// ---- step 8: TTL, from the policy result (GT-4) --------------------------
|
|
193
|
+
const ttlMs = outcome.ttlMs ?? deps.defaultTtlMs;
|
|
194
|
+
const expiresAt = new Date(instantMs(now, "clock.now()") + ttlMs).toISOString();
|
|
195
|
+
// ---- step 9: file (DK-1, AZ-1, AZ-4, CV-4) ------------------------------
|
|
196
|
+
const uncovered = deps.coverage.lookup(proposal.toolName);
|
|
197
|
+
const blocked = blockedMarker(proposal.toolName, uncovered, outcome.requirement);
|
|
198
|
+
// A blocked entry is never auto-approved: AZ-4 says a level the implementation does
|
|
199
|
+
// not run is filed `pending` and refuses every decision, and CV-4 says the same of a
|
|
200
|
+
// tool the host cannot cover. Both are a move *toward* a person, which is the
|
|
201
|
+
// direction AZ-4 permits.
|
|
202
|
+
const fires = outcome.requirement === "StandingOrder" && blocked === null;
|
|
203
|
+
const entryId = await deriveEntryId(ctx, proposal);
|
|
204
|
+
if (uncovered !== null) {
|
|
205
|
+
deps.telemetry.emit({
|
|
206
|
+
key: "coverage.refused",
|
|
207
|
+
at: now,
|
|
208
|
+
attributes: {
|
|
209
|
+
"gen_ai.tool.name": proposal.toolName,
|
|
210
|
+
"coverage.category": uncovered,
|
|
211
|
+
phase: "proposal",
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const attestation = fires && outcome.policy !== null
|
|
216
|
+
? {
|
|
217
|
+
by: {
|
|
218
|
+
kind: "standing-order",
|
|
219
|
+
policyId: outcome.policy.id,
|
|
220
|
+
version: outcome.policy.version,
|
|
221
|
+
},
|
|
222
|
+
at: now,
|
|
223
|
+
entryId,
|
|
224
|
+
}
|
|
225
|
+
: null;
|
|
226
|
+
const init = {
|
|
227
|
+
entryId,
|
|
228
|
+
tenantId: ctx.tenantId,
|
|
229
|
+
conversationId: ctx.conversationId,
|
|
230
|
+
channel: ctx.channel,
|
|
231
|
+
// On the row so a resubmission can re-run the coverage lookup against the tool
|
|
232
|
+
// that actually proposed the write (CV-4), and so an audit can name it.
|
|
233
|
+
toolName: proposal.toolName,
|
|
234
|
+
affidavit,
|
|
235
|
+
requirement: outcome.requirement,
|
|
236
|
+
filedAt: now,
|
|
237
|
+
expiresAt,
|
|
238
|
+
// DK-1: a resubmission names what it replaces on the way in. The successor link
|
|
239
|
+
// is written on the *other* row, by `resubmit`, after this filing succeeds.
|
|
240
|
+
...(proposal.supersedes === null ? {} : { supersedes: proposal.supersedes }),
|
|
241
|
+
// A Standing Order writes status, execution outcome and attestation in the same
|
|
242
|
+
// operation as the filing (AZ-1) — never a file followed by an approve, which
|
|
243
|
+
// would leave a window in which an approved write had no attestation.
|
|
244
|
+
...(attestation === null
|
|
245
|
+
? {}
|
|
246
|
+
: { status: "approved", execution: "unexecuted", attestation }),
|
|
247
|
+
...(blocked === null ? {} : { blocked }),
|
|
248
|
+
};
|
|
249
|
+
const { entry, created } = await deps.store.file(newEntry(init));
|
|
250
|
+
if (fires && outcome.policy !== null) {
|
|
251
|
+
deps.telemetry.emit({
|
|
252
|
+
key: "standing-order.fired",
|
|
253
|
+
at: now,
|
|
254
|
+
attributes: {
|
|
255
|
+
"policy.id": outcome.policy.id,
|
|
256
|
+
"policy.version": outcome.policy.version,
|
|
257
|
+
"entry.id": entry.entryId,
|
|
258
|
+
"risk.score": outcome.riskScore,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
deps.telemetry.emit({
|
|
263
|
+
key: "affidavit.filed",
|
|
264
|
+
at: now,
|
|
265
|
+
attributes: {
|
|
266
|
+
"gen_ai.tool.name": proposal.toolName,
|
|
267
|
+
"gen_ai.conversation.id": ctx.conversationId,
|
|
268
|
+
"entry.id": entry.entryId,
|
|
269
|
+
"docket.requirement": entry.requirement,
|
|
270
|
+
"docket.status": entry.status,
|
|
271
|
+
"affidavit.field_count": entry.affidavit.fields.length,
|
|
272
|
+
created,
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
return { entry, created, card: evidenceCard(entry, proposal, outcome) };
|
|
276
|
+
}
|
|
277
|
+
// ---------------------------------------------------------------------------
|
|
278
|
+
// Step 6 — substance (GT-3)
|
|
279
|
+
// ---------------------------------------------------------------------------
|
|
280
|
+
/**
|
|
281
|
+
* Refuse a proposal that swears to nothing: no field carrying provenance other than
|
|
282
|
+
* `Empty`, or a non-empty value sitting under an `Empty` tag (GT-3).
|
|
283
|
+
*
|
|
284
|
+
* The hollow case is checked first because it is the more specific diagnosis — an
|
|
285
|
+
* all-`Empty` Affidavit with values in it satisfies both descriptions, and "you filled
|
|
286
|
+
* in a value and told me nothing about where it came from" is the more useful thing to
|
|
287
|
+
* say.
|
|
288
|
+
*
|
|
289
|
+
* A value counts as empty when it is `null` or a string that is blank. `0` and `false`
|
|
290
|
+
* are values somebody meant, and a field carrying one under an `Empty` tag is exactly
|
|
291
|
+
* the hollow shape the rule is about.
|
|
292
|
+
*/
|
|
293
|
+
function refuseHollow(affidavit, proposal, ctx, deps, now) {
|
|
294
|
+
const hollow = affidavit.fields.find((field) => field.provenance.current.source === "Empty" && !isEmptyValue(field.value));
|
|
295
|
+
const reason = hollow !== undefined
|
|
296
|
+
? `field ${JSON.stringify(hollow.name)} carries a value with Empty provenance`
|
|
297
|
+
: affidavit.fields.every((field) => field.provenance.current.source === "Empty")
|
|
298
|
+
? "no proposed field carries provenance other than Empty"
|
|
299
|
+
: null;
|
|
300
|
+
if (reason === null)
|
|
301
|
+
return;
|
|
302
|
+
deps.telemetry.emit({
|
|
303
|
+
key: "affidavit.refused.substance",
|
|
304
|
+
at: now,
|
|
305
|
+
attributes: {
|
|
306
|
+
"gen_ai.tool.name": proposal.toolName,
|
|
307
|
+
"gen_ai.conversation.id": ctx.conversationId,
|
|
308
|
+
"affidavit.field_count": affidavit.fields.length,
|
|
309
|
+
reason,
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
throw new AffiantError("substance-refused", `GT-3: this proposal swears to nothing — ${reason}. It is not filed, not counted and ` +
|
|
313
|
+
`not broadcast.`, { toolName: proposal.toolName, reason, entityType: affidavit.entityType });
|
|
314
|
+
}
|
|
315
|
+
/** Whether `value` is the absence of a value: `null`, or a string with nothing in it. */
|
|
316
|
+
function isEmptyValue(value) {
|
|
317
|
+
if (value === null)
|
|
318
|
+
return true;
|
|
319
|
+
return typeof value === "string" && value.trim() === "";
|
|
320
|
+
}
|
|
321
|
+
// ---------------------------------------------------------------------------
|
|
322
|
+
// Step 9 — the row and the card
|
|
323
|
+
// ---------------------------------------------------------------------------
|
|
324
|
+
/**
|
|
325
|
+
* The AZ-4 marker the entry is filed with, or `null` when it can be decided.
|
|
326
|
+
*
|
|
327
|
+
* Coverage comes first: a tool the host cannot intercept is the more fundamental
|
|
328
|
+
* problem, and its category is the more useful thing on the row.
|
|
329
|
+
*/
|
|
330
|
+
function blockedMarker(toolName, uncovered, requirement) {
|
|
331
|
+
if (uncovered !== null)
|
|
332
|
+
return coverageRefusedMarker(toolName, uncovered);
|
|
333
|
+
if (requirement === "MultiParty" || requirement === "ReferralRequired") {
|
|
334
|
+
// Recorded verbatim (AZ-4): the row says what was asked for, and no code path
|
|
335
|
+
// turns it into the weaker requirement this version does know how to run.
|
|
336
|
+
return { code: "requirement-not-implemented", level: requirement };
|
|
337
|
+
}
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
/** The card a host delivers, built from the **stored** entry (GT-4) and the wire carry. */
|
|
341
|
+
function evidenceCard(entry, proposal, outcome) {
|
|
342
|
+
// AF-2's three numbers come off the stored Affidavit, so the card and the record
|
|
343
|
+
// can never disagree about them: all three ride the wire Affidavit, and two of
|
|
344
|
+
// them are repeated on the envelope for the one version the superseded wire's
|
|
345
|
+
// consumers are still reading.
|
|
346
|
+
const sworn = entry.amendedAffidavit ?? entry.affidavit;
|
|
347
|
+
const carry = wireCarry(entry, proposal, outcome);
|
|
348
|
+
return {
|
|
349
|
+
protocolVersion: entry.protocolVersion,
|
|
350
|
+
docketId: entry.entryId,
|
|
351
|
+
// The record's own version, not the row's envelope tag (SR-4). SR-1's canonical
|
|
352
|
+
// form is over the Affidavit as the schema defines it, `protocolVersion`
|
|
353
|
+
// included, so re-stamping the record on the way onto the card would produce a
|
|
354
|
+
// document whose hash is not the row's `canonicalHash` — the substitution the
|
|
355
|
+
// form exists to make impossible. The two are the same value on every path a
|
|
356
|
+
// host takes; they differ only where a caller pinned the row to another tag,
|
|
357
|
+
// and then it is the envelope that carries the pin, not the sworn record.
|
|
358
|
+
affidavit: toWire(sworn),
|
|
359
|
+
requiredBy: entry.expiresAt,
|
|
360
|
+
priorAmendments: proposal.priorAmendments ?? entry.preservedAmendments?.amendments ?? null,
|
|
361
|
+
populatedConfidence: sworn.populatedConfidence,
|
|
362
|
+
emptyFieldCount: sworn.emptyFieldCount,
|
|
363
|
+
blocked: entry.blocked,
|
|
364
|
+
...presentationToWire(carry),
|
|
365
|
+
requiresConfirmation: carry.requiresConfirmation,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* The presentation the core does not own: the sentences a reviewer should see,
|
|
370
|
+
* whether a person must confirm, the reviewer surface's per-field rendering hints,
|
|
371
|
+
* and the host's own verb for the operation.
|
|
372
|
+
*/
|
|
373
|
+
function wireCarry(entry, proposal, outcome) {
|
|
374
|
+
const warnings = [];
|
|
375
|
+
if (outcome.reason !== null)
|
|
376
|
+
warnings.push(outcome.reason);
|
|
377
|
+
if (entry.blocked?.code === "coverage-refused") {
|
|
378
|
+
warnings.push(`CV-4: ${JSON.stringify(proposal.toolName)} is declared uncovered ` +
|
|
379
|
+
`(${String(entry.blocked.category)}); this proposal is on the record and cannot be ` +
|
|
380
|
+
`approved through the gate.`);
|
|
381
|
+
}
|
|
382
|
+
if (entry.blocked?.code === "requirement-not-implemented") {
|
|
383
|
+
warnings.push(`AZ-4: ${String(entry.blocked.level)} approval is not implemented in this version; the ` +
|
|
384
|
+
`entry is blocked and no decision on it will be accepted.`);
|
|
385
|
+
}
|
|
386
|
+
// One entry per field the host declared something about, naming a field the
|
|
387
|
+
// Affidavit carries — a hint for a field the record does not carry would render
|
|
388
|
+
// a control over nothing. A field the host said nothing about gets no entry at
|
|
389
|
+
// all, rather than an entry full of nulls: absence is how the wire spells "no
|
|
390
|
+
// hint, render from the field's own kind".
|
|
391
|
+
const presentation = [];
|
|
392
|
+
const schemaByName = new Map((proposal.schema?.fields ?? []).map((entry_) => [entry_.name, entry_]));
|
|
393
|
+
for (const field of (entry.amendedAffidavit ?? entry.affidavit).fields) {
|
|
394
|
+
const declared = schemaByName.get(field.name);
|
|
395
|
+
const allowedValues = declared?.allowedValues ?? null;
|
|
396
|
+
// Carried from the host's field schema, never invented here: the reviewer
|
|
397
|
+
// surface renders it as an input constraint and the gate validates nothing
|
|
398
|
+
// against it.
|
|
399
|
+
const pattern = declared?.pattern ?? null;
|
|
400
|
+
if (allowedValues === null && pattern === null)
|
|
401
|
+
continue;
|
|
402
|
+
presentation.push({
|
|
403
|
+
name: field.name,
|
|
404
|
+
kind: field.kind,
|
|
405
|
+
...(allowedValues === null ? {} : { allowedValues }),
|
|
406
|
+
...(pattern === null ? {} : { pattern }),
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
warnings,
|
|
411
|
+
// A blocked entry sits in `pending` and refuses every decision (AZ-4, CV-4), so
|
|
412
|
+
// it is not a card a person can confirm. Saying `true` here would offer a
|
|
413
|
+
// reviewer surface an approve button that cannot work, on the same card that
|
|
414
|
+
// carries a warning saying no decision will be accepted.
|
|
415
|
+
requiresConfirmation: entry.status === "pending" && entry.blocked === null,
|
|
416
|
+
presentation,
|
|
417
|
+
// The host's word for what it is doing, carried onto the card so a reviewer
|
|
418
|
+
// surface can head the card with the verb a person recognises rather than with
|
|
419
|
+
// the protocol's two-valued shape. It comes from this filing, like the hints
|
|
420
|
+
// beside it — a resubmission builds its proposal from the row, which swears to
|
|
421
|
+
// the evidence and not to how the host labels it, so a resubmitted card carries
|
|
422
|
+
// neither until the host supplies them again.
|
|
423
|
+
hostOperation: proposal.operationLabel,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
// ---------------------------------------------------------------------------
|
|
427
|
+
// Entry ids
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
/**
|
|
430
|
+
* The entry id for this proposal: a SHA-256 over the tenant, the conversation, the
|
|
431
|
+
* tool and the canonical form of the operation and its arguments, laid out as a UUID.
|
|
432
|
+
*
|
|
433
|
+
* The layout sets the version nibble to `8` and the variant bits to `10`, which RFC
|
|
434
|
+
* 9562 reserves for exactly this — a UUID whose bits are a hash an application chose.
|
|
435
|
+
* The shape matters because `docketId` is a UUID string on the wire; the determinism
|
|
436
|
+
* matters because it is what makes a retried tool call a replay rather than a second
|
|
437
|
+
* review (GT-4, DK-1).
|
|
438
|
+
*
|
|
439
|
+
* @throws TypeError if `args` contains something with no canonical form — a function,
|
|
440
|
+
* a symbol, a cycle. Tool arguments are JSON; anything else is a caller bug.
|
|
441
|
+
*/
|
|
442
|
+
export async function deriveEntryId(ctx, proposal) {
|
|
443
|
+
const material = canonicalJson({
|
|
444
|
+
tenantId: ctx.tenantId,
|
|
445
|
+
conversationId: ctx.conversationId,
|
|
446
|
+
toolName: proposal.toolName,
|
|
447
|
+
operation: proposal.operation,
|
|
448
|
+
args: proposal.args ?? null,
|
|
449
|
+
// Only when there is one, so a first filing's id is exactly what it was before
|
|
450
|
+
// resubmission existed, and a retry of the original call is still a replay.
|
|
451
|
+
...(proposal.supersedes === null ? {} : { supersedes: proposal.supersedes }),
|
|
452
|
+
});
|
|
453
|
+
const digest = await sha256Hex(new TextEncoder().encode(material));
|
|
454
|
+
return uuidFromDigest(digest);
|
|
455
|
+
}
|
|
456
|
+
/** Lay 128 bits of `digest` out as a UUID with version 8 and the RFC 9562 variant. */
|
|
457
|
+
function uuidFromDigest(digest) {
|
|
458
|
+
const nibbles = [...digest.slice(0, 32)];
|
|
459
|
+
nibbles[12] = "8";
|
|
460
|
+
nibbles[16] = "89ab"[Number.parseInt(nibbles[16] ?? "0", 16) % 4] ?? "8";
|
|
461
|
+
const hex = nibbles.join("");
|
|
462
|
+
return [
|
|
463
|
+
hex.slice(0, 8),
|
|
464
|
+
hex.slice(8, 12),
|
|
465
|
+
hex.slice(12, 16),
|
|
466
|
+
hex.slice(16, 20),
|
|
467
|
+
hex.slice(20, 32),
|
|
468
|
+
].join("-");
|
|
469
|
+
}
|
|
470
|
+
// ---------------------------------------------------------------------------
|
|
471
|
+
// Bindings and values
|
|
472
|
+
// ---------------------------------------------------------------------------
|
|
473
|
+
/**
|
|
474
|
+
* The `utterance-span` binding for a value the port reported as literally present
|
|
475
|
+
* (PV-2), or `null` when there is no span or the span does not fit the turn.
|
|
476
|
+
*
|
|
477
|
+
* The hash is a SHA-256 of the span's own text, so an auditor holding the turn can
|
|
478
|
+
* re-derive it and see that the pointer still points where it did. A span that runs
|
|
479
|
+
* past the end of the utterance, or reads backwards, is not evidence: the binding is
|
|
480
|
+
* dropped and the tag stays `Conversation` with nothing behind it, which PV-4 then
|
|
481
|
+
* treats as unbound — the honest outcome.
|
|
482
|
+
*/
|
|
483
|
+
async function utteranceSpanBinding(utterance, span) {
|
|
484
|
+
if (span === null)
|
|
485
|
+
return null;
|
|
486
|
+
if (!Number.isInteger(span.start) || !Number.isInteger(span.end))
|
|
487
|
+
return null;
|
|
488
|
+
if (span.start < 0 || span.end < span.start || span.end > utterance.length)
|
|
489
|
+
return null;
|
|
490
|
+
const text = utterance.slice(span.start, span.end);
|
|
491
|
+
return {
|
|
492
|
+
kind: "utterance-span",
|
|
493
|
+
ref: {
|
|
494
|
+
offset: span.start,
|
|
495
|
+
length: span.end - span.start,
|
|
496
|
+
hash: await sha256Hex(new TextEncoder().encode(text)),
|
|
497
|
+
},
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* `value` as a JSON value.
|
|
502
|
+
*
|
|
503
|
+
* @throws RangeError when a port hands back something with no JSON form. A port
|
|
504
|
+
* contract violation is a host programming error rather than a refusal, and
|
|
505
|
+
* letting it through would put an unserializable value on a record whose
|
|
506
|
+
* whole purpose is to be read back later.
|
|
507
|
+
*/
|
|
508
|
+
function requireJsonValue(value, where) {
|
|
509
|
+
if (!isJsonValue(value)) {
|
|
510
|
+
throw new RangeError(`${where} is not a JSON value (${typeof value}); every value on an Affidavit must ` +
|
|
511
|
+
`survive serialization`);
|
|
512
|
+
}
|
|
513
|
+
return value;
|
|
514
|
+
}
|
|
515
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/gate/pipeline.ts"],"names":[],"mappings":"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"}
|