@bounded-authority-protocol/verifier 0.2.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 +190 -0
- package/NOTICE +10 -0
- package/README.md +183 -0
- package/dist/src/base64url.d.ts +2 -0
- package/dist/src/base64url.js +115 -0
- package/dist/src/base64url.js.map +1 -0
- package/dist/src/bounds.d.ts +50 -0
- package/dist/src/bounds.js +114 -0
- package/dist/src/bounds.js.map +1 -0
- package/dist/src/compact.d.ts +19 -0
- package/dist/src/compact.js +111 -0
- package/dist/src/compact.js.map +1 -0
- package/dist/src/digest.d.ts +8 -0
- package/dist/src/digest.js +116 -0
- package/dist/src/digest.js.map +1 -0
- package/dist/src/ed25519.d.ts +7 -0
- package/dist/src/ed25519.js +61 -0
- package/dist/src/ed25519.js.map +1 -0
- package/dist/src/error.d.ts +15 -0
- package/dist/src/error.js +34 -0
- package/dist/src/error.js.map +1 -0
- package/dist/src/facts.d.ts +104 -0
- package/dist/src/facts.js +6 -0
- package/dist/src/facts.js.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +31 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jcs.d.ts +3 -0
- package/dist/src/jcs.js +285 -0
- package/dist/src/jcs.js.map +1 -0
- package/dist/src/json.d.ts +25 -0
- package/dist/src/json.js +473 -0
- package/dist/src/json.js.map +1 -0
- package/dist/src/jwk.d.ts +14 -0
- package/dist/src/jwk.js +77 -0
- package/dist/src/jwk.js.map +1 -0
- package/dist/src/selector.d.ts +16 -0
- package/dist/src/selector.js +142 -0
- package/dist/src/selector.js.map +1 -0
- package/dist/src/uri.d.ts +4 -0
- package/dist/src/uri.js +280 -0
- package/dist/src/uri.js.map +1 -0
- package/dist/src/v1.d.ts +211 -0
- package/dist/src/v1.js +2206 -0
- package/dist/src/v1.js.map +1 -0
- package/dist/src/v2.d.ts +291 -0
- package/dist/src/v2.js +2300 -0
- package/dist/src/v2.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { fail } from "./error.js";
|
|
2
|
+
// The fixed v1 profile maxima — the 38-row Hard maxima table (spec/bap-v1.md).
|
|
3
|
+
// Pinned by the corpus bounds.new cases so any mistyped constant fails. Fixed-width keys
|
|
4
|
+
// (REQ1-BOUNDS-fixed-widths, L395): digest_bytes, public_key_bytes, signature_bytes are the immutable
|
|
5
|
+
// cryptographic constants of suite BAP1-Ed25519-SHA256 — they MUST equal the maximum exactly (widening
|
|
6
|
+
// is forbidden); all others may be tightened to a positive integer at most the maximum.
|
|
7
|
+
export const MAXIMA = {
|
|
8
|
+
compact_bytes: 65536,
|
|
9
|
+
encoded_segment_bytes: 32768,
|
|
10
|
+
decoded_segment_bytes: 24576,
|
|
11
|
+
json_bytes: 65536,
|
|
12
|
+
depth: 32,
|
|
13
|
+
object_members: 64,
|
|
14
|
+
array_items: 256,
|
|
15
|
+
total_nodes: 4096,
|
|
16
|
+
string_bytes: 8192,
|
|
17
|
+
key_bytes: 128,
|
|
18
|
+
number_lexeme_bytes: 64,
|
|
19
|
+
integer_magnitude: 9007199254740991,
|
|
20
|
+
float_magnitude: 9007199254740991,
|
|
21
|
+
kid_bytes: 128,
|
|
22
|
+
jcs_bytes: 65536,
|
|
23
|
+
uri_bytes: 8192,
|
|
24
|
+
identifier_bytes: 512,
|
|
25
|
+
nonce_bytes: 512,
|
|
26
|
+
method_bytes: 32,
|
|
27
|
+
operation_bytes: 128,
|
|
28
|
+
audiences: 64,
|
|
29
|
+
operations: 64,
|
|
30
|
+
selectors: 64,
|
|
31
|
+
path_segments: 32,
|
|
32
|
+
one_of_values: 256,
|
|
33
|
+
public_key_bytes: 32,
|
|
34
|
+
signature_bytes: 64,
|
|
35
|
+
digest_bytes: 32,
|
|
36
|
+
clock_skew: 60,
|
|
37
|
+
proof_max_age: 300,
|
|
38
|
+
chain_row_bytes: 4096,
|
|
39
|
+
chain_rows: 65536,
|
|
40
|
+
anchor_bytes: 8192,
|
|
41
|
+
archive_header_bytes: 8192,
|
|
42
|
+
archive_chunks: 65796,
|
|
43
|
+
archive_bytes: 270820384,
|
|
44
|
+
object_version_bytes: 512,
|
|
45
|
+
key_transitions: 256,
|
|
46
|
+
};
|
|
47
|
+
export const MAXIMUM_BOUNDS = { maximum: MAXIMA, overrides: new Map() };
|
|
48
|
+
export function boundsMaximum() {
|
|
49
|
+
// Return a FRESH Bounds each call so a caller cannot mutate a shared singleton's overrides Map
|
|
50
|
+
// to widen the profile maximum globally (ReadonlyMap is compile-time only; runtime mutation is
|
|
51
|
+
// otherwise possible). REQ1-BOUNDS-tighten-only.
|
|
52
|
+
return { maximum: MAXIMA, overrides: new Map() };
|
|
53
|
+
}
|
|
54
|
+
// REQ1-BOUNDS-reject-list (L397): unknown, non-integer, zero, negative, widening, or fixed-width-
|
|
55
|
+
// changing limits are invalid. Fixed-width keys (L395) cannot be tightened or widened.
|
|
56
|
+
const FIXED_WIDTH_KEYS = new Set([
|
|
57
|
+
"digest_bytes",
|
|
58
|
+
"public_key_bytes",
|
|
59
|
+
"signature_bytes",
|
|
60
|
+
]);
|
|
61
|
+
export function boundsNew(tightening) {
|
|
62
|
+
if (tightening === undefined)
|
|
63
|
+
return MAXIMUM_BOUNDS;
|
|
64
|
+
const overrides = new Map();
|
|
65
|
+
for (const [key, value] of Object.entries(tightening)) {
|
|
66
|
+
if (!(key in MAXIMA))
|
|
67
|
+
fail(`bounds.new: unknown limit ${key}`);
|
|
68
|
+
if (!Number.isInteger(value))
|
|
69
|
+
fail(`bounds.new: non-integer limit ${key}`);
|
|
70
|
+
const mk = key;
|
|
71
|
+
if (FIXED_WIDTH_KEYS.has(mk)) {
|
|
72
|
+
// REQ1-BOUNDS-fixed-widths: fixed-width keys cannot be tightened or widened, but setting to
|
|
73
|
+
// the exact maximum is an identity no-op (valid). Any other value rejects.
|
|
74
|
+
if (value !== MAXIMA[mk])
|
|
75
|
+
fail(`bounds.new: fixed-width key ${key} must equal maximum`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
if (value <= 0)
|
|
79
|
+
fail(`bounds.new: non-positive limit ${key}`);
|
|
80
|
+
if (value > MAXIMA[mk])
|
|
81
|
+
fail(`bounds.new: widening limit ${key}`);
|
|
82
|
+
}
|
|
83
|
+
overrides.set(mk, value);
|
|
84
|
+
}
|
|
85
|
+
return { maximum: MAXIMA, overrides };
|
|
86
|
+
}
|
|
87
|
+
// Re-validate a Bounds object (mirrors the reference's Bounds.coerce/1, anchored_export_codec.ex:33
|
|
88
|
+
// + runtime.ex:123 etc.). Bounds is an exported structural interface, so a caller can hand-craft a
|
|
89
|
+
// {maximum, overrides} object that bypasses boundsNew — including a WIDENING override (compact_bytes
|
|
90
|
+
// > MAXIMA). resolve() trusts the override directly; without this gate the verify/decode paths would
|
|
91
|
+
// honor the forged widening (cross-vendor F2). coerceBounds re-runs the boundsNew validation over the
|
|
92
|
+
// override map so every entry point that resolves caller-supplied bounds fails closed on a forgery.
|
|
93
|
+
export function coerceBounds(b) {
|
|
94
|
+
for (const [key, value] of b.overrides) {
|
|
95
|
+
if (!Number.isInteger(value))
|
|
96
|
+
fail(`bounds.coerce: non-integer limit ${key}`);
|
|
97
|
+
if (FIXED_WIDTH_KEYS.has(key)) {
|
|
98
|
+
if (value !== MAXIMA[key])
|
|
99
|
+
fail(`bounds.coerce: fixed-width key ${key} must equal maximum`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
if (value <= 0)
|
|
103
|
+
fail(`bounds.coerce: non-positive limit ${key}`);
|
|
104
|
+
if (value > MAXIMA[key])
|
|
105
|
+
fail(`bounds.coerce: widening limit ${key}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return b;
|
|
109
|
+
}
|
|
110
|
+
// Resolve a bound: the override if present, else the maximum.
|
|
111
|
+
export function resolve(b, key) {
|
|
112
|
+
return b.overrides.get(key) ?? MAXIMA[key];
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=bounds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounds.js","sourceRoot":"","sources":["../../src/bounds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Result } from "./error.js";
|
|
2
|
+
import { type Bounds } from "./bounds.js";
|
|
3
|
+
export interface CompactSegments {
|
|
4
|
+
readonly protectedSegment: Uint8Array;
|
|
5
|
+
readonly payloadSegment: Uint8Array;
|
|
6
|
+
readonly signature: Uint8Array;
|
|
7
|
+
readonly protectedBytes: Uint8Array;
|
|
8
|
+
readonly payloadBytes: Uint8Array;
|
|
9
|
+
readonly signingInput: Uint8Array;
|
|
10
|
+
}
|
|
11
|
+
export declare function parseCompact(input: Uint8Array, bounds?: Bounds): CompactSegments;
|
|
12
|
+
export declare function scanCompact(input: Uint8Array, bounds?: Bounds): void;
|
|
13
|
+
export type SigningInputKind = "grant" | "proof" | "local_loopback_http_proof" | "boundary_anchor" | "key_transition";
|
|
14
|
+
export interface SigningInput {
|
|
15
|
+
readonly kind: SigningInputKind;
|
|
16
|
+
readonly protectedSegment: Uint8Array;
|
|
17
|
+
readonly payloadSegment: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
export declare function assembleSegments(input: SigningInput, signature: Uint8Array): Result<Uint8Array>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { fail, assert, trying } from "./error.js";
|
|
2
|
+
import { base64urlDecode, base64urlEncode } from "./base64url.js";
|
|
3
|
+
import { resolve, coerceBounds, MAXIMUM_BOUNDS } from "./bounds.js";
|
|
4
|
+
const DOT = 0x2e;
|
|
5
|
+
// Parse + bound a compact input into 3 segments. Validates the segment count, bounds, canonical
|
|
6
|
+
// base64url of each segment, and decodes protected + payload (signature kept raw after decode).
|
|
7
|
+
export function parseCompact(input, bounds = MAXIMUM_BOUNDS) {
|
|
8
|
+
// Cross-vendor F2: re-validate caller-supplied bounds (a hand-crafted Bounds can widen limits past
|
|
9
|
+
// MAXIMA, bypassing boundsNew). Mirrors the reference's Bounds.coerce on every entry point.
|
|
10
|
+
const b = coerceBounds(bounds);
|
|
11
|
+
if (input.length > resolve(b, "compact_bytes"))
|
|
12
|
+
fail("compact: byte bound");
|
|
13
|
+
if (input.length === 0)
|
|
14
|
+
fail("compact: empty");
|
|
15
|
+
// Split into exactly 3 segments on '.'.
|
|
16
|
+
const dots = [];
|
|
17
|
+
for (let i = 0; i < input.length; i++)
|
|
18
|
+
if (input[i] === DOT)
|
|
19
|
+
dots.push(i);
|
|
20
|
+
if (dots.length !== 2)
|
|
21
|
+
fail("compact: three segments");
|
|
22
|
+
const d0 = dots[0];
|
|
23
|
+
const d1 = dots[1];
|
|
24
|
+
if (d0 === 0 || d1 === d0 + 1 || d1 === input.length - 1)
|
|
25
|
+
fail("compact: empty segment");
|
|
26
|
+
const protectedText = input.subarray(0, d0);
|
|
27
|
+
const payloadText = input.subarray(d0 + 1, d1);
|
|
28
|
+
const signatureText = input.subarray(d1 + 1);
|
|
29
|
+
if (protectedText.length > resolve(b, "encoded_segment_bytes"))
|
|
30
|
+
fail("compact: protected segment bound");
|
|
31
|
+
if (payloadText.length > resolve(b, "encoded_segment_bytes"))
|
|
32
|
+
fail("compact: payload segment bound");
|
|
33
|
+
const protectedBytes = base64urlDecode(protectedText, resolve(b, "decoded_segment_bytes"));
|
|
34
|
+
const payloadBytes = base64urlDecode(payloadText, resolve(b, "decoded_segment_bytes"));
|
|
35
|
+
const signature = base64urlDecode(signatureText);
|
|
36
|
+
// Decoded signature-width gate (runtime.ex:237 parse_grant, :259 parse_proof,
|
|
37
|
+
// boundary_anchor_codec.ex:88, key_transition_codec.ex:120 all enforce byte_size(signature) ==
|
|
38
|
+
// signature_bytes). scanCompact (the ath/hash gate) intentionally does NOT — it mirrors
|
|
39
|
+
// CompactJws.scan (shape+size only); the decoded-width check belongs to the decode path.
|
|
40
|
+
if (signature.length !== resolve(b, "signature_bytes"))
|
|
41
|
+
fail("compact: signature width");
|
|
42
|
+
return {
|
|
43
|
+
protectedSegment: protectedText,
|
|
44
|
+
payloadSegment: payloadText,
|
|
45
|
+
signature,
|
|
46
|
+
protectedBytes,
|
|
47
|
+
payloadBytes,
|
|
48
|
+
signingInput: concat(protectedText, DOTB, payloadText),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const DOTB = new Uint8Array([DOT]);
|
|
52
|
+
// scan_compact — faithful port of the reference CompactJws.scan (compact_jws.ex:16-27): the
|
|
53
|
+
// shape+size gate that `ath`/`hash` run BEFORE hashing a compact. It validates structure + bounds
|
|
54
|
+
// only — NOT base64url canonicity (canonicity is the full verify path's job via parseCompact). The
|
|
55
|
+
// producer ath (proof_signing_input) and the verify grant-hash both gate on this so a non-compact
|
|
56
|
+
// grant (wrong segment count, oversized, dotted signature) is rejected rather than hashed. Mirrors
|
|
57
|
+
// the Rust scan_compact gate added in the BAP-15 closeout.
|
|
58
|
+
export function scanCompact(input, bounds = MAXIMUM_BOUNDS) {
|
|
59
|
+
const b = coerceBounds(bounds);
|
|
60
|
+
if (input.length > resolve(b, "compact_bytes"))
|
|
61
|
+
fail("compact: byte bound");
|
|
62
|
+
if (input.length === 0)
|
|
63
|
+
fail("compact: empty");
|
|
64
|
+
const dots = [];
|
|
65
|
+
for (let i = 0; i < input.length; i++)
|
|
66
|
+
if (input[i] === DOT)
|
|
67
|
+
dots.push(i);
|
|
68
|
+
if (dots.length !== 2)
|
|
69
|
+
fail("compact: three segments");
|
|
70
|
+
const d0 = dots[0], d1 = dots[1];
|
|
71
|
+
if (d0 === 0 || d1 === d0 + 1 || d1 === input.length - 1)
|
|
72
|
+
fail("compact: empty segment");
|
|
73
|
+
const segBytes = resolve(b, "encoded_segment_bytes");
|
|
74
|
+
if (d0 > segBytes)
|
|
75
|
+
fail("compact: protected segment bound");
|
|
76
|
+
if (d1 - d0 - 1 > segBytes)
|
|
77
|
+
fail("compact: payload segment bound");
|
|
78
|
+
if (input.length - d1 - 1 > segBytes)
|
|
79
|
+
fail("compact: signature segment bound");
|
|
80
|
+
// signature dot-free: dots.length === 2 guarantees no dot inside the signature segment.
|
|
81
|
+
}
|
|
82
|
+
function concat(...parts) {
|
|
83
|
+
let len = 0;
|
|
84
|
+
for (const p of parts)
|
|
85
|
+
len += p.length;
|
|
86
|
+
const out = new Uint8Array(len);
|
|
87
|
+
let off = 0;
|
|
88
|
+
for (const p of parts) {
|
|
89
|
+
out.set(p, off);
|
|
90
|
+
off += p.length;
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
// assemble_segments: the LOW-LEVEL compact assembler (mirrors CompactJws.assemble's byte assembly,
|
|
95
|
+
// compact_jws.ex:41-43). Validates only the kind closed-set + 64-byte signature width, then
|
|
96
|
+
// concatenates protected.payload.base64url(signature). It does NOT validate the signing-input
|
|
97
|
+
// header/payload content — that is the v1.ts assemble_compact FAÇADE's job (re-parse per kind,
|
|
98
|
+
// runtime.ex:151 validate_assembled_compact). Test helpers and conformance use this to build
|
|
99
|
+
// compacts freely; the public contract is the façade (assembleCompact in v1.ts).
|
|
100
|
+
export function assembleSegments(input, signature) {
|
|
101
|
+
return trying(() => {
|
|
102
|
+
const KINDS = ["grant", "proof", "local_loopback_http_proof", "boundary_anchor", "key_transition"];
|
|
103
|
+
if (!KINDS.includes(input.kind))
|
|
104
|
+
fail("assemble_segments: kind closed set");
|
|
105
|
+
assert(signature.length === 64, "assemble_segments: signature width 64");
|
|
106
|
+
// compact = protected "." payload "." base64url(signature).
|
|
107
|
+
const sigB64 = base64urlEncode(signature);
|
|
108
|
+
return concat(input.protectedSegment, DOTB, input.payloadSegment, DOTB, sigB64);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/compact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Result } from "./error.js";
|
|
2
|
+
import { type Tagged } from "./json.js";
|
|
3
|
+
import { type Bounds } from "./bounds.js";
|
|
4
|
+
export declare const REQUEST_PREFIX: Uint8Array<ArrayBuffer>;
|
|
5
|
+
export declare function typedProject(value: Tagged): Tagged;
|
|
6
|
+
export declare function requestDigest(operation: string, castArguments: Tagged, bounds?: Bounds): Uint8Array;
|
|
7
|
+
export declare function digestWithPrefix(prefix: Uint8Array, operation: string, castArguments: Tagged, bounds?: Bounds): Uint8Array;
|
|
8
|
+
export declare function requestDigestB64url(operation: string, castArguments: Tagged, bounds?: Bounds): Result<string>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { fail, trying } from "./error.js";
|
|
2
|
+
import { sha256 } from "./ed25519.js";
|
|
3
|
+
import { jcsEncode } from "./jcs.js";
|
|
4
|
+
import { base64urlEncode } from "./base64url.js";
|
|
5
|
+
import { strUtf8 } from "./json.js";
|
|
6
|
+
import { resolve, coerceBounds, MAXIMUM_BOUNDS } from "./bounds.js";
|
|
7
|
+
// The request digest (spec/bap-v1.md § Signing and digest inputs, L238-264):
|
|
8
|
+
// base64url(SHA-256("BAP1-REQUEST\0" || JCS([operation, typed(cast_arguments)])))
|
|
9
|
+
// The prefix is exact ASCII including its final zero byte (REQ1-SIGNING-digest-prefix). typed()
|
|
10
|
+
// projects the tagged JSON algebra to the closed ["tag", value] JSON form before JCS, preserving the
|
|
11
|
+
// int/float distinction (REQ1-SELECTOR-semantic-identity depends on it).
|
|
12
|
+
export const REQUEST_PREFIX = new Uint8Array([
|
|
13
|
+
0x42, 0x41, 0x50, 0x31, 0x2d, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x00, // "BAP1-REQUEST\0"
|
|
14
|
+
]);
|
|
15
|
+
// typed() projection: tagged value → ["tag", value] JSON array (spec/bap-v1.md).
|
|
16
|
+
// :null → ["null"]; bool → ["boolean",v]; int → ["integer",v]; float → ["float",v];
|
|
17
|
+
// string → ["string",v]; array → ["array", [typed(v)...]]; object → ["object", {k: typed(v)...}]
|
|
18
|
+
export function typedProject(value) {
|
|
19
|
+
switch (value.t) {
|
|
20
|
+
case "null": return { t: "array", v: [{ t: "string", v: strUtf8("null") }] };
|
|
21
|
+
case "bool": return { t: "array", v: [{ t: "string", v: strUtf8("boolean") }, { t: "bool", v: value.v }] };
|
|
22
|
+
case "int": return { t: "array", v: [{ t: "string", v: strUtf8("integer") }, { t: "int", v: value.v }] };
|
|
23
|
+
case "float": return { t: "array", v: [{ t: "string", v: strUtf8("float") }, { t: "float", v: value.v }] };
|
|
24
|
+
case "string": return { t: "array", v: [{ t: "string", v: strUtf8("string") }, { t: "string", v: value.v }] };
|
|
25
|
+
case "array": return { t: "array", v: [{ t: "string", v: strUtf8("array") }, { t: "array", v: value.v.map(typedProject) }] };
|
|
26
|
+
case "object": {
|
|
27
|
+
const out = new Map();
|
|
28
|
+
for (const [k, v] of value.v)
|
|
29
|
+
out.set(k, typedProject(v));
|
|
30
|
+
return { t: "array", v: [{ t: "string", v: strUtf8("object") }, { t: "object", v: out }] };
|
|
31
|
+
}
|
|
32
|
+
default: fail("typed: unknown tag");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// request_digest(operation, cast_arguments, bounds?). operation is validated printable ASCII 1..128.
|
|
36
|
+
// Pins the v1 domain separator (BAP1-REQUEST\0); the v2 façade calls digestWithPrefix with the
|
|
37
|
+
// BAP2-REQUEST\0 separator — everything else in the digest is major-independent.
|
|
38
|
+
export function requestDigest(operation, castArguments, bounds = MAXIMUM_BOUNDS) {
|
|
39
|
+
return digestWithPrefix(REQUEST_PREFIX, operation, castArguments, bounds);
|
|
40
|
+
}
|
|
41
|
+
// The major-independent digest core: SHA-256(prefix || JCS([operation, typed(cast_arguments)])).
|
|
42
|
+
// The domain separator is the only per-major input (REQ1-SIGNING-digest-prefix; the v2 profile
|
|
43
|
+
// carries BAP2-REQUEST\0 per ADR 0028's contract-major activation).
|
|
44
|
+
export function digestWithPrefix(prefix, operation, castArguments, bounds = MAXIMUM_BOUNDS) {
|
|
45
|
+
// Cross-vendor F2: re-validate caller-supplied bounds (Bounds is a structural interface; a caller
|
|
46
|
+
// can hand-craft widening overrides that bypass boundsNew). Mirrors the reference's Bounds.coerce.
|
|
47
|
+
const b = coerceBounds(bounds);
|
|
48
|
+
// operation: 1..operation_bytes, printable ASCII.
|
|
49
|
+
const opBytes = strUtf8(operation);
|
|
50
|
+
if (opBytes.length < 1 || opBytes.length > resolve(b, "operation_bytes")) {
|
|
51
|
+
fail("request_digest: operation bound");
|
|
52
|
+
}
|
|
53
|
+
for (let i = 0; i < opBytes.length; i++) {
|
|
54
|
+
const byte = opBytes[i];
|
|
55
|
+
if (byte < 0x20 || byte > 0x7e)
|
|
56
|
+
fail("request_digest: operation printable ASCII");
|
|
57
|
+
}
|
|
58
|
+
// The projection: [operation_string, typed(cast_arguments)].
|
|
59
|
+
const projected = typedProject(castArguments);
|
|
60
|
+
const array = { t: "array", v: [{ t: "string", v: opBytes }, projected] };
|
|
61
|
+
// Per-node bounds on the TYPED projection (not the raw args): `typed` deepens/triples the tree, so
|
|
62
|
+
// the depth boundary is ~15 (not 32) and total_nodes is reachable inline. Mirrors the official
|
|
63
|
+
// Jcs.encode per-node gate (corpus_independent.mjs:1913 withinJsonBounds + countJsonNodes).
|
|
64
|
+
if (!withinTaggedBounds(array, 0, b))
|
|
65
|
+
fail("request_digest: cast_arguments bounds");
|
|
66
|
+
if (countTaggedNodes(array) > resolve(b, "total_nodes"))
|
|
67
|
+
fail("request_digest: total_nodes");
|
|
68
|
+
// JCS over the projection, enforcing jcs_bytes bound.
|
|
69
|
+
const jcs = jcsEncode(array, b);
|
|
70
|
+
if (jcs.length > resolve(b, "jcs_bytes"))
|
|
71
|
+
fail("request_digest: jcs_bytes bound");
|
|
72
|
+
const digest = sha256(prefix, jcs);
|
|
73
|
+
return digest; // raw 32 bytes
|
|
74
|
+
}
|
|
75
|
+
// Per-node-type bounds gate over the tagged algebra: a SCALAR is valid at level <= depth; a
|
|
76
|
+
// CONTAINER at level < depth (its children sit at level+1). Root value at level 0. Also enforces
|
|
77
|
+
// members/items/string-bytes/magnitude per node.
|
|
78
|
+
function withinTaggedBounds(v, level, bounds) {
|
|
79
|
+
switch (v.t) {
|
|
80
|
+
case "null":
|
|
81
|
+
case "bool":
|
|
82
|
+
return level <= resolve(bounds, "depth");
|
|
83
|
+
case "int":
|
|
84
|
+
return level <= resolve(bounds, "depth") && Math.abs(v.v) <= resolve(bounds, "integer_magnitude");
|
|
85
|
+
case "float":
|
|
86
|
+
return level <= resolve(bounds, "depth") && Number.isFinite(v.v) && Math.abs(v.v) <= resolve(bounds, "float_magnitude");
|
|
87
|
+
case "string":
|
|
88
|
+
return level <= resolve(bounds, "depth") && v.v.length <= resolve(bounds, "string_bytes");
|
|
89
|
+
case "array":
|
|
90
|
+
return level < resolve(bounds, "depth")
|
|
91
|
+
&& v.v.length <= resolve(bounds, "array_items")
|
|
92
|
+
&& v.v.every((item) => withinTaggedBounds(item, level + 1, bounds));
|
|
93
|
+
case "object":
|
|
94
|
+
return level < resolve(bounds, "depth")
|
|
95
|
+
&& v.v.size <= resolve(bounds, "object_members")
|
|
96
|
+
&& [...v.v.values()].every((val) => withinTaggedBounds(val, level + 1, bounds));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Node count: one node per value (scalar OR container); object keys are not nodes. Mirrors the
|
|
100
|
+
// official next_node! (jcs.ex:105) for the total_nodes gate on the typed projection.
|
|
101
|
+
function countTaggedNodes(v) {
|
|
102
|
+
switch (v.t) {
|
|
103
|
+
case "array": return 1 + v.v.reduce((n, item) => n + countTaggedNodes(item), 0);
|
|
104
|
+
case "object": return 1 + [...v.v.values()].reduce((n, val) => n + countTaggedNodes(val), 0);
|
|
105
|
+
default: return 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// base64url-encoded form (for comparison against proof.ba_req which is base64url). Returns
|
|
109
|
+
// Ok<string> | Err (cross-vendor #21 + the bounds-ignored note: thread bounds into the digest).
|
|
110
|
+
export function requestDigestB64url(operation, castArguments, bounds = MAXIMUM_BOUNDS) {
|
|
111
|
+
return trying(() => {
|
|
112
|
+
const raw = requestDigest(operation, castArguments, bounds);
|
|
113
|
+
return new TextDecoder().decode(base64urlEncode(raw));
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"digest.js","sourceRoot":"","sources":["../../src/digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createPublicKey } from "node:crypto";
|
|
2
|
+
export declare function _importedFingerprints(): Set<string>;
|
|
3
|
+
export declare function _resetCensus(): void;
|
|
4
|
+
export declare function importPublicKey(rawKey: Uint8Array, fingerprint: string): ReturnType<typeof createPublicKey>;
|
|
5
|
+
export declare function ed25519Verify(message: Uint8Array, signature: Uint8Array, publicKey: ReturnType<typeof createPublicKey>): boolean;
|
|
6
|
+
export declare function sha256(...parts: Uint8Array[]): Uint8Array;
|
|
7
|
+
export declare function sha256Concat(parts: Uint8Array[]): Uint8Array;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createPublicKey, verify as verifySig } from "node:crypto";
|
|
2
|
+
import { assert, fail } from "./error.js";
|
|
3
|
+
// Ed25519 verification via node:crypto (the crypto import boundary the two-boundary census tracks).
|
|
4
|
+
// Per spec/bap-v1.md § Signing and digest inputs + RFC 8032. The verifier validates the fixed 32-byte
|
|
5
|
+
// public-key and 64-byte signature encodings, then delegates Ed25519 verification to the backend. A
|
|
6
|
+
// backend rejection or exception returns exactly Invalid (REQ1-SIGNING-backend-reject).
|
|
7
|
+
// Census tracking: every key imported via importPublicKey is recorded here, so the conformance runner
|
|
8
|
+
// can assert discovery == verify-import == index public_key_fingerprints (both directions).
|
|
9
|
+
const importedFingerprints = new Set();
|
|
10
|
+
export function _importedFingerprints() {
|
|
11
|
+
return new Set(importedFingerprints);
|
|
12
|
+
}
|
|
13
|
+
export function _resetCensus() {
|
|
14
|
+
importedFingerprints.clear();
|
|
15
|
+
}
|
|
16
|
+
// Import a raw 32-byte Ed25519 public key as a node:crypto KeyObject, recording the fingerprint for the
|
|
17
|
+
// census. Returns the KeyObject. Throws InvalidError on a malformed key.
|
|
18
|
+
export function importPublicKey(rawKey, fingerprint) {
|
|
19
|
+
assert(rawKey.length === 32, "ed25519: public key must be 32 bytes");
|
|
20
|
+
// Build the SPKI DER for an Ed25519 public key: SEQUENCE { AlgId, BIT STRING <32 raw bytes> }.
|
|
21
|
+
// This matches the runner's SPKI_ED25519_PREFIX (corpus_independent.mjs:27).
|
|
22
|
+
const SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
23
|
+
const der = Buffer.concat([SPKI_PREFIX, Buffer.from(rawKey)]);
|
|
24
|
+
try {
|
|
25
|
+
const key = createPublicKey({ key: der, format: "der", type: "spki" });
|
|
26
|
+
importedFingerprints.add(fingerprint);
|
|
27
|
+
return key;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
fail("ed25519: invalid public key");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Verify an Ed25519 signature. Returns true if the signature is valid, false otherwise. Maps backend
|
|
34
|
+
// exceptions to InvalidError (REQ1-SIGNING-backend-reject).
|
|
35
|
+
export function ed25519Verify(message, signature, publicKey) {
|
|
36
|
+
assert(signature.length === 64, "ed25519: signature must be 64 bytes");
|
|
37
|
+
try {
|
|
38
|
+
return verifySig(undefined, Buffer.from(message), publicKey, Buffer.from(signature));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
fail("ed25519: backend rejected");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// SHA-256 helper (FIPS 180-4), used by thumbprints + digests.
|
|
45
|
+
import { createHash } from "node:crypto";
|
|
46
|
+
export function sha256(...parts) {
|
|
47
|
+
const h = createHash("sha256");
|
|
48
|
+
for (const p of parts)
|
|
49
|
+
h.update(Buffer.from(p));
|
|
50
|
+
return new Uint8Array(h.digest());
|
|
51
|
+
}
|
|
52
|
+
// SHA-256 over an ARRAY of chunks (no spread). Used by archive-verify, which hashes a caller-supplied
|
|
53
|
+
// chunk list that may hold up to archive_chunks (65796) entries — beyond V8's ~65534 call-argument
|
|
54
|
+
// ceiling, so the chunk list MUST be fed as an array, not spread into sha256(...chunks).
|
|
55
|
+
export function sha256Concat(parts) {
|
|
56
|
+
const h = createHash("sha256");
|
|
57
|
+
for (const p of parts)
|
|
58
|
+
h.update(Buffer.from(p));
|
|
59
|
+
return new Uint8Array(h.digest());
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ed25519.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../../src/ed25519.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE1C,oGAAoG;AACpG,sGAAsG;AACtG,oGAAoG;AACpG,wFAAwF;AAExF,sGAAsG;AACtG,4FAA4F;AAC5F,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;AAC/C,MAAM,UAAU,qBAAqB;IACnC,OAAO,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC;AACvC,CAAC;AACD,MAAM,UAAU,YAAY;IAC1B,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAC/B,CAAC;AAED,wGAAwG;AACxG,yEAAyE;AACzE,MAAM,UAAU,eAAe,CAAC,MAAkB,EAAE,WAAmB;IACrE,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,EAAE,EAAE,sCAAsC,CAAC,CAAC;IACrE,+FAA+F;IAC/F,6EAA6E;IAC7E,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACvE,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtC,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,4DAA4D;AAC5D,MAAM,UAAU,aAAa,CAC3B,OAAmB,EACnB,SAAqB,EACrB,SAA6C;IAE7C,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,qCAAqC,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,MAAM,UAAU,MAAM,CAAC,GAAG,KAAmB;IAC3C,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC;AAED,sGAAsG;AACtG,mGAAmG;AACnG,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,KAAmB;IAC9C,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class InvalidError extends Error {
|
|
2
|
+
readonly name = "InvalidError";
|
|
3
|
+
constructor(message?: string);
|
|
4
|
+
}
|
|
5
|
+
export type Result<T> = {
|
|
6
|
+
readonly ok: true;
|
|
7
|
+
readonly value: T;
|
|
8
|
+
} | {
|
|
9
|
+
readonly ok: false;
|
|
10
|
+
};
|
|
11
|
+
export declare const ok: <T>(value: T) => Result<T>;
|
|
12
|
+
export declare const err: () => Result<never>;
|
|
13
|
+
export declare function trying<T>(fn: () => T): Result<T>;
|
|
14
|
+
export declare function fail(message?: string): never;
|
|
15
|
+
export declare function assert(condition: unknown, message?: string): asserts condition;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// The single closed error value. Mirrors the Elixir {:error, :invalid} — no reason, no partial.
|
|
2
|
+
// AGENTS rule 1: verification is not authority; rule 3: fail closed. Every public façade function
|
|
3
|
+
// returns Ok<T> | Err on this. A GENUINE protocol rejection throws/returns InvalidError; a runner/SDK
|
|
4
|
+
// bug (TypeError, RangeError, uncaught library throw) is a distinct class that must NOT map to Invalid
|
|
5
|
+
// (mirrors the Node runner's InvalidError whitelist discipline, corpus_independent.mjs:88-102 — only a
|
|
6
|
+
// genuine protocol rejection maps to INVALID; everything else is a bug).
|
|
7
|
+
export class InvalidError extends Error {
|
|
8
|
+
name = "InvalidError";
|
|
9
|
+
constructor(message = "invalid") {
|
|
10
|
+
super(message);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const ok = (value) => ({ ok: true, value });
|
|
14
|
+
export const err = () => ({ ok: false });
|
|
15
|
+
// Convenience: run a thunk that may throw InvalidError; convert to Result. Any NON-Invalid throw
|
|
16
|
+
// propagates (a bug, not a verdict) — this is the whitelist.
|
|
17
|
+
export function trying(fn) {
|
|
18
|
+
try {
|
|
19
|
+
return ok(fn());
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
if (e instanceof InvalidError)
|
|
23
|
+
return err();
|
|
24
|
+
throw e;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function fail(message) {
|
|
28
|
+
throw new InvalidError(message);
|
|
29
|
+
}
|
|
30
|
+
export function assert(condition, message) {
|
|
31
|
+
if (!condition)
|
|
32
|
+
fail(message);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/error.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,kGAAkG;AAClG,sGAAsG;AACtG,uGAAuG;AACvG,uGAAuG;AACvG,yEAAyE;AACzE,MAAM,OAAO,YAAa,SAAQ,KAAK;IACnB,IAAI,GAAG,cAAc,CAAC;IACxC,YAAY,OAAO,GAAG,SAAS;QAC7B,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAKD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAI,KAAQ,EAAa,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,GAAG,GAAG,GAAkB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAExD,iGAAiG;AACjG,6DAA6D;AAC7D,MAAM,UAAU,MAAM,CAAI,EAAW;IACnC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,YAAY;YAAE,OAAO,GAAG,EAAE,CAAC;QAC5C,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAgB;IACnC,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,SAAkB,EAAE,OAAgB;IACzD,IAAI,CAAC,SAAS;QAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export interface GrantFacts {
|
|
2
|
+
readonly version: number;
|
|
3
|
+
readonly issuer: string;
|
|
4
|
+
readonly grantId: string;
|
|
5
|
+
readonly issuerKeyFingerprint: Uint8Array;
|
|
6
|
+
readonly holderThumbprint: Uint8Array;
|
|
7
|
+
readonly matchedAudience: string;
|
|
8
|
+
readonly issuedAt: number;
|
|
9
|
+
readonly notBefore: number;
|
|
10
|
+
readonly expiresAt: number;
|
|
11
|
+
readonly authorization: "not_evaluated";
|
|
12
|
+
}
|
|
13
|
+
export interface EnvelopeFacts {
|
|
14
|
+
readonly version: number;
|
|
15
|
+
readonly issuer: string;
|
|
16
|
+
readonly grantId: string;
|
|
17
|
+
readonly issuerKeyFingerprint: Uint8Array;
|
|
18
|
+
readonly holderThumbprint: Uint8Array;
|
|
19
|
+
readonly matchedAudience: string;
|
|
20
|
+
readonly grantIssuedAt: number;
|
|
21
|
+
readonly grantNotBefore: number;
|
|
22
|
+
readonly grantExpiresAt: number;
|
|
23
|
+
readonly proofId: string;
|
|
24
|
+
readonly invocationId: string;
|
|
25
|
+
readonly operation: string;
|
|
26
|
+
readonly uri: string;
|
|
27
|
+
readonly grantHash: Uint8Array;
|
|
28
|
+
readonly requestHash: Uint8Array;
|
|
29
|
+
readonly proofIssuedAt: number;
|
|
30
|
+
readonly authorization: "not_evaluated";
|
|
31
|
+
}
|
|
32
|
+
export interface ChainFacts {
|
|
33
|
+
readonly version: 1;
|
|
34
|
+
readonly chainId: string;
|
|
35
|
+
readonly firstSequence: number;
|
|
36
|
+
readonly lastSequence: number;
|
|
37
|
+
readonly rowCount: number;
|
|
38
|
+
readonly previousHash: Uint8Array;
|
|
39
|
+
readonly lastHash: Uint8Array;
|
|
40
|
+
readonly verification: "boundary_consistent";
|
|
41
|
+
readonly trust: "not_evaluated";
|
|
42
|
+
}
|
|
43
|
+
export interface AnchorFacts {
|
|
44
|
+
readonly version: 1;
|
|
45
|
+
readonly anchorId: string;
|
|
46
|
+
readonly anchoredAt: number;
|
|
47
|
+
readonly chainId: string;
|
|
48
|
+
readonly sequence: number;
|
|
49
|
+
readonly chainHash: Uint8Array;
|
|
50
|
+
readonly keyFingerprint: Uint8Array;
|
|
51
|
+
readonly verification: "signature_and_window";
|
|
52
|
+
readonly trust: "not_evaluated";
|
|
53
|
+
}
|
|
54
|
+
export interface KeyTransitionFacts {
|
|
55
|
+
readonly version: 1;
|
|
56
|
+
readonly transitionId: string;
|
|
57
|
+
readonly chainId: string;
|
|
58
|
+
readonly effectiveAt: number;
|
|
59
|
+
readonly currentKeyFingerprint: Uint8Array;
|
|
60
|
+
readonly nextKeyFingerprint: Uint8Array;
|
|
61
|
+
readonly verification: "authenticated_transition";
|
|
62
|
+
readonly trust: "not_evaluated";
|
|
63
|
+
}
|
|
64
|
+
export interface AnchoredExportFacts {
|
|
65
|
+
readonly version: 1;
|
|
66
|
+
readonly chainId: string;
|
|
67
|
+
readonly firstSequence: number;
|
|
68
|
+
readonly lastSequence: number;
|
|
69
|
+
readonly rowCount: number;
|
|
70
|
+
readonly previousHash: Uint8Array;
|
|
71
|
+
readonly lastHash: Uint8Array;
|
|
72
|
+
readonly digest: Uint8Array;
|
|
73
|
+
readonly startAnchorId: string;
|
|
74
|
+
readonly startAnchoredAt: number;
|
|
75
|
+
readonly startKeyFingerprint: Uint8Array;
|
|
76
|
+
readonly endAnchorId: string;
|
|
77
|
+
readonly endAnchoredAt: number;
|
|
78
|
+
readonly endKeyFingerprint: Uint8Array;
|
|
79
|
+
readonly transitionCount: number;
|
|
80
|
+
readonly objectVersion: string;
|
|
81
|
+
readonly verification: "anchored_export";
|
|
82
|
+
readonly trust: "not_evaluated";
|
|
83
|
+
readonly authorization: "not_evaluated";
|
|
84
|
+
}
|
|
85
|
+
export interface GrantDecoded {
|
|
86
|
+
readonly keyId: string;
|
|
87
|
+
readonly issuer: string;
|
|
88
|
+
readonly grantId: string;
|
|
89
|
+
readonly audiences: string[];
|
|
90
|
+
readonly issuedAt: number;
|
|
91
|
+
readonly notBefore: number;
|
|
92
|
+
readonly expiresAt: number;
|
|
93
|
+
readonly holderThumbprint: Uint8Array;
|
|
94
|
+
readonly verification: "not_evaluated";
|
|
95
|
+
}
|
|
96
|
+
export interface ProofDecoded {
|
|
97
|
+
readonly proofId: string;
|
|
98
|
+
readonly holderThumbprint: Uint8Array;
|
|
99
|
+
readonly verification: "not_evaluated";
|
|
100
|
+
}
|
|
101
|
+
export interface KeyLocator {
|
|
102
|
+
readonly keyId: string;
|
|
103
|
+
readonly trust: "not_evaluated";
|
|
104
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Value-bearing, redacted, non-authorizing facts (spec/bap-v1.md § Public verification contract,
|
|
2
|
+
// REQ1-VERIFY-facts-redacted, REQ1-VERIFY-facts-not-credentials). No generic encoder, no `toJSON`,
|
|
3
|
+
// no authorization/decision method (AGENTS rule 1). Grant/Envelope/Export carry
|
|
4
|
+
// `authorization: "not_evaluated"`; Chain/Anchor/Transition carry `trust: "not_evaluated"`.
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=facts.js.map
|