@sentropic/llm-mesh 0.27.1 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -0
- package/dist/capabilities.d.ts +4 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/catalog.d.ts +135 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +16 -0
- package/dist/catalog.js.map +1 -1
- package/dist/decision/adapter-result.d.ts +6 -0
- package/dist/decision/adapter-result.d.ts.map +1 -0
- package/dist/decision/adapter-result.js +148 -0
- package/dist/decision/adapter-result.js.map +1 -0
- package/dist/decision/adapter.d.ts +58 -0
- package/dist/decision/adapter.d.ts.map +1 -0
- package/dist/decision/adapter.js +70 -0
- package/dist/decision/adapter.js.map +1 -0
- package/dist/decision/admission.d.ts +23 -0
- package/dist/decision/admission.d.ts.map +1 -0
- package/dist/decision/admission.js +115 -0
- package/dist/decision/admission.js.map +1 -0
- package/dist/decision/budget.d.ts +60 -0
- package/dist/decision/budget.d.ts.map +1 -0
- package/dist/decision/budget.js +2 -0
- package/dist/decision/budget.js.map +1 -0
- package/dist/decision/client.d.ts +23 -0
- package/dist/decision/client.d.ts.map +1 -0
- package/dist/decision/client.js +836 -0
- package/dist/decision/client.js.map +1 -0
- package/dist/decision/criterion.d.ts +5 -0
- package/dist/decision/criterion.d.ts.map +1 -0
- package/dist/decision/criterion.js +54 -0
- package/dist/decision/criterion.js.map +1 -0
- package/dist/decision/deadline.d.ts +8 -0
- package/dist/decision/deadline.d.ts.map +1 -0
- package/dist/decision/deadline.js +56 -0
- package/dist/decision/deadline.js.map +1 -0
- package/dist/decision/descriptor-validation.d.ts +5 -0
- package/dist/decision/descriptor-validation.d.ts.map +1 -0
- package/dist/decision/descriptor-validation.js +99 -0
- package/dist/decision/descriptor-validation.js.map +1 -0
- package/dist/decision/descriptor.d.ts +81 -0
- package/dist/decision/descriptor.d.ts.map +1 -0
- package/dist/decision/descriptor.js +36 -0
- package/dist/decision/descriptor.js.map +1 -0
- package/dist/decision/dispatch.d.ts +11 -0
- package/dist/decision/dispatch.d.ts.map +1 -0
- package/dist/decision/dispatch.js +56 -0
- package/dist/decision/dispatch.js.map +1 -0
- package/dist/decision/errors.d.ts +43 -0
- package/dist/decision/errors.d.ts.map +1 -0
- package/dist/decision/errors.js +47 -0
- package/dist/decision/errors.js.map +1 -0
- package/dist/decision/execution.d.ts +31 -0
- package/dist/decision/execution.d.ts.map +1 -0
- package/dist/decision/execution.js +79 -0
- package/dist/decision/execution.js.map +1 -0
- package/dist/decision/host-options.d.ts +26 -0
- package/dist/decision/host-options.d.ts.map +1 -0
- package/dist/decision/host-options.js +2 -0
- package/dist/decision/host-options.js.map +1 -0
- package/dist/decision/host.d.ts +14 -0
- package/dist/decision/host.d.ts.map +1 -0
- package/dist/decision/host.js +6 -0
- package/dist/decision/host.js.map +1 -0
- package/dist/decision/index.d.ts +12 -0
- package/dist/decision/index.d.ts.map +1 -0
- package/dist/decision/index.js +3 -0
- package/dist/decision/index.js.map +1 -0
- package/dist/decision/jev-codec.d.ts +30 -0
- package/dist/decision/jev-codec.d.ts.map +1 -0
- package/dist/decision/jev-codec.js +51 -0
- package/dist/decision/jev-codec.js.map +1 -0
- package/dist/decision/jev-response.d.ts +7 -0
- package/dist/decision/jev-response.d.ts.map +1 -0
- package/dist/decision/jev-response.js +42 -0
- package/dist/decision/jev-response.js.map +1 -0
- package/dist/decision/jev-verdict.d.ts +14 -0
- package/dist/decision/jev-verdict.d.ts.map +1 -0
- package/dist/decision/jev-verdict.js +71 -0
- package/dist/decision/jev-verdict.js.map +1 -0
- package/dist/decision/policy.d.ts +11 -0
- package/dist/decision/policy.d.ts.map +1 -0
- package/dist/decision/policy.js +33 -0
- package/dist/decision/policy.js.map +1 -0
- package/dist/decision/pricing.d.ts +40 -0
- package/dist/decision/pricing.d.ts.map +1 -0
- package/dist/decision/pricing.js +65 -0
- package/dist/decision/pricing.js.map +1 -0
- package/dist/decision/raw.d.ts +7 -0
- package/dist/decision/raw.d.ts.map +1 -0
- package/dist/decision/raw.js +53 -0
- package/dist/decision/raw.js.map +1 -0
- package/dist/decision/receipt.d.ts +120 -0
- package/dist/decision/receipt.d.ts.map +1 -0
- package/dist/decision/receipt.js +58 -0
- package/dist/decision/receipt.js.map +1 -0
- package/dist/decision/request-policy.d.ts +3 -0
- package/dist/decision/request-policy.d.ts.map +1 -0
- package/dist/decision/request-policy.js +19 -0
- package/dist/decision/request-policy.js.map +1 -0
- package/dist/decision/request.d.ts +85 -0
- package/dist/decision/request.d.ts.map +1 -0
- package/dist/decision/request.js +49 -0
- package/dist/decision/request.js.map +1 -0
- package/dist/decision/service.d.ts +39 -0
- package/dist/decision/service.d.ts.map +1 -0
- package/dist/decision/service.js +138 -0
- package/dist/decision/service.js.map +1 -0
- package/dist/decision/structured.d.ts +125 -0
- package/dist/decision/structured.d.ts.map +1 -0
- package/dist/decision/structured.js +250 -0
- package/dist/decision/structured.js.map +1 -0
- package/dist/decision/validate-result.d.ts +8 -0
- package/dist/decision/validate-result.d.ts.map +1 -0
- package/dist/decision/validate-result.js +91 -0
- package/dist/decision/validate-result.js.map +1 -0
- package/dist/decision/validation-context.d.ts +55 -0
- package/dist/decision/validation-context.d.ts.map +1 -0
- package/dist/decision/validation-context.js +134 -0
- package/dist/decision/validation-context.js.map +1 -0
- package/dist/decision/validation.d.ts +19 -0
- package/dist/decision/validation.d.ts.map +1 -0
- package/dist/decision/validation.js +86 -0
- package/dist/decision/validation.js.map +1 -0
- package/dist/decision/verdict.d.ts +81 -0
- package/dist/decision/verdict.d.ts.map +1 -0
- package/dist/decision/verdict.js +140 -0
- package/dist/decision/verdict.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +4 -3
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +2 -1
- package/dist/providers.js.map +1 -1
- package/dist/registry.d.ts +6 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js.map +1 -1
- package/dist/speech/capabilities.d.ts +48 -0
- package/dist/speech/capabilities.d.ts.map +1 -0
- package/dist/speech/capabilities.js +41 -0
- package/dist/speech/capabilities.js.map +1 -0
- package/dist/speech/catalog.d.ts +8 -0
- package/dist/speech/catalog.d.ts.map +1 -0
- package/dist/speech/catalog.js +5 -0
- package/dist/speech/catalog.js.map +1 -0
- package/dist/speech/contracts.d.ts +196 -0
- package/dist/speech/contracts.d.ts.map +1 -0
- package/dist/speech/contracts.js +39 -0
- package/dist/speech/contracts.js.map +1 -0
- package/dist/speech/index.d.ts +4 -0
- package/dist/speech/index.d.ts.map +1 -0
- package/dist/speech/index.js +4 -0
- package/dist/speech/index.js.map +1 -0
- package/dist/transport/jev.d.ts +23 -0
- package/dist/transport/jev.d.ts.map +1 -0
- package/dist/transport/jev.js +107 -0
- package/dist/transport/jev.js.map +1 -0
- package/package.json +17 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-result.d.ts","sourceRoot":"","sources":["../../src/decision/validate-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,cAAc,CAAC;AAIpE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAgEzE;;4EAE4E;AAC5E,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,eAAe,EACrE,eAAe,EAAE,yBAAyB,GAAG,IAAI,EAAE,SAAS,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAqB9F"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createDecisionError } from './errors.js';
|
|
2
|
+
import { has, hasOnlyKeys, isRecord } from './validation.js';
|
|
3
|
+
import { isValidDecisionReceipt, isValidDecisionVerdict } from './client.js';
|
|
4
|
+
import { isDecisionErrorCode } from './errors.js';
|
|
5
|
+
/** Rebuild a wire error from code/phase/liability evidence; never carries wording. */
|
|
6
|
+
function rebuildWireError(error, receipt) {
|
|
7
|
+
if (!isRecord(error) || !hasOnlyKeys(error, ['code', 'message', 'phase', 'retryable', 'retryAfterMs'])
|
|
8
|
+
|| !isDecisionErrorCode(error.code)
|
|
9
|
+
|| !['preflight', 'admission', 'dispatch', 'parse', 'settlement'].includes(error.phase))
|
|
10
|
+
return null;
|
|
11
|
+
const unresolved = receipt.budget.state !== 'not-admitted' && receipt.budget.state !== 'released';
|
|
12
|
+
const nonRetryable = unresolved || error.retryable === false;
|
|
13
|
+
const rebuilt = createDecisionError(error.code, error.phase, { retryAfterMs: !nonRetryable && has(error, 'retryAfterMs') && typeof error.retryAfterMs === 'number'
|
|
14
|
+
? error.retryAfterMs : undefined });
|
|
15
|
+
if (nonRetryable) {
|
|
16
|
+
rebuilt.retryable = false;
|
|
17
|
+
delete rebuilt.retryAfterMs;
|
|
18
|
+
}
|
|
19
|
+
return rebuilt;
|
|
20
|
+
}
|
|
21
|
+
const rebuildVerdict = (verdict) => {
|
|
22
|
+
const rebuilt = {
|
|
23
|
+
criterionKind: verdict.criterionKind,
|
|
24
|
+
resolvedCriterionKind: verdict.resolvedCriterionKind,
|
|
25
|
+
score: structuredClone(verdict.score),
|
|
26
|
+
decision: structuredClone(verdict.decision),
|
|
27
|
+
label: structuredClone(verdict.label),
|
|
28
|
+
rationale: structuredClone(verdict.rationale),
|
|
29
|
+
confidence: structuredClone(verdict.confidence),
|
|
30
|
+
distribution: structuredClone(verdict.distribution),
|
|
31
|
+
};
|
|
32
|
+
if (Object.hasOwn(verdict, 'providerRaw'))
|
|
33
|
+
rebuilt.providerRaw = structuredClone(verdict.providerRaw);
|
|
34
|
+
return rebuilt;
|
|
35
|
+
};
|
|
36
|
+
const rebuildReceipt = (receipt) => {
|
|
37
|
+
const rebuilt = {
|
|
38
|
+
schemaVersion: receipt.schemaVersion,
|
|
39
|
+
callId: receipt.callId,
|
|
40
|
+
correlationId: receipt.correlationId,
|
|
41
|
+
evaluator: receipt.evaluator === null ? null : { providerId: receipt.evaluator.providerId,
|
|
42
|
+
evaluatorId: receipt.evaluator.evaluatorId, revision: receipt.evaluator.revision },
|
|
43
|
+
servedEvaluator: receipt.servedEvaluator === null ? null : { providerId: receipt.servedEvaluator.providerId,
|
|
44
|
+
evaluatorId: receipt.servedEvaluator.evaluatorId, revision: receipt.servedEvaluator.revision },
|
|
45
|
+
servedModelId: receipt.servedModelId,
|
|
46
|
+
startedAt: receipt.startedAt,
|
|
47
|
+
finishedAt: receipt.finishedAt,
|
|
48
|
+
latencyMs: receipt.latencyMs,
|
|
49
|
+
dispatch: receipt.dispatch,
|
|
50
|
+
attempts: receipt.attempts,
|
|
51
|
+
usage: structuredClone(receipt.usage),
|
|
52
|
+
cost: structuredClone(receipt.cost),
|
|
53
|
+
retention: structuredClone(receipt.retention),
|
|
54
|
+
budget: structuredClone(receipt.budget),
|
|
55
|
+
outcome: receipt.outcome,
|
|
56
|
+
};
|
|
57
|
+
if (has(receipt, 'providerRequestId'))
|
|
58
|
+
rebuilt.providerRequestId = receipt.providerRequestId;
|
|
59
|
+
if (has(receipt, 'providerLatencyMs'))
|
|
60
|
+
rebuilt.providerLatencyMs = receipt.providerLatencyMs;
|
|
61
|
+
if (has(receipt, 'errorCode'))
|
|
62
|
+
rebuilt.errorCode = receipt.errorCode;
|
|
63
|
+
return rebuilt;
|
|
64
|
+
};
|
|
65
|
+
/** Pure wire-result validator: no network, provider imports, env reads or credentials.
|
|
66
|
+
* Validates a detached wire envelope against the transmitted request snapshot
|
|
67
|
+
* and trusted context snapshot, rebuilding both branches field by field. */
|
|
68
|
+
export function validateDecisionResult(requestSnapshot, contextSnapshot, wireValue) {
|
|
69
|
+
if (!isRecord(wireValue) || typeof requestSnapshot.correlationId !== 'string')
|
|
70
|
+
return null;
|
|
71
|
+
const expectedCorrelationId = requestSnapshot.correlationId;
|
|
72
|
+
if (hasOnlyKeys(wireValue, ['kind', 'ok', 'verdict', 'receipt'])
|
|
73
|
+
&& wireValue.kind === 'verdict' && wireValue.ok === true
|
|
74
|
+
&& isValidDecisionReceipt(wireValue.receipt, requestSnapshot, expectedCorrelationId, contextSnapshot)
|
|
75
|
+
&& wireValue.receipt.outcome === 'verdict'
|
|
76
|
+
&& isValidDecisionVerdict(wireValue.verdict, requestSnapshot, contextSnapshot)) {
|
|
77
|
+
return { kind: 'verdict', ok: true, verdict: rebuildVerdict(wireValue.verdict),
|
|
78
|
+
receipt: rebuildReceipt(wireValue.receipt) };
|
|
79
|
+
}
|
|
80
|
+
if (hasOnlyKeys(wireValue, ['kind', 'ok', 'error', 'receipt'])
|
|
81
|
+
&& wireValue.kind === 'error' && wireValue.ok === false
|
|
82
|
+
&& isValidDecisionReceipt(wireValue.receipt, requestSnapshot, expectedCorrelationId, contextSnapshot)
|
|
83
|
+
&& wireValue.receipt.outcome === 'error') {
|
|
84
|
+
const error = rebuildWireError(wireValue.error, wireValue.receipt);
|
|
85
|
+
if (error && wireValue.receipt.errorCode === error.code) {
|
|
86
|
+
return { kind: 'error', ok: false, error, receipt: rebuildReceipt(wireValue.receipt) };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=validate-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-result.js","sourceRoot":"","sources":["../../src/decision/validate-result.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { DecisionCriterion, DecisionRequest, EvaluatorRef } from './request.js';
|
|
2
|
+
/** Closed validation relation and version, published with the selected definition. */
|
|
3
|
+
export interface DecisionValidationProfile {
|
|
4
|
+
profile: 'native-distribution-v1' | 'scalar-label-v1';
|
|
5
|
+
version: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DecisionValidationScoreSemantics {
|
|
8
|
+
meaning: string;
|
|
9
|
+
min: number;
|
|
10
|
+
max: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DecisionValidationConfidenceSemantics {
|
|
13
|
+
meaning: string;
|
|
14
|
+
meaningRef: string;
|
|
15
|
+
min: number;
|
|
16
|
+
max: number;
|
|
17
|
+
}
|
|
18
|
+
/** Evidence the selected profile admits for one resolved kind. Null score or
|
|
19
|
+
* confidence forbids that carrier; rationale stays forbidden unless optional. */
|
|
20
|
+
export interface DecisionValidationSemantics {
|
|
21
|
+
nativeDecision: boolean;
|
|
22
|
+
score: DecisionValidationScoreSemantics | null;
|
|
23
|
+
confidence: DecisionValidationConfidenceSemantics | null;
|
|
24
|
+
rationale: 'forbidden' | 'optional';
|
|
25
|
+
}
|
|
26
|
+
export type DirectDecisionCriterion = Exclude<DecisionCriterion, {
|
|
27
|
+
kind: 'registered';
|
|
28
|
+
}>;
|
|
29
|
+
/** Trusted resolution of one registered criterion: exact requested identity,
|
|
30
|
+
* resolved direct criterion, trusted timestamp and consumer-set age bound. */
|
|
31
|
+
export interface DecisionRegisteredResolution {
|
|
32
|
+
criteriaId: string;
|
|
33
|
+
revision: string;
|
|
34
|
+
resolvedKind: 'binary' | 'graded' | 'choice';
|
|
35
|
+
criterion: DirectDecisionCriterion;
|
|
36
|
+
resolvedAt: string;
|
|
37
|
+
maxAgeMs: number;
|
|
38
|
+
}
|
|
39
|
+
/** The only source of revision-specific validation facts. The response never
|
|
40
|
+
* selects or weakens its own profile. Detached and frozen on parse. */
|
|
41
|
+
export interface DecisionValidationContext {
|
|
42
|
+
evaluator: EvaluatorRef;
|
|
43
|
+
validationProfile: DecisionValidationProfile;
|
|
44
|
+
acceptedServedModelIds: readonly string[];
|
|
45
|
+
semantics: DecisionValidationSemantics;
|
|
46
|
+
registeredResolution?: DecisionRegisteredResolution;
|
|
47
|
+
definitionDigest: string;
|
|
48
|
+
}
|
|
49
|
+
export type DecisionValidationContextResolver = (snapshot: DecisionRequest) => DecisionValidationContext | null | undefined | Promise<DecisionValidationContext | null | undefined>;
|
|
50
|
+
/** Parse, bind to the transmitted snapshot and freeze. Null on any fault:
|
|
51
|
+
* wrong shape, wrong evaluator, unknown profile, empty model set, missing or
|
|
52
|
+
* stale/future registered resolution. Direct criteria resolve from the
|
|
53
|
+
* request snapshot and never consult a resolution. */
|
|
54
|
+
export declare function parseDecisionValidationContext(candidate: unknown, request: DecisionRequest, nowMs: number): DecisionValidationContext | null;
|
|
55
|
+
//# sourceMappingURL=validation-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-context.d.ts","sourceRoot":"","sources":["../../src/decision/validation-context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAErF,sFAAsF;AACtF,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAAC;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,qCAAqC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAOD;iFACiF;AACjF,MAAM,WAAW,2BAA2B;IAC1C,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,gCAAgC,GAAG,IAAI,CAAC;IAC/C,UAAU,EAAE,qCAAqC,GAAG,IAAI,CAAC;IACzD,SAAS,EAAE,WAAW,GAAG,UAAU,CAAC;CACrC;AAED,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAEzF;8EAC8E;AAC9E,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC7C,SAAS,EAAE,uBAAuB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;uEACuE;AACvE,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,YAAY,CAAC;IACxB,iBAAiB,EAAE,yBAAyB,CAAC;IAC7C,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,SAAS,EAAE,2BAA2B,CAAC;IACvC,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;IACpD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,iCAAiC,GAAG,CAC9C,QAAQ,EAAE,eAAe,KACtB,yBAAyB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,yBAAyB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AA6C1G;;;sDAGsD;AACtD,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EACzF,KAAK,EAAE,MAAM,GAAG,yBAAyB,GAAG,IAAI,CAiEjD"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { hasOnlyKeys, isRecord, isText, snapshotBoundedJson } from './validation.js';
|
|
2
|
+
import { freezeDecisionData } from './descriptor-validation.js';
|
|
3
|
+
import { isDecisionCriterion } from './criterion.js';
|
|
4
|
+
const KNOWN_PROFILE_VERSIONS = {
|
|
5
|
+
'native-distribution-v1': ['v1'],
|
|
6
|
+
'scalar-label-v1': ['v1'],
|
|
7
|
+
};
|
|
8
|
+
const KNOWN_PROFILES = new Set(['native-distribution-v1', 'scalar-label-v1']);
|
|
9
|
+
const RESOLVED_KINDS = new Set(['binary', 'graded', 'choice']);
|
|
10
|
+
const DIGEST_RE = /^[0-9a-f]{64}$/;
|
|
11
|
+
const isEvaluatorRef = (value) => isRecord(value) && hasOnlyKeys(value, ['providerId', 'evaluatorId', 'revision'])
|
|
12
|
+
&& isText(value.providerId) && isText(value.evaluatorId) && isText(value.revision);
|
|
13
|
+
const sameEvaluatorRef = (left, right) => left.providerId === right.providerId && left.evaluatorId === right.evaluatorId && left.revision === right.revision;
|
|
14
|
+
const isBoundedMeaning = (value) => isRecord(value) && hasOnlyKeys(value, ['meaning', 'min', 'max'])
|
|
15
|
+
&& isText(value.meaning) && typeof value.min === 'number' && Number.isFinite(value.min)
|
|
16
|
+
&& typeof value.max === 'number' && Number.isFinite(value.max) && value.min < value.max;
|
|
17
|
+
const isBoundedConfidence = (value) => isRecord(value) && hasOnlyKeys(value, ['meaning', 'meaningRef', 'min', 'max'])
|
|
18
|
+
&& isText(value.meaning) && isText(value.meaningRef) && typeof value.min === 'number' && Number.isFinite(value.min)
|
|
19
|
+
&& typeof value.max === 'number' && Number.isFinite(value.max) && value.min <= value.max;
|
|
20
|
+
const isDirectCriterionOfKind = (value, kind) => {
|
|
21
|
+
if (!isDecisionCriterion(value) || value.kind !== kind)
|
|
22
|
+
return false;
|
|
23
|
+
return true;
|
|
24
|
+
};
|
|
25
|
+
const MAX_CONTEXT_AGE_MS = 86_400_000;
|
|
26
|
+
const isRegisteredResolution = (value, request, nowMs) => {
|
|
27
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['criteriaId', 'revision', 'resolvedKind', 'criterion', 'resolvedAt', 'maxAgeMs']))
|
|
28
|
+
return false;
|
|
29
|
+
if (!isText(value.criteriaId) || !isText(value.revision) || !RESOLVED_KINDS.has(value.resolvedKind))
|
|
30
|
+
return false;
|
|
31
|
+
if (request.criterion.kind !== 'registered')
|
|
32
|
+
return false;
|
|
33
|
+
if (value.criteriaId !== request.criterion.criteriaId || value.revision !== request.criterion.revision)
|
|
34
|
+
return false;
|
|
35
|
+
if (!isDirectCriterionOfKind(value.criterion, value.resolvedKind))
|
|
36
|
+
return false;
|
|
37
|
+
if (value.criterion.kind !== value.resolvedKind)
|
|
38
|
+
return false;
|
|
39
|
+
if (!isText(value.resolvedAt))
|
|
40
|
+
return false;
|
|
41
|
+
const resolvedAt = Date.parse(value.resolvedAt);
|
|
42
|
+
if (!Number.isFinite(resolvedAt) || resolvedAt > nowMs)
|
|
43
|
+
return false;
|
|
44
|
+
if (typeof value.maxAgeMs !== 'number' || !Number.isSafeInteger(value.maxAgeMs) || value.maxAgeMs < 1
|
|
45
|
+
|| value.maxAgeMs > MAX_CONTEXT_AGE_MS)
|
|
46
|
+
return false;
|
|
47
|
+
return nowMs - resolvedAt <= value.maxAgeMs;
|
|
48
|
+
};
|
|
49
|
+
/** Parse, bind to the transmitted snapshot and freeze. Null on any fault:
|
|
50
|
+
* wrong shape, wrong evaluator, unknown profile, empty model set, missing or
|
|
51
|
+
* stale/future registered resolution. Direct criteria resolve from the
|
|
52
|
+
* request snapshot and never consult a resolution. */
|
|
53
|
+
export function parseDecisionValidationContext(candidate, request, nowMs) {
|
|
54
|
+
const snapshot = snapshotBoundedJson(candidate);
|
|
55
|
+
if (!snapshot.ok || !isRecord(snapshot.value))
|
|
56
|
+
return null;
|
|
57
|
+
const source = snapshot.value;
|
|
58
|
+
if (!hasOnlyKeys(source, ['evaluator', 'validationProfile', 'acceptedServedModelIds',
|
|
59
|
+
'semantics', 'definitionDigest', 'registeredResolution'])
|
|
60
|
+
&& !hasOnlyKeys(source, ['evaluator', 'validationProfile', 'acceptedServedModelIds', 'semantics', 'definitionDigest'])) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (!isEvaluatorRef(source.evaluator) || !sameEvaluatorRef(source.evaluator, request.evaluator))
|
|
64
|
+
return null;
|
|
65
|
+
const profile = source.validationProfile;
|
|
66
|
+
if (!isRecord(profile) || !hasOnlyKeys(profile, ['profile', 'version'])
|
|
67
|
+
|| !KNOWN_PROFILES.has(profile.profile) || !isText(profile.version))
|
|
68
|
+
return null;
|
|
69
|
+
const allowedVersions = KNOWN_PROFILE_VERSIONS[profile.profile];
|
|
70
|
+
if (!allowedVersions || !allowedVersions.includes(profile.version))
|
|
71
|
+
return null;
|
|
72
|
+
const models = source.acceptedServedModelIds;
|
|
73
|
+
if (!Array.isArray(models) || models.length === 0 || !models.every(isText)
|
|
74
|
+
|| new Set(models).size !== models.length)
|
|
75
|
+
return null;
|
|
76
|
+
const semantics = source.semantics;
|
|
77
|
+
if (!isRecord(semantics) || !hasOnlyKeys(semantics, ['nativeDecision', 'score', 'confidence', 'rationale']))
|
|
78
|
+
return null;
|
|
79
|
+
if (typeof semantics.nativeDecision !== 'boolean')
|
|
80
|
+
return null;
|
|
81
|
+
if (semantics.score !== null && !isBoundedMeaning(semantics.score))
|
|
82
|
+
return null;
|
|
83
|
+
if (semantics.confidence !== null && !isBoundedConfidence(semantics.confidence))
|
|
84
|
+
return null;
|
|
85
|
+
if (semantics.rationale !== 'forbidden' && semantics.rationale !== 'optional')
|
|
86
|
+
return null;
|
|
87
|
+
// §3.4 native-distribution-v1 forbids fabricated native evidence: a context
|
|
88
|
+
// that permits rationale under the native profile contradicts the profile
|
|
89
|
+
// and must fail before headers or fetch, never redefine native semantics.
|
|
90
|
+
if (profile.profile === 'native-distribution-v1' && semantics.rationale !== 'forbidden')
|
|
91
|
+
return null;
|
|
92
|
+
if (!isText(source.definitionDigest) || !DIGEST_RE.test(source.definitionDigest))
|
|
93
|
+
return null;
|
|
94
|
+
const registered = request.criterion.kind === 'registered';
|
|
95
|
+
if (registered && !isRegisteredResolution(source.registeredResolution, request, nowMs))
|
|
96
|
+
return null;
|
|
97
|
+
if (!registered && source.registeredResolution !== undefined)
|
|
98
|
+
return null;
|
|
99
|
+
// Required profile evidence (§3.4): a native binary/graded verdict carries a
|
|
100
|
+
// native score, so a native context without score semantics for those kinds
|
|
101
|
+
// cannot validate anything and fails here rather than at the response.
|
|
102
|
+
const effectiveKind = registered
|
|
103
|
+
? source.registeredResolution.resolvedKind
|
|
104
|
+
: request.criterion.kind;
|
|
105
|
+
if (profile.profile === 'native-distribution-v1' && effectiveKind !== 'choice' && semantics.score === null)
|
|
106
|
+
return null;
|
|
107
|
+
const ref = source.evaluator;
|
|
108
|
+
const scoreSource = semantics.score;
|
|
109
|
+
const confidenceSource = semantics.confidence;
|
|
110
|
+
const context = {
|
|
111
|
+
evaluator: { providerId: ref.providerId, evaluatorId: ref.evaluatorId, revision: ref.revision },
|
|
112
|
+
validationProfile: { profile: profile.profile,
|
|
113
|
+
version: profile.version },
|
|
114
|
+
acceptedServedModelIds: [...models],
|
|
115
|
+
semantics: { nativeDecision: semantics.nativeDecision,
|
|
116
|
+
score: scoreSource === null ? null : { ...scoreSource },
|
|
117
|
+
confidence: confidenceSource === null ? null : { ...confidenceSource },
|
|
118
|
+
rationale: semantics.rationale },
|
|
119
|
+
definitionDigest: source.definitionDigest,
|
|
120
|
+
};
|
|
121
|
+
if (registered) {
|
|
122
|
+
const resolution = source.registeredResolution;
|
|
123
|
+
context.registeredResolution = {
|
|
124
|
+
criteriaId: resolution.criteriaId,
|
|
125
|
+
revision: resolution.revision,
|
|
126
|
+
resolvedKind: resolution.resolvedKind,
|
|
127
|
+
criterion: structuredClone(resolution.criterion),
|
|
128
|
+
resolvedAt: resolution.resolvedAt,
|
|
129
|
+
maxAgeMs: resolution.maxAgeMs,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return freezeDecisionData(context);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=validation-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-context.js","sourceRoot":"","sources":["../../src/decision/validation-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const DECISION_MAX_JSON_BYTES: number;
|
|
2
|
+
export declare const DECISION_MAX_JSON_DEPTH = 16;
|
|
3
|
+
export declare const DECISION_MAX_RAW_BYTES: number;
|
|
4
|
+
export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
|
|
5
|
+
export declare const has: (value: object, key: string) => boolean;
|
|
6
|
+
export declare const hasOnlyKeys: (value: object, keys: readonly string[]) => boolean;
|
|
7
|
+
export declare const isText: (value: unknown) => value is string;
|
|
8
|
+
export declare const isMicroUsd: (value: unknown) => value is string;
|
|
9
|
+
export declare const isCorrelationId: (value: unknown) => value is string;
|
|
10
|
+
/** sha256 hex digest over the canonical form of one compiled artifact. */
|
|
11
|
+
export declare const digestStructuredArtifact: (value: unknown) => string;
|
|
12
|
+
export declare function snapshotBoundedJson(value: unknown, maxBytes?: number): {
|
|
13
|
+
ok: true;
|
|
14
|
+
value: unknown;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
};
|
|
18
|
+
export declare const isBoundedJson: (value: unknown, maxBytes?: number) => boolean;
|
|
19
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/decision/validation.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,QAAa,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAGhD,eAAO,MAAM,QAAQ,UAAW,OAAO,qCAC+B,CAAC;AACvE,eAAO,MAAM,GAAG,UAAW,MAAM,OAAO,MAAM,KAAG,OAAoC,CAAC;AACtF,eAAO,MAAM,WAAW,UAAW,MAAM,QAAQ,SAAS,MAAM,EAAE,KAAG,OACd,CAAC;AACxD,eAAO,MAAM,MAAM,UAAW,OAAO,oBACiB,CAAC;AACvD,eAAO,MAAM,UAAU,UAAW,OAAO,oBACqB,CAAC;AAC/D,eAAO,MAAM,eAAe,UAAW,OAAO,oBACuB,CAAC;AActE,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,UAAW,OAAO,KAAG,MACO,CAAC;AAkClE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAA0B,GACpF;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAU7C;AAED,eAAO,MAAM,aAAa,UAAW,OAAO,wBAAuC,OAC1C,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export const DECISION_MAX_JSON_BYTES = 256 * 1024;
|
|
3
|
+
export const DECISION_MAX_JSON_DEPTH = 16;
|
|
4
|
+
export const DECISION_MAX_RAW_BYTES = 16 * 1024;
|
|
5
|
+
const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);
|
|
6
|
+
export const isRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
7
|
+
export const has = (value, key) => Object.hasOwn(value, key);
|
|
8
|
+
export const hasOnlyKeys = (value, keys) => Object.keys(value).every((key) => keys.includes(key));
|
|
9
|
+
export const isText = (value) => typeof value === 'string' && value.trim().length > 0;
|
|
10
|
+
export const isMicroUsd = (value) => typeof value === 'string' && /^(0|[1-9][0-9]*)$/.test(value);
|
|
11
|
+
export const isCorrelationId = (value) => typeof value === 'string' && /^[A-Za-z0-9._:-]{1,128}$/.test(value);
|
|
12
|
+
/** Canonical JSON with sorted object keys, so digests are process-stable. */
|
|
13
|
+
const canonicalJson = (value) => {
|
|
14
|
+
if (Array.isArray(value))
|
|
15
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
16
|
+
if (value !== null && typeof value === 'object') {
|
|
17
|
+
const record = value;
|
|
18
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(',')}}`;
|
|
19
|
+
}
|
|
20
|
+
const serialized = JSON.stringify(value) ?? 'null';
|
|
21
|
+
if (typeof value === 'number' && !Number.isFinite(value))
|
|
22
|
+
throw new Error('Non-finite digest input.');
|
|
23
|
+
return serialized;
|
|
24
|
+
};
|
|
25
|
+
/** sha256 hex digest over the canonical form of one compiled artifact. */
|
|
26
|
+
export const digestStructuredArtifact = (value) => createHash('sha256').update(canonicalJson(value)).digest('hex');
|
|
27
|
+
/** Copy data descriptors only; never serialize or read fields from the live caller object. */
|
|
28
|
+
function copyJson(value, depth, budget) {
|
|
29
|
+
if (--budget.remaining < 0 || depth > DECISION_MAX_JSON_DEPTH)
|
|
30
|
+
throw new Error('Invalid JSON.');
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
budget.remaining -= value.length;
|
|
33
|
+
if (budget.remaining < 0)
|
|
34
|
+
throw new Error('Invalid JSON.');
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
if (value === null || typeof value === 'boolean')
|
|
38
|
+
return value;
|
|
39
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
40
|
+
return value;
|
|
41
|
+
if (typeof value !== 'object')
|
|
42
|
+
throw new Error('Invalid JSON.');
|
|
43
|
+
const array = Array.isArray(value);
|
|
44
|
+
const proto = Object.getPrototypeOf(value);
|
|
45
|
+
if (proto !== (array ? Array.prototype : Object.prototype) && proto !== null)
|
|
46
|
+
throw new Error('Invalid JSON.');
|
|
47
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
48
|
+
if (Object.getOwnPropertySymbols(descriptors).length)
|
|
49
|
+
throw new Error('Invalid JSON.');
|
|
50
|
+
const length = descriptors.length?.value;
|
|
51
|
+
if (array && (!Number.isSafeInteger(length) || length < 0
|
|
52
|
+
|| Object.keys(descriptors).length !== length + 1))
|
|
53
|
+
throw new Error('Invalid JSON.');
|
|
54
|
+
const copy = array ? [] : Object.create(null);
|
|
55
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
56
|
+
if (array && key === 'length')
|
|
57
|
+
continue;
|
|
58
|
+
if (array && (!/^(0|[1-9][0-9]*)$/.test(key) || Number(key) >= length))
|
|
59
|
+
throw new Error('Invalid JSON.');
|
|
60
|
+
if (unsafeKeys.has(key) || descriptor.enumerable !== true || !has(descriptor, 'value'))
|
|
61
|
+
throw new Error('Invalid JSON.');
|
|
62
|
+
// Node visits and text lengths are lower bounds on serialized bytes, including shared paths.
|
|
63
|
+
if (!array)
|
|
64
|
+
budget.remaining -= key.length;
|
|
65
|
+
if (budget.remaining < 0)
|
|
66
|
+
throw new Error('Invalid JSON.');
|
|
67
|
+
copy[key] = copyJson(descriptor.value, depth + 1, budget);
|
|
68
|
+
}
|
|
69
|
+
return copy;
|
|
70
|
+
}
|
|
71
|
+
export function snapshotBoundedJson(value, maxBytes = DECISION_MAX_JSON_BYTES) {
|
|
72
|
+
try {
|
|
73
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)
|
|
74
|
+
return { ok: false };
|
|
75
|
+
const copy = copyJson(value, 0, { remaining: maxBytes });
|
|
76
|
+
const serialized = JSON.stringify(copy);
|
|
77
|
+
if (new TextEncoder().encode(serialized).byteLength > maxBytes)
|
|
78
|
+
return { ok: false };
|
|
79
|
+
return { ok: true, value: JSON.parse(serialized) };
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return { ok: false };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export const isBoundedJson = (value, maxBytes = DECISION_MAX_JSON_BYTES) => snapshotBoundedJson(value, maxBytes).ok;
|
|
86
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/decision/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { DecisionRule, Json, DecisionCriterion } from './request.js';
|
|
2
|
+
export type ScoreScale = {
|
|
3
|
+
kind: 'bounded';
|
|
4
|
+
min: number;
|
|
5
|
+
max: number;
|
|
6
|
+
direction: 'higher-is-better' | 'lower-is-better' | 'unordered';
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'unknown';
|
|
9
|
+
reason: 'unknown (source-gap)';
|
|
10
|
+
};
|
|
11
|
+
export interface DecisionScore {
|
|
12
|
+
value: number;
|
|
13
|
+
scale: ScoreScale;
|
|
14
|
+
meaning: 'rubric-grade' | 'probability-true' | 'support' | 'provider-defined';
|
|
15
|
+
normalized?: {
|
|
16
|
+
value: number;
|
|
17
|
+
transform: 'linear-min-max';
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface DecisionVerdict {
|
|
21
|
+
criterionKind: DecisionCriterion['kind'];
|
|
22
|
+
resolvedCriterionKind: 'binary' | 'graded' | 'choice';
|
|
23
|
+
score: DecisionScore | null;
|
|
24
|
+
decision: {
|
|
25
|
+
pass: boolean;
|
|
26
|
+
origin: 'provider' | 'threshold' | 'labels';
|
|
27
|
+
rule?: DecisionRule;
|
|
28
|
+
} | null;
|
|
29
|
+
label: {
|
|
30
|
+
value: string;
|
|
31
|
+
origin: 'provider';
|
|
32
|
+
} | null;
|
|
33
|
+
rationale: {
|
|
34
|
+
text: string;
|
|
35
|
+
origin: 'provider';
|
|
36
|
+
} | null;
|
|
37
|
+
confidence: {
|
|
38
|
+
value: number;
|
|
39
|
+
min: number;
|
|
40
|
+
max: number;
|
|
41
|
+
meaning: 'provider-confidence' | 'decision-confidence';
|
|
42
|
+
meaningRef: string;
|
|
43
|
+
origin: 'provider';
|
|
44
|
+
} | null;
|
|
45
|
+
distribution: readonly {
|
|
46
|
+
outcome: string;
|
|
47
|
+
nativeOutcome: string;
|
|
48
|
+
probability: number;
|
|
49
|
+
}[] | null;
|
|
50
|
+
providerRaw?: {
|
|
51
|
+
data: Json;
|
|
52
|
+
bytes: number;
|
|
53
|
+
truncated: boolean;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Preserve native values and direction; normalization is relative position, not accuracy. */
|
|
57
|
+
export declare function parseDecisionScore(candidate: unknown): DecisionScore | null;
|
|
58
|
+
/** A descriptor supplies the documented meaning; this never derives confidence from score. */
|
|
59
|
+
export declare function parseDecisionConfidence(candidate: unknown): DecisionVerdict['confidence'];
|
|
60
|
+
/** Map an exact, descriptor-owned native key set, preserving order and probabilities. */
|
|
61
|
+
export declare function mapDecisionDistribution(candidate: unknown, declared: readonly {
|
|
62
|
+
outcome: string;
|
|
63
|
+
nativeOutcome: string;
|
|
64
|
+
}[]): DecisionVerdict['distribution'];
|
|
65
|
+
export type DecisionDerivation = {
|
|
66
|
+
ok: true;
|
|
67
|
+
decision: DecisionVerdict['decision'];
|
|
68
|
+
} | {
|
|
69
|
+
ok: false;
|
|
70
|
+
code: 'REQUEST_INVALID' | 'CAPABILITY_UNSUPPORTED' | 'VERDICT_INVALID';
|
|
71
|
+
};
|
|
72
|
+
export declare function deriveDecision(input: {
|
|
73
|
+
rule?: DecisionRule;
|
|
74
|
+
score: DecisionScore | null;
|
|
75
|
+
label: string | null;
|
|
76
|
+
providerDecision: boolean | null;
|
|
77
|
+
declaredLabels?: readonly string[];
|
|
78
|
+
}): DecisionDerivation;
|
|
79
|
+
/** Primary values must be meaningful; false and zero are valid evidence. */
|
|
80
|
+
export declare function hasDecisionVerdictValue(value: Pick<DecisionVerdict, 'score' | 'decision' | 'label'>): boolean;
|
|
81
|
+
//# sourceMappingURL=verdict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdict.d.ts","sourceRoot":"","sources":["../../src/decision/verdict.ts"],"names":[],"mappings":"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"}
|