agent-passport-system 4.1.1 → 4.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/dist/src/adapters/oauth-id-jag/import-v1.d.ts +74 -0
- package/dist/src/adapters/oauth-id-jag/import-v1.d.ts.map +1 -0
- package/dist/src/adapters/oauth-id-jag/import-v1.js +243 -0
- package/dist/src/adapters/oauth-id-jag/import-v1.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/profiles/a2a/identity-v1.d.ts +44 -0
- package/dist/src/profiles/a2a/identity-v1.d.ts.map +1 -0
- package/dist/src/profiles/a2a/identity-v1.js +208 -0
- package/dist/src/profiles/a2a/identity-v1.js.map +1 -0
- package/dist/src/profiles/a2a/index.d.ts +2 -0
- package/dist/src/profiles/a2a/index.d.ts.map +1 -0
- package/dist/src/profiles/a2a/index.js +2 -0
- package/dist/src/profiles/a2a/index.js.map +1 -0
- package/dist/src/profiles/mcp/authorization-v1.d.ts +88 -0
- package/dist/src/profiles/mcp/authorization-v1.d.ts.map +1 -0
- package/dist/src/profiles/mcp/authorization-v1.js +215 -0
- package/dist/src/profiles/mcp/authorization-v1.js.map +1 -0
- package/dist/src/profiles/mcp/index.d.ts +2 -0
- package/dist/src/profiles/mcp/index.d.ts.map +1 -0
- package/dist/src/profiles/mcp/index.js +2 -0
- package/dist/src/profiles/mcp/index.js.map +1 -0
- package/dist/src/v2/action-reference/index.d.ts +2 -0
- package/dist/src/v2/action-reference/index.d.ts.map +1 -0
- package/dist/src/v2/action-reference/index.js +2 -0
- package/dist/src/v2/action-reference/index.js.map +1 -0
- package/dist/src/v2/action-reference/v2.d.ts +23 -0
- package/dist/src/v2/action-reference/v2.d.ts.map +1 -0
- package/dist/src/v2/action-reference/v2.js +57 -0
- package/dist/src/v2/action-reference/v2.js.map +1 -0
- package/dist/src/v2/authority-delegation/budget.d.ts +20 -0
- package/dist/src/v2/authority-delegation/budget.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/budget.js +141 -0
- package/dist/src/v2/authority-delegation/budget.js.map +1 -0
- package/dist/src/v2/authority-delegation/canonical.d.ts +12 -0
- package/dist/src/v2/authority-delegation/canonical.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/canonical.js +33 -0
- package/dist/src/v2/authority-delegation/canonical.js.map +1 -0
- package/dist/src/v2/authority-delegation/compare.d.ts +4 -0
- package/dist/src/v2/authority-delegation/compare.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/compare.js +67 -0
- package/dist/src/v2/authority-delegation/compare.js.map +1 -0
- package/dist/src/v2/authority-delegation/index.d.ts +10 -0
- package/dist/src/v2/authority-delegation/index.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/index.js +12 -0
- package/dist/src/v2/authority-delegation/index.js.map +1 -0
- package/dist/src/v2/authority-delegation/issue.d.ts +10 -0
- package/dist/src/v2/authority-delegation/issue.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/issue.js +52 -0
- package/dist/src/v2/authority-delegation/issue.js.map +1 -0
- package/dist/src/v2/authority-delegation/parse.d.ts +4 -0
- package/dist/src/v2/authority-delegation/parse.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/parse.js +96 -0
- package/dist/src/v2/authority-delegation/parse.js.map +1 -0
- package/dist/src/v2/authority-delegation/schema.d.ts +7 -0
- package/dist/src/v2/authority-delegation/schema.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/schema.js +177 -0
- package/dist/src/v2/authority-delegation/schema.js.map +1 -0
- package/dist/src/v2/authority-delegation/scope.d.ts +6 -0
- package/dist/src/v2/authority-delegation/scope.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/scope.js +50 -0
- package/dist/src/v2/authority-delegation/scope.js.map +1 -0
- package/dist/src/v2/authority-delegation/types.d.ts +98 -0
- package/dist/src/v2/authority-delegation/types.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/types.js +10 -0
- package/dist/src/v2/authority-delegation/types.js.map +1 -0
- package/dist/src/v2/authority-delegation/verify.d.ts +5 -0
- package/dist/src/v2/authority-delegation/verify.d.ts.map +1 -0
- package/dist/src/v2/authority-delegation/verify.js +124 -0
- package/dist/src/v2/authority-delegation/verify.js.map +1 -0
- package/dist/src/v2/identity-binding/did-aps.d.ts +12 -0
- package/dist/src/v2/identity-binding/did-aps.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/did-aps.js +53 -0
- package/dist/src/v2/identity-binding/did-aps.js.map +1 -0
- package/dist/src/v2/identity-binding/index.d.ts +6 -0
- package/dist/src/v2/identity-binding/index.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/index.js +6 -0
- package/dist/src/v2/identity-binding/index.js.map +1 -0
- package/dist/src/v2/identity-binding/passport.d.ts +18 -0
- package/dist/src/v2/identity-binding/passport.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/passport.js +144 -0
- package/dist/src/v2/identity-binding/passport.js.map +1 -0
- package/dist/src/v2/identity-binding/principal-binding.d.ts +20 -0
- package/dist/src/v2/identity-binding/principal-binding.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/principal-binding.js +128 -0
- package/dist/src/v2/identity-binding/principal-binding.js.map +1 -0
- package/dist/src/v2/identity-binding/revocation.d.ts +12 -0
- package/dist/src/v2/identity-binding/revocation.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/revocation.js +97 -0
- package/dist/src/v2/identity-binding/revocation.js.map +1 -0
- package/dist/src/v2/identity-binding/types.d.ts +72 -0
- package/dist/src/v2/identity-binding/types.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/types.js +4 -0
- package/dist/src/v2/identity-binding/types.js.map +1 -0
- package/dist/src/v2/identity-binding/validation.d.ts +9 -0
- package/dist/src/v2/identity-binding/validation.d.ts.map +1 -0
- package/dist/src/v2/identity-binding/validation.js +104 -0
- package/dist/src/v2/identity-binding/validation.js.map +1 -0
- package/dist/src/v2/receipt-core/decision-ref.d.ts +23 -0
- package/dist/src/v2/receipt-core/decision-ref.d.ts.map +1 -0
- package/dist/src/v2/receipt-core/decision-ref.js +75 -0
- package/dist/src/v2/receipt-core/decision-ref.js.map +1 -0
- package/dist/src/v2/receipt-core/jcs.d.ts +15 -0
- package/dist/src/v2/receipt-core/jcs.d.ts.map +1 -0
- package/dist/src/v2/receipt-core/jcs.js +198 -0
- package/dist/src/v2/receipt-core/jcs.js.map +1 -0
- package/dist/src/v2/receipt-core/receipt.d.ts +21 -0
- package/dist/src/v2/receipt-core/receipt.d.ts.map +1 -0
- package/dist/src/v2/receipt-core/receipt.js +132 -0
- package/dist/src/v2/receipt-core/receipt.js.map +1 -0
- package/dist/src/v2/receipt-core/supporting-record.d.ts +55 -0
- package/dist/src/v2/receipt-core/supporting-record.d.ts.map +1 -0
- package/dist/src/v2/receipt-core/supporting-record.js +243 -0
- package/dist/src/v2/receipt-core/supporting-record.js.map +1 -0
- package/dist/src/v2/receipt-core/types.d.ts +94 -0
- package/dist/src/v2/receipt-core/types.d.ts.map +1 -0
- package/dist/src/v2/receipt-core/types.js +4 -0
- package/dist/src/v2/receipt-core/types.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { validateAuthorityDelegationShape } from './schema.js';
|
|
4
|
+
const MAX_WIRE_BYTES = 1_048_576;
|
|
5
|
+
/**
|
|
6
|
+
* JSON.parse silently keeps the last occurrence of a duplicate member. RFC
|
|
7
|
+
* 8785 operates on I-JSON, so scan the already-syntax-checked source and reject
|
|
8
|
+
* repeated names at every object depth before accepting a signed record.
|
|
9
|
+
*/
|
|
10
|
+
function rejectDuplicateMembers(source) {
|
|
11
|
+
let cursor = 0;
|
|
12
|
+
const skipWhitespace = () => {
|
|
13
|
+
while (cursor < source.length && /[\u0009\u000a\u000d\u0020]/.test(source[cursor]))
|
|
14
|
+
cursor++;
|
|
15
|
+
};
|
|
16
|
+
const readString = () => {
|
|
17
|
+
const start = cursor;
|
|
18
|
+
cursor++; // opening quote; whole-document JSON.parse already proved syntax
|
|
19
|
+
while (cursor < source.length) {
|
|
20
|
+
if (source[cursor] === '\\') {
|
|
21
|
+
cursor += 2;
|
|
22
|
+
}
|
|
23
|
+
else if (source[cursor++] === '"') {
|
|
24
|
+
return JSON.parse(source.slice(start, cursor));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
throw new SyntaxError('unterminated JSON string');
|
|
28
|
+
};
|
|
29
|
+
const value = () => {
|
|
30
|
+
skipWhitespace();
|
|
31
|
+
const first = source[cursor];
|
|
32
|
+
if (first === '{') {
|
|
33
|
+
cursor++;
|
|
34
|
+
skipWhitespace();
|
|
35
|
+
const names = new Set();
|
|
36
|
+
if (source[cursor] === '}') {
|
|
37
|
+
cursor++;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
while (cursor < source.length) {
|
|
41
|
+
const name = readString();
|
|
42
|
+
if (names.has(name))
|
|
43
|
+
throw new SyntaxError('duplicate JSON object member');
|
|
44
|
+
names.add(name);
|
|
45
|
+
skipWhitespace();
|
|
46
|
+
cursor++; // colon
|
|
47
|
+
value();
|
|
48
|
+
skipWhitespace();
|
|
49
|
+
if (source[cursor++] === '}')
|
|
50
|
+
return;
|
|
51
|
+
skipWhitespace(); // comma was consumed
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (first === '[') {
|
|
55
|
+
cursor++;
|
|
56
|
+
skipWhitespace();
|
|
57
|
+
if (source[cursor] === ']') {
|
|
58
|
+
cursor++;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
while (cursor < source.length) {
|
|
62
|
+
value();
|
|
63
|
+
skipWhitespace();
|
|
64
|
+
if (source[cursor++] === ']')
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (first === '"') {
|
|
69
|
+
readString();
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const start = cursor;
|
|
73
|
+
while (cursor < source.length && !/[\u0009\u000a\u000d\u0020,}\]]/.test(source[cursor]))
|
|
74
|
+
cursor++;
|
|
75
|
+
const token = source.slice(start, cursor);
|
|
76
|
+
if (/^[-0-9]/.test(token) && !/^-?(0|[1-9][0-9]*)$/.test(token)) {
|
|
77
|
+
throw new SyntaxError('non-integer JSON numbers are not permitted');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
value();
|
|
82
|
+
}
|
|
83
|
+
/** Strict untrusted-wire entry point: valid JSON, I-JSON names, and closed v1 schema. */
|
|
84
|
+
export function parseAuthorityDelegationJson(source) {
|
|
85
|
+
if (typeof source !== 'string' || Buffer.byteLength(source, 'utf8') > MAX_WIRE_BYTES) {
|
|
86
|
+
throw new TypeError('authority delegation JSON must be a string no larger than 1 MiB');
|
|
87
|
+
}
|
|
88
|
+
const decoded = JSON.parse(source);
|
|
89
|
+
rejectDuplicateMembers(source);
|
|
90
|
+
const failures = validateAuthorityDelegationShape(decoded);
|
|
91
|
+
if (failures.length > 0) {
|
|
92
|
+
throw new TypeError(`authority delegation wire invalid: ${failures.map(item => item.code).join(', ')}`);
|
|
93
|
+
}
|
|
94
|
+
return decoded;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AuthorityDelegationV1, AuthorityFailure } from './types.js';
|
|
2
|
+
export declare function isCanonicalTimestamp(value: unknown): value is string;
|
|
3
|
+
export declare function isCanonicalQuantity(value: unknown): value is string;
|
|
4
|
+
/** Closed-schema and canonical-value validation for an in-memory decoded record. */
|
|
5
|
+
export declare function validateAuthorityDelegationShape(value: unknown): AuthorityFailure[];
|
|
6
|
+
export declare function isAuthorityDelegationV1(value: unknown): value is AuthorityDelegationV1;
|
|
7
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/schema.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAmCzE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAIpE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAGnE;AAMD,oFAAoF;AACpF,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CA4GnF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAEtF"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { grantsAreCanonical } from './scope.js';
|
|
4
|
+
import { AUTHORITY_DELEGATION_RECORD_TYPE, AUTHORITY_DELEGATION_VERSION, REPUTATION_PROFILE_V1, REVERSIBILITY_PROFILE_V1, SCOPE_PROFILE_V1, VALUES_PROFILE_V1, } from './types.js';
|
|
5
|
+
const ID = /^sha256:[0-9a-f]{64}$/;
|
|
6
|
+
const HEX_32 = /^[0-9a-f]{32}$/;
|
|
7
|
+
const HEX_128 = /^[0-9a-f]{128}$/;
|
|
8
|
+
const DECIMAL = /^(0|[1-9][0-9]*)$/;
|
|
9
|
+
const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
10
|
+
const MAX_QUANTITY = 9223372036854775807n;
|
|
11
|
+
const MILLIS_UTC = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
12
|
+
function record(value) {
|
|
13
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
14
|
+
? value
|
|
15
|
+
: null;
|
|
16
|
+
}
|
|
17
|
+
function exactKeys(value, expected) {
|
|
18
|
+
const actual = Object.keys(value).sort();
|
|
19
|
+
const wanted = [...expected].sort();
|
|
20
|
+
return actual.length === wanted.length && actual.every((key, i) => key === wanted[i]);
|
|
21
|
+
}
|
|
22
|
+
function wellFormedUnicode(value) {
|
|
23
|
+
for (let i = 0; i < value.length; i++) {
|
|
24
|
+
const unit = value.charCodeAt(i);
|
|
25
|
+
if (unit >= 0xd800 && unit <= 0xdbff) {
|
|
26
|
+
const next = value.charCodeAt(++i);
|
|
27
|
+
if (!(next >= 0xdc00 && next <= 0xdfff))
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
else if (unit >= 0xdc00 && unit <= 0xdfff) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
export function isCanonicalTimestamp(value) {
|
|
37
|
+
if (typeof value !== 'string' || !MILLIS_UTC.test(value) || value.startsWith('0000-'))
|
|
38
|
+
return false;
|
|
39
|
+
const parsed = new Date(value);
|
|
40
|
+
return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;
|
|
41
|
+
}
|
|
42
|
+
export function isCanonicalQuantity(value) {
|
|
43
|
+
if (typeof value !== 'string' || !DECIMAL.test(value))
|
|
44
|
+
return false;
|
|
45
|
+
try {
|
|
46
|
+
return BigInt(value) <= MAX_QUANTITY;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function failure(code, message) {
|
|
53
|
+
return { code, message };
|
|
54
|
+
}
|
|
55
|
+
/** Closed-schema and canonical-value validation for an in-memory decoded record. */
|
|
56
|
+
export function validateAuthorityDelegationShape(value) {
|
|
57
|
+
const failures = [];
|
|
58
|
+
const top = record(value);
|
|
59
|
+
if (!top || !exactKeys(top, [
|
|
60
|
+
'record_type', 'version', 'delegation_id', 'parent_delegation_id', 'issuer',
|
|
61
|
+
'subject', 'verification_method', 'issued_at', 'nonce', 'authority', 'signature',
|
|
62
|
+
]))
|
|
63
|
+
return [failure('SCHEMA_INVALID', 'delegation must be an exact closed v1 object')];
|
|
64
|
+
if (top.record_type !== AUTHORITY_DELEGATION_RECORD_TYPE || top.version !== AUTHORITY_DELEGATION_VERSION) {
|
|
65
|
+
failures.push(failure('UNSUPPORTED_VERSION', 'unsupported authority-delegation record_type or version'));
|
|
66
|
+
}
|
|
67
|
+
if (typeof top.delegation_id !== 'string' || !ID.test(top.delegation_id)) {
|
|
68
|
+
failures.push(failure('SCHEMA_INVALID', 'delegation_id must be sha256:<64 lowercase hex>'));
|
|
69
|
+
}
|
|
70
|
+
if (top.parent_delegation_id !== null &&
|
|
71
|
+
(typeof top.parent_delegation_id !== 'string' || !ID.test(top.parent_delegation_id))) {
|
|
72
|
+
failures.push(failure('SCHEMA_INVALID', 'parent_delegation_id must be null or a delegation digest'));
|
|
73
|
+
}
|
|
74
|
+
for (const key of ['issuer', 'subject', 'verification_method']) {
|
|
75
|
+
const item = top[key];
|
|
76
|
+
if (typeof item !== 'string' || item.length === 0 || Buffer.byteLength(item, 'utf8') > 1024 || !wellFormedUnicode(item)) {
|
|
77
|
+
failures.push(failure('SCHEMA_INVALID', `${key} must be a non-empty well-formed Unicode string`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!isCanonicalTimestamp(top.issued_at))
|
|
81
|
+
failures.push(failure('NONCANONICAL_VALUE', 'issued_at must be canonical UTC milliseconds'));
|
|
82
|
+
if (typeof top.nonce !== 'string' || !HEX_32.test(top.nonce))
|
|
83
|
+
failures.push(failure('NONCANONICAL_VALUE', 'nonce must be 32 lowercase hex characters'));
|
|
84
|
+
if (typeof top.signature !== 'string' || !HEX_128.test(top.signature))
|
|
85
|
+
failures.push(failure('SCHEMA_INVALID', 'signature must be 128 lowercase hex characters'));
|
|
86
|
+
const authority = record(top.authority);
|
|
87
|
+
if (!authority || !exactKeys(authority, ['scope', 'spend', 'depth', 'time', 'reputation', 'values', 'reversibility'])) {
|
|
88
|
+
failures.push(failure('SCHEMA_INVALID', 'authority must carry exactly all seven facets'));
|
|
89
|
+
return failures;
|
|
90
|
+
}
|
|
91
|
+
const scope = record(authority.scope);
|
|
92
|
+
if (!scope || !exactKeys(scope, ['profile', 'grants']) || typeof scope.profile !== 'string' ||
|
|
93
|
+
!IDENTIFIER.test(scope.profile) || !Array.isArray(scope.grants) ||
|
|
94
|
+
!scope.grants.every(item => typeof item === 'string')) {
|
|
95
|
+
failures.push(failure('SCHEMA_INVALID', 'scope must contain profile and grants'));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
if (scope.profile !== SCOPE_PROFILE_V1)
|
|
99
|
+
failures.push(failure('UNSUPPORTED_PROFILE', 'unsupported scope profile'));
|
|
100
|
+
if (!grantsAreCanonical(scope.grants))
|
|
101
|
+
failures.push(failure('NONCANONICAL_VALUE', 'scope grants must be valid, sorted, unique, and irredundant'));
|
|
102
|
+
}
|
|
103
|
+
const spend = record(authority.spend);
|
|
104
|
+
if (!spend || typeof spend.mode !== 'string') {
|
|
105
|
+
failures.push(failure('SCHEMA_INVALID', 'spend must be a tagged object'));
|
|
106
|
+
}
|
|
107
|
+
else if (spend.mode === 'unbounded') {
|
|
108
|
+
if (!exactKeys(spend, ['mode']))
|
|
109
|
+
failures.push(failure('SCHEMA_INVALID', 'unbounded spend has no other fields'));
|
|
110
|
+
}
|
|
111
|
+
else if (spend.mode === 'bounded') {
|
|
112
|
+
if (!exactKeys(spend, ['mode', 'unit', 'per_action', 'cumulative']) ||
|
|
113
|
+
typeof spend.unit !== 'string' || !IDENTIFIER.test(spend.unit) ||
|
|
114
|
+
!isCanonicalQuantity(spend.per_action) || !isCanonicalQuantity(spend.cumulative)) {
|
|
115
|
+
failures.push(failure('NONCANONICAL_VALUE', 'bounded spend fields are malformed'));
|
|
116
|
+
}
|
|
117
|
+
else if (BigInt(spend.per_action) > BigInt(spend.cumulative)) {
|
|
118
|
+
failures.push(failure('SCHEMA_INVALID', 'spend per_action cannot exceed cumulative'));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
failures.push(failure('SCHEMA_INVALID', 'unknown spend mode'));
|
|
123
|
+
const depth = record(authority.depth);
|
|
124
|
+
if (!depth || !exactKeys(depth, ['remaining']) || !Number.isInteger(depth.remaining) ||
|
|
125
|
+
depth.remaining < 0 || depth.remaining > 255) {
|
|
126
|
+
failures.push(failure('SCHEMA_INVALID', 'depth.remaining must be an integer from 0 through 255'));
|
|
127
|
+
}
|
|
128
|
+
const time = record(authority.time);
|
|
129
|
+
if (!time || !exactKeys(time, ['not_before', 'not_after']) ||
|
|
130
|
+
!isCanonicalTimestamp(time.not_before) || !isCanonicalTimestamp(time.not_after)) {
|
|
131
|
+
failures.push(failure('NONCANONICAL_VALUE', 'time bounds must be canonical UTC milliseconds'));
|
|
132
|
+
}
|
|
133
|
+
else if (Date.parse(time.not_before) >= Date.parse(time.not_after)) {
|
|
134
|
+
failures.push(failure('SCHEMA_INVALID', 'time window must be non-empty'));
|
|
135
|
+
}
|
|
136
|
+
else if (isCanonicalTimestamp(top.issued_at) && Date.parse(time.not_before) < Date.parse(top.issued_at)) {
|
|
137
|
+
failures.push(failure('SCHEMA_INVALID', 'time.not_before cannot predate issued_at'));
|
|
138
|
+
}
|
|
139
|
+
const reputation = record(authority.reputation);
|
|
140
|
+
if (!reputation || !exactKeys(reputation, ['profile', 'ceiling']) ||
|
|
141
|
+
typeof reputation.profile !== 'string' || !IDENTIFIER.test(reputation.profile) ||
|
|
142
|
+
!Number.isInteger(reputation.ceiling) || reputation.ceiling < 0 ||
|
|
143
|
+
reputation.ceiling > 100) {
|
|
144
|
+
failures.push(failure('SCHEMA_INVALID', 'reputation ceiling must be an integer from 0 through 100'));
|
|
145
|
+
}
|
|
146
|
+
else if (reputation.profile !== REPUTATION_PROFILE_V1) {
|
|
147
|
+
failures.push(failure('UNSUPPORTED_PROFILE', 'unsupported reputation profile'));
|
|
148
|
+
}
|
|
149
|
+
const values = record(authority.values);
|
|
150
|
+
if (!values || !exactKeys(values, ['profile', 'required']) || typeof values.profile !== 'string' ||
|
|
151
|
+
!IDENTIFIER.test(values.profile) || !Array.isArray(values.required) ||
|
|
152
|
+
!values.required.every(item => typeof item === 'string' && IDENTIFIER.test(item))) {
|
|
153
|
+
failures.push(failure('SCHEMA_INVALID', 'values.required must contain valid identifiers'));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
if (values.profile !== VALUES_PROFILE_V1)
|
|
157
|
+
failures.push(failure('UNSUPPORTED_PROFILE', 'unsupported values profile'));
|
|
158
|
+
const required = values.required;
|
|
159
|
+
if (required.some((item, i) => i > 0 && required[i - 1] >= item)) {
|
|
160
|
+
failures.push(failure('NONCANONICAL_VALUE', 'values.required must be sorted and unique'));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const reversibility = record(authority.reversibility);
|
|
164
|
+
if (!reversibility || !exactKeys(reversibility, ['profile', 'ceiling']) ||
|
|
165
|
+
typeof reversibility.profile !== 'string' || !IDENTIFIER.test(reversibility.profile) ||
|
|
166
|
+
!['tentative', 'compensable', 'irreversible'].includes(String(reversibility.ceiling))) {
|
|
167
|
+
failures.push(failure('SCHEMA_INVALID', 'reversibility facet is malformed'));
|
|
168
|
+
}
|
|
169
|
+
else if (reversibility.profile !== REVERSIBILITY_PROFILE_V1) {
|
|
170
|
+
failures.push(failure('UNSUPPORTED_PROFILE', 'unsupported reversibility profile'));
|
|
171
|
+
}
|
|
172
|
+
return failures;
|
|
173
|
+
}
|
|
174
|
+
export function isAuthorityDelegationV1(value) {
|
|
175
|
+
return validateAuthorityDelegationShape(value).length === 0;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function isValidScopeGrant(grant: string): boolean;
|
|
2
|
+
/** Exact grants cover only themselves. A terminal :* grant covers its prefix and descendants. */
|
|
3
|
+
export declare function scopeGrantCovers(parent: string, child: string): boolean;
|
|
4
|
+
export declare function grantsAreCanonical(grants: readonly string[]): boolean;
|
|
5
|
+
export declare function scopeNarrows(parent: readonly string[], child: readonly string[]): boolean;
|
|
6
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/scope.ts"],"names":[],"mappings":"AAKA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASxD;AAED,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQvE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAYrE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAEzF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
const SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
4
|
+
export function isValidScopeGrant(grant) {
|
|
5
|
+
if (grant === '*')
|
|
6
|
+
return true;
|
|
7
|
+
if (typeof grant !== 'string' || grant.length === 0 || grant.length > 255)
|
|
8
|
+
return false;
|
|
9
|
+
const parts = grant.split(':');
|
|
10
|
+
if (parts.length > 16)
|
|
11
|
+
return false;
|
|
12
|
+
const wildcard = parts.at(-1) === '*';
|
|
13
|
+
if (wildcard)
|
|
14
|
+
parts.pop();
|
|
15
|
+
if (parts.length === 0 || parts.some(part => !SEGMENT.test(part)))
|
|
16
|
+
return false;
|
|
17
|
+
return !parts.includes('*');
|
|
18
|
+
}
|
|
19
|
+
/** Exact grants cover only themselves. A terminal :* grant covers its prefix and descendants. */
|
|
20
|
+
export function scopeGrantCovers(parent, child) {
|
|
21
|
+
if (parent === '*')
|
|
22
|
+
return true;
|
|
23
|
+
if (parent.endsWith(':*')) {
|
|
24
|
+
const prefix = parent.slice(0, -2);
|
|
25
|
+
const childPrefix = child.endsWith(':*') ? child.slice(0, -2) : child;
|
|
26
|
+
return childPrefix === prefix || childPrefix.startsWith(prefix + ':');
|
|
27
|
+
}
|
|
28
|
+
return parent === child;
|
|
29
|
+
}
|
|
30
|
+
export function grantsAreCanonical(grants) {
|
|
31
|
+
if (!Array.isArray(grants))
|
|
32
|
+
return false;
|
|
33
|
+
for (let i = 0; i < grants.length; i++) {
|
|
34
|
+
const grant = grants[i];
|
|
35
|
+
if (!isValidScopeGrant(grant))
|
|
36
|
+
return false;
|
|
37
|
+
if (i > 0 && grants[i - 1] >= grant)
|
|
38
|
+
return false;
|
|
39
|
+
// A canonical set is an antichain: no entry is redundant under another entry.
|
|
40
|
+
for (let j = 0; j < grants.length; j++) {
|
|
41
|
+
if (i !== j && scopeGrantCovers(grants[j], grant))
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
export function scopeNarrows(parent, child) {
|
|
48
|
+
return child.every(grant => parent.some(parentGrant => scopeGrantCovers(parentGrant, grant)));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/scope.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,sCAAsC;AAEtC,MAAM,OAAO,GAAG,mCAAmC,CAAA;AAEnD,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAA;IACvF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAA;IACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAA;IACrC,IAAI,QAAQ;QAAE,KAAK,CAAC,GAAG,EAAE,CAAA;IACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IAC/E,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AAC7B,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,KAAa;IAC5D,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IAC/B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAClC,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QACrE,OAAO,WAAW,KAAK,MAAM,IAAI,WAAW,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,CAAA;IACvE,CAAC;IACD,OAAO,MAAM,KAAK,KAAK,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAyB;IAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QAC3C,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;QACjD,8EAA8E;QAC9E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;QACjE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAyB,EAAE,KAAwB;IAC9E,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;AAC/F,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** First complete APS authority-delegation wire profile. */
|
|
2
|
+
export declare const AUTHORITY_DELEGATION_RECORD_TYPE: 'aps:authority-delegation:v1';
|
|
3
|
+
export declare const AUTHORITY_DELEGATION_VERSION: '1.0';
|
|
4
|
+
export declare const SCOPE_PROFILE_V1: 'aps-hierarchical-v1';
|
|
5
|
+
export declare const REPUTATION_PROFILE_V1: 'aps-score-0-100-v1';
|
|
6
|
+
export declare const VALUES_PROFILE_V1: 'aps-values-identifiers-v1';
|
|
7
|
+
export declare const REVERSIBILITY_PROFILE_V1: 'aps-tci-v1';
|
|
8
|
+
export interface ScopeFacetV1 {
|
|
9
|
+
profile: typeof SCOPE_PROFILE_V1;
|
|
10
|
+
grants: string[];
|
|
11
|
+
}
|
|
12
|
+
export type SpendFacetV1 = {
|
|
13
|
+
mode: 'unbounded';
|
|
14
|
+
} | {
|
|
15
|
+
mode: 'bounded';
|
|
16
|
+
/** Opaque, exact-match accounting unit, for example iso4217:USD:minor. */
|
|
17
|
+
unit: string;
|
|
18
|
+
/** Canonical unsigned decimal integer. */
|
|
19
|
+
per_action: string;
|
|
20
|
+
/** Canonical unsigned decimal integer applying to the whole delegation subtree. */
|
|
21
|
+
cumulative: string;
|
|
22
|
+
};
|
|
23
|
+
export interface DepthFacetV1 {
|
|
24
|
+
/** Number of further delegation hops the subject may create. */
|
|
25
|
+
remaining: number;
|
|
26
|
+
}
|
|
27
|
+
export interface TimeFacetV1 {
|
|
28
|
+
not_before: string;
|
|
29
|
+
not_after: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ReputationFacetV1 {
|
|
32
|
+
profile: typeof REPUTATION_PROFILE_V1;
|
|
33
|
+
ceiling: number;
|
|
34
|
+
}
|
|
35
|
+
export interface ValuesFacetV1 {
|
|
36
|
+
profile: typeof VALUES_PROFILE_V1;
|
|
37
|
+
required: string[];
|
|
38
|
+
}
|
|
39
|
+
export type ReversibilityClassV1 = 'tentative' | 'compensable' | 'irreversible';
|
|
40
|
+
export interface ReversibilityFacetV1 {
|
|
41
|
+
profile: typeof REVERSIBILITY_PROFILE_V1;
|
|
42
|
+
ceiling: ReversibilityClassV1;
|
|
43
|
+
}
|
|
44
|
+
export interface AuthorityVectorV1 {
|
|
45
|
+
scope: ScopeFacetV1;
|
|
46
|
+
spend: SpendFacetV1;
|
|
47
|
+
depth: DepthFacetV1;
|
|
48
|
+
time: TimeFacetV1;
|
|
49
|
+
reputation: ReputationFacetV1;
|
|
50
|
+
values: ValuesFacetV1;
|
|
51
|
+
reversibility: ReversibilityFacetV1;
|
|
52
|
+
}
|
|
53
|
+
export interface AuthorityDelegationBodyV1 {
|
|
54
|
+
record_type: typeof AUTHORITY_DELEGATION_RECORD_TYPE;
|
|
55
|
+
version: typeof AUTHORITY_DELEGATION_VERSION;
|
|
56
|
+
/** Null only for a trust-policy-selected root. */
|
|
57
|
+
parent_delegation_id: string | null;
|
|
58
|
+
issuer: string;
|
|
59
|
+
subject: string;
|
|
60
|
+
verification_method: string;
|
|
61
|
+
issued_at: string;
|
|
62
|
+
/** 16 random bytes encoded as 32 lowercase hexadecimal characters. */
|
|
63
|
+
nonce: string;
|
|
64
|
+
authority: AuthorityVectorV1;
|
|
65
|
+
}
|
|
66
|
+
export interface AuthorityDelegationV1 extends AuthorityDelegationBodyV1 {
|
|
67
|
+
delegation_id: string;
|
|
68
|
+
/** Raw 64-byte Ed25519 signature encoded as 128 lowercase hexadecimal characters. */
|
|
69
|
+
signature: string;
|
|
70
|
+
}
|
|
71
|
+
export type AuthorityFailureCode = 'SCHEMA_INVALID' | 'UNSUPPORTED_VERSION' | 'UNSUPPORTED_PROFILE' | 'NONCANONICAL_VALUE' | 'ID_MISMATCH' | 'KEY_RESOLUTION_FAILED' | 'SIGNATURE_INVALID' | 'ROOT_UNTRUSTED' | 'CHAIN_DUPLICATE_ID' | 'PARENT_MISMATCH' | 'CHAIN_CONTINUITY' | 'ISSUED_AT_OUTSIDE_PARENT' | 'SCOPE_WIDENING' | 'SPEND_WIDENING' | 'SPEND_UNIT_CHANGE' | 'DEPTH_EXHAUSTED' | 'DEPTH_WIDENING' | 'TIME_WIDENING' | 'REPUTATION_WIDENING' | 'VALUES_WEAKENING' | 'REVERSIBILITY_WIDENING' | 'NOT_YET_VALID' | 'EXPIRED' | 'REVOKED' | 'REVOCATION_UNKNOWN';
|
|
72
|
+
export interface AuthorityFailure {
|
|
73
|
+
code: AuthorityFailureCode;
|
|
74
|
+
message: string;
|
|
75
|
+
index?: number;
|
|
76
|
+
facet?: keyof AuthorityVectorV1;
|
|
77
|
+
}
|
|
78
|
+
export type AuthorityValidationState = 'valid' | 'invalid' | 'indeterminate' | 'unsupported';
|
|
79
|
+
export interface AuthorityValidationResult {
|
|
80
|
+
state: AuthorityValidationState;
|
|
81
|
+
valid: boolean;
|
|
82
|
+
failures: AuthorityFailure[];
|
|
83
|
+
}
|
|
84
|
+
export type VerificationKeyResolver = (issuer: string, verificationMethod: string, issuedAt: string) => string | null;
|
|
85
|
+
export type RevocationResolution = 'active' | 'revoked' | 'unknown';
|
|
86
|
+
export interface AuthorityChainVerificationOptions {
|
|
87
|
+
now: string;
|
|
88
|
+
resolveVerificationKey: VerificationKeyResolver;
|
|
89
|
+
trustRoot: (root: AuthorityDelegationV1) => boolean;
|
|
90
|
+
resolveRevocation: (delegation: AuthorityDelegationV1) => RevocationResolution;
|
|
91
|
+
}
|
|
92
|
+
export type BudgetReservationState = 'reserved' | 'dispatched' | 'committed' | 'cancelled';
|
|
93
|
+
export interface BudgetOperationResult {
|
|
94
|
+
ok: boolean;
|
|
95
|
+
code: 'RESERVED' | 'DISPATCHED' | 'COMMITTED' | 'CANCELLED' | 'IDEMPOTENT' | 'CONFLICT' | 'UNIT_MISMATCH' | 'PER_ACTION_EXCEEDED' | 'CUMULATIVE_EXCEEDED' | 'NOT_FOUND' | 'INVALID_STATE';
|
|
96
|
+
state?: BudgetReservationState;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/** First complete APS authority-delegation wire profile. */
|
|
4
|
+
export const AUTHORITY_DELEGATION_RECORD_TYPE = 'aps:authority-delegation:v1';
|
|
5
|
+
export const AUTHORITY_DELEGATION_VERSION = '1.0';
|
|
6
|
+
export const SCOPE_PROFILE_V1 = 'aps-hierarchical-v1';
|
|
7
|
+
export const REPUTATION_PROFILE_V1 = 'aps-score-0-100-v1';
|
|
8
|
+
export const VALUES_PROFILE_V1 = 'aps-values-identifiers-v1';
|
|
9
|
+
export const REVERSIBILITY_PROFILE_V1 = 'aps-tci-v1';
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/types.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,sCAAsC;AAEtC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,gCAAgC,GAAG,6BAAsC,CAAA;AACtF,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAc,CAAA;AAE1D,MAAM,CAAC,MAAM,gBAAgB,GAAG,qBAA8B,CAAA;AAC9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,oBAA6B,CAAA;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,2BAAoC,CAAA;AACrE,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAqB,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AuthorityChainVerificationOptions, AuthorityValidationResult } from './types.js';
|
|
2
|
+
/** Full root-to-leaf structural, cryptographic, temporal, and revocation validation. */
|
|
3
|
+
export declare function verifyAuthorityDelegationChain(rawChain: readonly unknown[], options: AuthorityChainVerificationOptions): AuthorityValidationResult;
|
|
4
|
+
export declare function verifyAuthorityDelegation(delegation: unknown, options: AuthorityChainVerificationOptions): AuthorityValidationResult;
|
|
5
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../../src/v2/authority-delegation/verify.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,iCAAiC,EAGjC,yBAAyB,EAE1B,MAAM,YAAY,CAAA;AAUnB,wFAAwF;AACxF,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,OAAO,EAAE,iCAAiC,GACzC,yBAAyB,CA8G3B;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,iCAAiC,GACzC,yBAAyB,CAE3B"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { authorityDelegationBody, computeAuthorityDelegationId, verifyAuthorityDelegationSignature, } from './canonical.js';
|
|
4
|
+
import { compareAuthority } from './compare.js';
|
|
5
|
+
import { isCanonicalTimestamp, validateAuthorityDelegationShape } from './schema.js';
|
|
6
|
+
function result(state, failures) {
|
|
7
|
+
return { state, valid: state === 'valid', failures };
|
|
8
|
+
}
|
|
9
|
+
function indexed(failure, index) {
|
|
10
|
+
return { ...failure, index };
|
|
11
|
+
}
|
|
12
|
+
/** Full root-to-leaf structural, cryptographic, temporal, and revocation validation. */
|
|
13
|
+
export function verifyAuthorityDelegationChain(rawChain, options) {
|
|
14
|
+
if (!Array.isArray(rawChain) || rawChain.length === 0 || rawChain.length > 256) {
|
|
15
|
+
return result('invalid', [{ code: 'SCHEMA_INVALID', message: 'chain must contain 1 through 256 records' }]);
|
|
16
|
+
}
|
|
17
|
+
if (!options || !isCanonicalTimestamp(options.now)) {
|
|
18
|
+
return result('invalid', [{ code: 'NONCANONICAL_VALUE', message: 'verification clock must be canonical UTC milliseconds' }]);
|
|
19
|
+
}
|
|
20
|
+
const now = Date.parse(options.now);
|
|
21
|
+
const chain = [];
|
|
22
|
+
for (let i = 0; i < rawChain.length; i++) {
|
|
23
|
+
const failures = validateAuthorityDelegationShape(rawChain[i]).map(item => indexed(item, i));
|
|
24
|
+
if (failures.length > 0) {
|
|
25
|
+
const unsupported = failures.every(item => item.code === 'UNSUPPORTED_VERSION' || item.code === 'UNSUPPORTED_PROFILE');
|
|
26
|
+
return result(unsupported ? 'unsupported' : 'invalid', failures);
|
|
27
|
+
}
|
|
28
|
+
chain.push(rawChain[i]);
|
|
29
|
+
}
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
for (let i = 0; i < chain.length; i++) {
|
|
32
|
+
const delegation = chain[i];
|
|
33
|
+
if (seen.has(delegation.delegation_id)) {
|
|
34
|
+
return result('invalid', [{ code: 'CHAIN_DUPLICATE_ID', index: i, message: 'delegation ID repeats in chain' }]);
|
|
35
|
+
}
|
|
36
|
+
seen.add(delegation.delegation_id);
|
|
37
|
+
const expectedId = computeAuthorityDelegationId(authorityDelegationBody(delegation));
|
|
38
|
+
if (expectedId !== delegation.delegation_id) {
|
|
39
|
+
return result('invalid', [{ code: 'ID_MISMATCH', index: i, message: 'delegation content address does not match body' }]);
|
|
40
|
+
}
|
|
41
|
+
let publicKey = null;
|
|
42
|
+
try {
|
|
43
|
+
publicKey = options.resolveVerificationKey(delegation.issuer, delegation.verification_method, delegation.issued_at);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
publicKey = null;
|
|
47
|
+
}
|
|
48
|
+
if (publicKey === null) {
|
|
49
|
+
return result('indeterminate', [{ code: 'KEY_RESOLUTION_FAILED', index: i, message: 'issuer verification key could not be resolved' }]);
|
|
50
|
+
}
|
|
51
|
+
if (!verifyAuthorityDelegationSignature(delegation, publicKey)) {
|
|
52
|
+
return result('invalid', [{ code: 'SIGNATURE_INVALID', index: i, message: 'Ed25519 signature is invalid' }]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const root = chain[0];
|
|
56
|
+
if (root.parent_delegation_id !== null) {
|
|
57
|
+
return result('invalid', [{ code: 'PARENT_MISMATCH', index: 0, message: 'full chain root must carry null parent_delegation_id' }]);
|
|
58
|
+
}
|
|
59
|
+
if (typeof options.trustRoot !== 'function') {
|
|
60
|
+
return result('indeterminate', [{ code: 'ROOT_UNTRUSTED', index: 0, message: 'root trust policy is unavailable' }]);
|
|
61
|
+
}
|
|
62
|
+
let trustDecision;
|
|
63
|
+
try {
|
|
64
|
+
trustDecision = options.trustRoot(root);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return result('indeterminate', [{ code: 'ROOT_UNTRUSTED', index: 0, message: 'root trust policy could not decide' }]);
|
|
68
|
+
}
|
|
69
|
+
if (typeof trustDecision !== 'boolean') {
|
|
70
|
+
return result('indeterminate', [{ code: 'ROOT_UNTRUSTED', index: 0, message: 'root trust policy returned no boolean decision' }]);
|
|
71
|
+
}
|
|
72
|
+
if (!trustDecision) {
|
|
73
|
+
return result('invalid', [{ code: 'ROOT_UNTRUSTED', index: 0, message: 'root is not accepted by verifier trust policy' }]);
|
|
74
|
+
}
|
|
75
|
+
for (let i = 1; i < chain.length; i++) {
|
|
76
|
+
const parent = chain[i - 1];
|
|
77
|
+
const child = chain[i];
|
|
78
|
+
if (child.parent_delegation_id !== parent.delegation_id) {
|
|
79
|
+
return result('invalid', [{ code: 'PARENT_MISMATCH', index: i, message: 'child does not name immediate parent content address' }]);
|
|
80
|
+
}
|
|
81
|
+
if (child.issuer !== parent.subject) {
|
|
82
|
+
return result('invalid', [{ code: 'CHAIN_CONTINUITY', index: i, message: 'child issuer is not parent subject' }]);
|
|
83
|
+
}
|
|
84
|
+
const issued = Date.parse(child.issued_at);
|
|
85
|
+
if (issued < Date.parse(parent.authority.time.not_before) ||
|
|
86
|
+
issued >= Date.parse(parent.authority.time.not_after)) {
|
|
87
|
+
return result('invalid', [{ code: 'ISSUED_AT_OUTSIDE_PARENT', index: i, message: 'child was issued outside parent validity window' }]);
|
|
88
|
+
}
|
|
89
|
+
const attenuationFailures = compareAuthority(parent.authority, child.authority);
|
|
90
|
+
if (attenuationFailures.length > 0) {
|
|
91
|
+
const indexedFailures = attenuationFailures.map(item => indexed(item, i));
|
|
92
|
+
const unsupported = indexedFailures.every(item => item.code === 'UNSUPPORTED_PROFILE');
|
|
93
|
+
return result(unsupported ? 'unsupported' : 'invalid', indexedFailures);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (let i = 0; i < chain.length; i++) {
|
|
97
|
+
const delegation = chain[i];
|
|
98
|
+
if (now < Date.parse(delegation.authority.time.not_before)) {
|
|
99
|
+
return result('invalid', [{ code: 'NOT_YET_VALID', index: i, message: 'delegation is not yet valid' }]);
|
|
100
|
+
}
|
|
101
|
+
if (now >= Date.parse(delegation.authority.time.not_after)) {
|
|
102
|
+
return result('invalid', [{ code: 'EXPIRED', index: i, message: 'delegation has expired' }]);
|
|
103
|
+
}
|
|
104
|
+
let revocation = 'unknown';
|
|
105
|
+
try {
|
|
106
|
+
const resolved = options.resolveRevocation(delegation);
|
|
107
|
+
revocation = resolved === 'active' || resolved === 'revoked' ? resolved : 'unknown';
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
revocation = 'unknown';
|
|
111
|
+
}
|
|
112
|
+
if (revocation === 'revoked') {
|
|
113
|
+
return result('invalid', [{ code: 'REVOKED', index: i, message: 'delegation is revoked' }]);
|
|
114
|
+
}
|
|
115
|
+
if (revocation === 'unknown') {
|
|
116
|
+
return result('indeterminate', [{ code: 'REVOCATION_UNKNOWN', index: i, message: 'revocation status is unknown' }]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result('valid', []);
|
|
120
|
+
}
|
|
121
|
+
export function verifyAuthorityDelegation(delegation, options) {
|
|
122
|
+
return verifyAuthorityDelegationChain([delegation], options);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=verify.js.map
|