agent-passport-system 4.1.0 → 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/README.md +37 -34
- 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 +6 -6
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { canonicalizeJCS } from '../../core/canonical-jcs.js';
|
|
5
|
+
import { sign, verify } from '../../crypto/keys.js';
|
|
6
|
+
import { assertExactKeys, assertHex, assertIJson, assertPlainRecord, assertSortedUnique, assertUtcMilliseconds, sortedUnique, } from './validation.js';
|
|
7
|
+
const ID_DOMAIN = 'APS-PRINCIPAL-BINDING-ID-V1\0';
|
|
8
|
+
const SIGNATURE_DOMAIN = 'APS-PRINCIPAL-BINDING-SIG-V1\0';
|
|
9
|
+
export function issuePrincipalBindingV1(input) {
|
|
10
|
+
const draft = {
|
|
11
|
+
record_type: 'aps.principal-binding',
|
|
12
|
+
version: '1.0',
|
|
13
|
+
agent_id: input.agent_id,
|
|
14
|
+
principal_id: input.principal_id,
|
|
15
|
+
verification_method: input.verification_method,
|
|
16
|
+
audiences: sortedUnique(input.audiences, 'audiences'),
|
|
17
|
+
authority_profiles: sortedUnique(input.authority_profiles, 'authority_profiles'),
|
|
18
|
+
status_uri: input.status_uri,
|
|
19
|
+
issued_at: input.issued_at,
|
|
20
|
+
expires_at: input.expires_at,
|
|
21
|
+
nonce: input.nonce,
|
|
22
|
+
};
|
|
23
|
+
validateBindingDraft(draft);
|
|
24
|
+
const bindingId = digest(ID_DOMAIN + canonicalizeJCS(draft));
|
|
25
|
+
const withId = { ...draft, binding_id: bindingId };
|
|
26
|
+
return {
|
|
27
|
+
...withId,
|
|
28
|
+
signature: sign(SIGNATURE_DOMAIN + canonicalizeJCS(withId), input.principal_private_key_hex),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function verifyPrincipalBindingV1(candidate, options) {
|
|
32
|
+
let binding;
|
|
33
|
+
try {
|
|
34
|
+
binding = validateBinding(candidate);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return invalid('PRINCIPAL_BINDING_MALFORMED');
|
|
38
|
+
}
|
|
39
|
+
const idForm = omit(binding, ['binding_id', 'signature']);
|
|
40
|
+
if (digest(ID_DOMAIN + canonicalizeJCS(idForm)) !== binding.binding_id) {
|
|
41
|
+
return invalid('PRINCIPAL_BINDING_ID_MISMATCH');
|
|
42
|
+
}
|
|
43
|
+
const now = options.now ?? new Date().toISOString();
|
|
44
|
+
if (now < binding.issued_at || now >= binding.expires_at) {
|
|
45
|
+
return invalid('PRINCIPAL_BINDING_NOT_CURRENT');
|
|
46
|
+
}
|
|
47
|
+
const resolution = await options.resolve_key({
|
|
48
|
+
controller: binding.principal_id,
|
|
49
|
+
verification_method: binding.verification_method,
|
|
50
|
+
at: binding.issued_at,
|
|
51
|
+
});
|
|
52
|
+
if (resolution.state !== 'resolved' || !resolution.public_key_hex) {
|
|
53
|
+
const indeterminate = resolution.state === 'unreachable';
|
|
54
|
+
return {
|
|
55
|
+
state: indeterminate ? 'indeterminate' : 'invalid',
|
|
56
|
+
code: `PRINCIPAL_BINDING_KEY_${resolution.state.toUpperCase()}`,
|
|
57
|
+
proof_of_possession: false,
|
|
58
|
+
key_authority: indeterminate ? 'unresolved' : 'rejected',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const signatureForm = omit(binding, ['signature']);
|
|
62
|
+
if (!verify(SIGNATURE_DOMAIN + canonicalizeJCS(signatureForm), binding.signature, resolution.public_key_hex)) {
|
|
63
|
+
return invalid('PRINCIPAL_BINDING_SIGNATURE_INVALID');
|
|
64
|
+
}
|
|
65
|
+
let claimLevel = 'principal_attested';
|
|
66
|
+
if (options.principal_is_externally_verified &&
|
|
67
|
+
await options.principal_is_externally_verified(binding.principal_id, binding.issued_at)) {
|
|
68
|
+
claimLevel = 'externally_verified_principal';
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
state: 'valid',
|
|
72
|
+
code: 'OK',
|
|
73
|
+
proof_of_possession: true,
|
|
74
|
+
key_authority: 'verified',
|
|
75
|
+
principal_claim_level: claimLevel,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function validateBinding(value) {
|
|
79
|
+
assertPlainRecord(value, 'principal binding');
|
|
80
|
+
assertExactKeys(value, [
|
|
81
|
+
'record_type', 'version', 'binding_id', 'agent_id', 'principal_id',
|
|
82
|
+
'verification_method', 'audiences', 'authority_profiles', 'status_uri',
|
|
83
|
+
'issued_at', 'expires_at', 'nonce', 'signature',
|
|
84
|
+
], [], 'principal binding');
|
|
85
|
+
validateBindingDraft(value);
|
|
86
|
+
assertHex(String(value.binding_id), 64, 'binding_id');
|
|
87
|
+
assertHex(String(value.signature), 128, 'signature');
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
function validateBindingDraft(value) {
|
|
91
|
+
assertIJson(value);
|
|
92
|
+
if (value.record_type !== 'aps.principal-binding' || value.version !== '1.0')
|
|
93
|
+
throw new Error('profile');
|
|
94
|
+
if (!/^did:[a-z0-9]+:.+$/.test(value.agent_id))
|
|
95
|
+
throw new Error('agent_id');
|
|
96
|
+
if (!/^did:[a-z0-9]+:.+$/.test(value.principal_id) && !/^https:\/\//.test(value.principal_id)) {
|
|
97
|
+
throw new Error('principal_id');
|
|
98
|
+
}
|
|
99
|
+
if (!value.verification_method.startsWith(`${value.principal_id}#`))
|
|
100
|
+
throw new Error('verification_method');
|
|
101
|
+
if (!Array.isArray(value.audiences) || value.audiences.length === 0)
|
|
102
|
+
throw new Error('audiences');
|
|
103
|
+
if (!Array.isArray(value.authority_profiles) || value.authority_profiles.length === 0)
|
|
104
|
+
throw new Error('authority_profiles');
|
|
105
|
+
assertSortedUnique(value.audiences, 'audiences');
|
|
106
|
+
assertSortedUnique(value.authority_profiles, 'authority_profiles');
|
|
107
|
+
if (!/^https:\/\//.test(value.status_uri))
|
|
108
|
+
throw new Error('status_uri');
|
|
109
|
+
assertUtcMilliseconds(value.issued_at, 'issued_at');
|
|
110
|
+
assertUtcMilliseconds(value.expires_at, 'expires_at');
|
|
111
|
+
if (value.issued_at >= value.expires_at)
|
|
112
|
+
throw new Error('binding time window');
|
|
113
|
+
assertHex(value.nonce, 32, 'nonce');
|
|
114
|
+
}
|
|
115
|
+
function digest(value) {
|
|
116
|
+
return createHash('sha256').update(value, 'utf8').digest('hex');
|
|
117
|
+
}
|
|
118
|
+
function omit(value, keys) {
|
|
119
|
+
const result = {};
|
|
120
|
+
for (const [key, entry] of Object.entries(value))
|
|
121
|
+
if (!keys.includes(key))
|
|
122
|
+
result[key] = entry;
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
function invalid(code) {
|
|
126
|
+
return { state: 'invalid', code, proof_of_possession: false, key_authority: 'rejected' };
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=principal-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal-binding.js","sourceRoot":"","sources":["../../../../src/v2/identity-binding/principal-binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HistoricalKeyResolver, IdentityVerificationResult, PrincipalBindingRevocationV1 } from './types.js';
|
|
2
|
+
export declare function issuePrincipalBindingRevocationV1(input: {
|
|
3
|
+
binding_id: string;
|
|
4
|
+
principal_id: string;
|
|
5
|
+
verification_method: string;
|
|
6
|
+
revoked_at: string;
|
|
7
|
+
reason_code: string;
|
|
8
|
+
nonce: string;
|
|
9
|
+
principal_private_key_hex: string;
|
|
10
|
+
}): PrincipalBindingRevocationV1;
|
|
11
|
+
export declare function verifyPrincipalBindingRevocationV1(candidate: unknown, resolveKey: HistoricalKeyResolver): Promise<IdentityVerificationResult>;
|
|
12
|
+
//# sourceMappingURL=revocation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revocation.d.ts","sourceRoot":"","sources":["../../../../src/v2/identity-binding/revocation.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,qBAAqB,EACrB,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,YAAY,CAAA;AAYnB,wBAAgB,iCAAiC,CAAC,KAAK,EAAE;IACvD,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB,EAAE,MAAM,CAAA;CAClC,GAAG,4BAA4B,CAqB/B;AAED,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,OAAO,EAClB,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,0BAA0B,CAAC,CAgCrC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { canonicalizeJCS } from '../../core/canonical-jcs.js';
|
|
5
|
+
import { sign, verify } from '../../crypto/keys.js';
|
|
6
|
+
import { assertExactKeys, assertHex, assertIJson, assertPlainRecord, assertUtcMilliseconds, } from './validation.js';
|
|
7
|
+
const ID_DOMAIN = 'APS-PRINCIPAL-BINDING-REVOCATION-ID-V1\0';
|
|
8
|
+
const SIGNATURE_DOMAIN = 'APS-PRINCIPAL-BINDING-REVOCATION-SIG-V1\0';
|
|
9
|
+
export function issuePrincipalBindingRevocationV1(input) {
|
|
10
|
+
const draft = {
|
|
11
|
+
record_type: 'aps.principal-binding-revocation',
|
|
12
|
+
version: '1.0',
|
|
13
|
+
binding_id: input.binding_id,
|
|
14
|
+
principal_id: input.principal_id,
|
|
15
|
+
verification_method: input.verification_method,
|
|
16
|
+
revoked_at: input.revoked_at,
|
|
17
|
+
reason_code: input.reason_code,
|
|
18
|
+
nonce: input.nonce,
|
|
19
|
+
};
|
|
20
|
+
validateRevocationDraft(draft);
|
|
21
|
+
const revocationId = digest(ID_DOMAIN + canonicalizeJCS(draft));
|
|
22
|
+
const withId = {
|
|
23
|
+
...draft,
|
|
24
|
+
revocation_id: revocationId,
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
...withId,
|
|
28
|
+
signature: sign(SIGNATURE_DOMAIN + canonicalizeJCS(withId), input.principal_private_key_hex),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function verifyPrincipalBindingRevocationV1(candidate, resolveKey) {
|
|
32
|
+
let revocation;
|
|
33
|
+
try {
|
|
34
|
+
revocation = validateRevocation(candidate);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return invalid('PRINCIPAL_BINDING_REVOCATION_MALFORMED');
|
|
38
|
+
}
|
|
39
|
+
const idForm = omit(revocation, ['revocation_id', 'signature']);
|
|
40
|
+
if (digest(ID_DOMAIN + canonicalizeJCS(idForm)) !== revocation.revocation_id) {
|
|
41
|
+
return invalid('PRINCIPAL_BINDING_REVOCATION_ID_MISMATCH');
|
|
42
|
+
}
|
|
43
|
+
const resolution = await resolveKey({
|
|
44
|
+
controller: revocation.principal_id,
|
|
45
|
+
verification_method: revocation.verification_method,
|
|
46
|
+
at: revocation.revoked_at,
|
|
47
|
+
});
|
|
48
|
+
if (resolution.state !== 'resolved' || !resolution.public_key_hex) {
|
|
49
|
+
return {
|
|
50
|
+
state: resolution.state === 'unreachable' ? 'indeterminate' : 'invalid',
|
|
51
|
+
code: `PRINCIPAL_BINDING_REVOCATION_KEY_${resolution.state.toUpperCase()}`,
|
|
52
|
+
proof_of_possession: false,
|
|
53
|
+
key_authority: resolution.state === 'unreachable' ? 'unresolved' : 'rejected',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const signatureForm = omit(revocation, ['signature']);
|
|
57
|
+
if (!verify(SIGNATURE_DOMAIN + canonicalizeJCS(signatureForm), revocation.signature, resolution.public_key_hex))
|
|
58
|
+
return invalid('PRINCIPAL_BINDING_REVOCATION_SIGNATURE_INVALID');
|
|
59
|
+
return { state: 'valid', code: 'OK', proof_of_possession: true, key_authority: 'verified' };
|
|
60
|
+
}
|
|
61
|
+
function validateRevocation(value) {
|
|
62
|
+
assertPlainRecord(value, 'binding revocation');
|
|
63
|
+
assertExactKeys(value, [
|
|
64
|
+
'record_type', 'version', 'revocation_id', 'binding_id', 'principal_id',
|
|
65
|
+
'verification_method', 'revoked_at', 'reason_code', 'nonce', 'signature',
|
|
66
|
+
], [], 'binding revocation');
|
|
67
|
+
validateRevocationDraft(value);
|
|
68
|
+
assertHex(String(value.revocation_id), 64, 'revocation_id');
|
|
69
|
+
assertHex(String(value.signature), 128, 'signature');
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
function validateRevocationDraft(value) {
|
|
73
|
+
assertIJson(value);
|
|
74
|
+
if (value.record_type !== 'aps.principal-binding-revocation' || value.version !== '1.0')
|
|
75
|
+
throw new Error('profile');
|
|
76
|
+
assertHex(value.binding_id, 64, 'binding_id');
|
|
77
|
+
if (!value.verification_method.startsWith(`${value.principal_id}#`))
|
|
78
|
+
throw new Error('verification_method');
|
|
79
|
+
assertUtcMilliseconds(value.revoked_at, 'revoked_at');
|
|
80
|
+
if (!/^[a-z][a-z0-9_.-]{0,63}$/.test(value.reason_code))
|
|
81
|
+
throw new Error('reason_code');
|
|
82
|
+
assertHex(value.nonce, 32, 'nonce');
|
|
83
|
+
}
|
|
84
|
+
function digest(value) {
|
|
85
|
+
return createHash('sha256').update(value, 'utf8').digest('hex');
|
|
86
|
+
}
|
|
87
|
+
function omit(value, keys) {
|
|
88
|
+
const result = {};
|
|
89
|
+
for (const [key, entry] of Object.entries(value))
|
|
90
|
+
if (!keys.includes(key))
|
|
91
|
+
result[key] = entry;
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
function invalid(code) {
|
|
95
|
+
return { state: 'invalid', code, proof_of_possession: false, key_authority: 'rejected' };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=revocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revocation.js","sourceRoot":"","sources":["../../../../src/v2/identity-binding/revocation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type Hex32 = string;
|
|
2
|
+
export type Hex64 = string;
|
|
3
|
+
export type Hex128 = string;
|
|
4
|
+
export interface PassportSelfAssertionsV2 {
|
|
5
|
+
display_name?: string;
|
|
6
|
+
capabilities: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A cryptographic agent identity record. Principal authority is deliberately
|
|
10
|
+
* absent; it is carried by PrincipalBindingV1 instead of being self-asserted
|
|
11
|
+
* inside the passport.
|
|
12
|
+
*/
|
|
13
|
+
export interface PassportV2 {
|
|
14
|
+
record_type: 'aps.agent-passport';
|
|
15
|
+
version: '2.0';
|
|
16
|
+
passport_id: Hex64;
|
|
17
|
+
agent_id: string;
|
|
18
|
+
verification_method: string;
|
|
19
|
+
public_key_multibase: string;
|
|
20
|
+
issued_at: string;
|
|
21
|
+
expires_at: string;
|
|
22
|
+
nonce: Hex32;
|
|
23
|
+
self_asserted: PassportSelfAssertionsV2;
|
|
24
|
+
signature: Hex128;
|
|
25
|
+
}
|
|
26
|
+
export interface PrincipalBindingV1 {
|
|
27
|
+
record_type: 'aps.principal-binding';
|
|
28
|
+
version: '1.0';
|
|
29
|
+
binding_id: Hex64;
|
|
30
|
+
agent_id: string;
|
|
31
|
+
principal_id: string;
|
|
32
|
+
verification_method: string;
|
|
33
|
+
audiences: string[];
|
|
34
|
+
authority_profiles: string[];
|
|
35
|
+
status_uri: string;
|
|
36
|
+
issued_at: string;
|
|
37
|
+
expires_at: string;
|
|
38
|
+
nonce: Hex32;
|
|
39
|
+
signature: Hex128;
|
|
40
|
+
}
|
|
41
|
+
export interface PrincipalBindingRevocationV1 {
|
|
42
|
+
record_type: 'aps.principal-binding-revocation';
|
|
43
|
+
version: '1.0';
|
|
44
|
+
revocation_id: Hex64;
|
|
45
|
+
binding_id: Hex64;
|
|
46
|
+
principal_id: string;
|
|
47
|
+
verification_method: string;
|
|
48
|
+
revoked_at: string;
|
|
49
|
+
reason_code: string;
|
|
50
|
+
nonce: Hex32;
|
|
51
|
+
signature: Hex128;
|
|
52
|
+
}
|
|
53
|
+
export type PrincipalClaimLevel = 'self_asserted' | 'principal_attested' | 'externally_verified_principal';
|
|
54
|
+
export type IdentityVerificationState = 'valid' | 'invalid' | 'indeterminate' | 'unsupported';
|
|
55
|
+
export interface IdentityVerificationResult {
|
|
56
|
+
state: IdentityVerificationState;
|
|
57
|
+
code: string;
|
|
58
|
+
proof_of_possession: boolean;
|
|
59
|
+
key_authority: 'verified' | 'unresolved' | 'rejected';
|
|
60
|
+
principal_claim_level?: PrincipalClaimLevel;
|
|
61
|
+
}
|
|
62
|
+
export interface HistoricalKeyResolutionRequest {
|
|
63
|
+
controller: string;
|
|
64
|
+
verification_method: string;
|
|
65
|
+
at: string;
|
|
66
|
+
}
|
|
67
|
+
export interface HistoricalKeyResolutionResult {
|
|
68
|
+
state: 'resolved' | 'not_found' | 'ambiguous' | 'malformed' | 'unreachable' | 'unsupported';
|
|
69
|
+
public_key_hex?: string;
|
|
70
|
+
}
|
|
71
|
+
export type HistoricalKeyResolver = (request: HistoricalKeyResolutionRequest) => HistoricalKeyResolutionResult | Promise<HistoricalKeyResolutionResult>;
|
|
72
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/v2/identity-binding/types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,KAAK,GAAG,MAAM,CAAA;AAC1B,MAAM,MAAM,KAAK,GAAG,MAAM,CAAA;AAC1B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAA;AAE3B,MAAM,WAAW,wBAAwB;IACvC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,oBAAoB,CAAA;IACjC,OAAO,EAAE,KAAK,CAAA;IACd,WAAW,EAAE,KAAK,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,KAAK,CAAA;IACZ,aAAa,EAAE,wBAAwB,CAAA;IACvC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,uBAAuB,CAAA;IACpC,OAAO,EAAE,KAAK,CAAA;IACd,UAAU,EAAE,KAAK,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,kCAAkC,CAAA;IAC/C,OAAO,EAAE,KAAK,CAAA;IACd,aAAa,EAAE,KAAK,CAAA;IACpB,UAAU,EAAE,KAAK,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,oBAAoB,GACpB,+BAA+B,CAAA;AAEnC,MAAM,MAAM,yBAAyB,GACjC,OAAO,GACP,SAAS,GACT,eAAe,GACf,aAAa,CAAA;AAEjB,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,yBAAyB,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,mBAAmB,EAAE,OAAO,CAAA;IAC5B,aAAa,EAAE,UAAU,GAAG,YAAY,GAAG,UAAU,CAAA;IACrD,qBAAqB,CAAC,EAAE,mBAAmB,CAAA;CAC5C;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,MAAM,CAAA;IAClB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,aAAa,CAAA;IAC3F,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,8BAA8B,KACpC,6BAA6B,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/v2/identity-binding/types.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,sCAAsC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function assertPlainRecord(value: unknown, name: string): asserts value is Record<string, unknown>;
|
|
2
|
+
export declare function assertExactKeys(value: Record<string, unknown>, required: readonly string[], optional?: readonly string[], name?: string): void;
|
|
3
|
+
export declare function assertIJson(value: unknown, path?: string, ancestors?: WeakSet<object>): void;
|
|
4
|
+
export declare function assertUnicodeScalarString(value: string, path: string): void;
|
|
5
|
+
export declare function assertUtcMilliseconds(value: string, name: string): void;
|
|
6
|
+
export declare function assertHex(value: string, length: number, name: string): void;
|
|
7
|
+
export declare function assertSortedUnique(values: string[], name: string): void;
|
|
8
|
+
export declare function sortedUnique(values: readonly string[], name: string): string[];
|
|
9
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../../src/v2/identity-binding/validation.ts"],"names":[],"mappings":"AAKA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQxG;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,IAAI,SAAW,GACd,IAAI,CAQN;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAM,EAAE,SAAS,kBAAwB,GAAG,IAAI,CA2B/F;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAW3E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMvE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI3E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAUvE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAK9E"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
const UTC_MILLISECONDS = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d\.\d{3}Z$/;
|
|
4
|
+
export function assertPlainRecord(value, name) {
|
|
5
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
6
|
+
throw new Error(`${name}: expected object`);
|
|
7
|
+
}
|
|
8
|
+
const prototype = Object.getPrototypeOf(value);
|
|
9
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
10
|
+
throw new Error(`${name}: non-JSON object`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function assertExactKeys(value, required, optional = [], name = 'object') {
|
|
14
|
+
const allowed = new Set([...required, ...optional]);
|
|
15
|
+
for (const key of required) {
|
|
16
|
+
if (!Object.hasOwn(value, key))
|
|
17
|
+
throw new Error(`${name}: missing ${key}`);
|
|
18
|
+
}
|
|
19
|
+
for (const key of Object.keys(value)) {
|
|
20
|
+
if (!allowed.has(key))
|
|
21
|
+
throw new Error(`${name}: unknown field ${key}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function assertIJson(value, path = '$', ancestors = new WeakSet()) {
|
|
25
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string') {
|
|
26
|
+
if (typeof value === 'string')
|
|
27
|
+
assertUnicodeScalarString(value, path);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (typeof value === 'number') {
|
|
31
|
+
if (!Number.isFinite(value) || (Number.isInteger(value) && !Number.isSafeInteger(value))) {
|
|
32
|
+
throw new Error(`${path}: non-I-JSON number`);
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value !== 'object' || value === undefined || value instanceof Date) {
|
|
37
|
+
throw new Error(`${path}: unsupported I-JSON value`);
|
|
38
|
+
}
|
|
39
|
+
if (ancestors.has(value))
|
|
40
|
+
throw new Error(`${path}: cyclic value`);
|
|
41
|
+
ancestors.add(value);
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
value.forEach((entry, index) => assertIJson(entry, `${path}[${index}]`, ancestors));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
assertPlainRecord(value, path);
|
|
47
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
48
|
+
assertUnicodeScalarString(key, `${path} key`);
|
|
49
|
+
if (entry === undefined)
|
|
50
|
+
throw new Error(`${path}.${key}: undefined is not I-JSON`);
|
|
51
|
+
assertIJson(entry, `${path}.${key}`, ancestors);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
ancestors.delete(value);
|
|
55
|
+
}
|
|
56
|
+
export function assertUnicodeScalarString(value, path) {
|
|
57
|
+
for (let index = 0; index < value.length; index++) {
|
|
58
|
+
const code = value.charCodeAt(index);
|
|
59
|
+
if (code >= 0xd800 && code <= 0xdbff) {
|
|
60
|
+
const next = value.charCodeAt(index + 1);
|
|
61
|
+
if (next < 0xdc00 || next > 0xdfff)
|
|
62
|
+
throw new Error(`${path}: lone surrogate`);
|
|
63
|
+
index++;
|
|
64
|
+
}
|
|
65
|
+
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
66
|
+
throw new Error(`${path}: lone surrogate`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function assertUtcMilliseconds(value, name) {
|
|
71
|
+
if (!UTC_MILLISECONDS.test(value))
|
|
72
|
+
throw new Error(`${name}: expected canonical UTC milliseconds`);
|
|
73
|
+
const parsed = new Date(value);
|
|
74
|
+
if (Number.isNaN(parsed.getTime()) || parsed.toISOString() !== value) {
|
|
75
|
+
throw new Error(`${name}: invalid calendar timestamp`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function assertHex(value, length, name) {
|
|
79
|
+
if (!new RegExp(`^[0-9a-f]{${length}}$`).test(value)) {
|
|
80
|
+
throw new Error(`${name}: expected ${length} lowercase hexadecimal characters`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function assertSortedUnique(values, name) {
|
|
84
|
+
for (const value of values) {
|
|
85
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
86
|
+
throw new Error(`${name}: empty or non-string value`);
|
|
87
|
+
assertUnicodeScalarString(value, name);
|
|
88
|
+
}
|
|
89
|
+
for (let index = 1; index < values.length; index++) {
|
|
90
|
+
if (compareUtf8(values[index - 1], values[index]) >= 0) {
|
|
91
|
+
throw new Error(`${name}: values must be sorted and unique by UTF-8 bytes`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export function sortedUnique(values, name) {
|
|
96
|
+
const result = [...values];
|
|
97
|
+
result.sort(compareUtf8);
|
|
98
|
+
assertSortedUnique(result, name);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function compareUtf8(left, right) {
|
|
102
|
+
return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../../src/v2/identity-binding/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CoreDecisionOutputV1, DecisionRefInputV1, JsonValue } from './types.js';
|
|
2
|
+
export declare const DECISION_REF_TAG: 'APS-DECISION-REF-V1';
|
|
3
|
+
export declare const DECISION_COMPONENT_TAGS: {
|
|
4
|
+
readonly authority: 'APS-DECISION-AUTHORITY-V1';
|
|
5
|
+
readonly policy: 'APS-DECISION-POLICY-V1';
|
|
6
|
+
readonly context: 'APS-DECISION-CONTEXT-V1';
|
|
7
|
+
readonly output: 'APS-DECISION-OUTPUT-V1';
|
|
8
|
+
};
|
|
9
|
+
export declare function computeDecisionComponentRefV1(tag: keyof typeof DECISION_COMPONENT_TAGS, value: JsonValue): string;
|
|
10
|
+
export declare function validateDecisionRefInputV1(input: DecisionRefInputV1): void;
|
|
11
|
+
export declare function computeDecisionRefV1(input: DecisionRefInputV1): string;
|
|
12
|
+
export declare function normalizeCoreDecisionOutputV1(input: CoreDecisionOutputV1): CoreDecisionOutputV1;
|
|
13
|
+
export declare function buildDecisionRefV1(input: {
|
|
14
|
+
action_ref: string;
|
|
15
|
+
authority_state: JsonValue;
|
|
16
|
+
policy_input: JsonValue;
|
|
17
|
+
decision_context: JsonValue;
|
|
18
|
+
decision_output: JsonValue;
|
|
19
|
+
}): {
|
|
20
|
+
input: DecisionRefInputV1;
|
|
21
|
+
decision_ref: string;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=decision-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-ref.d.ts","sourceRoot":"","sources":["../../../../src/v2/receipt-core/decision-ref.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAErF,eAAO,MAAM,gBAAgB,EAAG,qBAA8B,CAAA;AAC9D,eAAO,MAAM,uBAAuB;aAClC,SAAS,EAAE,2BAA2B;aACtC,MAAM,EAAE,wBAAwB;aAChC,OAAO,EAAE,yBAAyB;aAClC,MAAM,EAAE,wBAAwB;CACxB,CAAA;AAMV,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,OAAO,uBAAuB,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAEjH;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAW1E;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAGtE;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,oBAAoB,CA2B/F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,SAAS,CAAA;IAC1B,YAAY,EAAE,SAAS,CAAA;IACvB,gBAAgB,EAAE,SAAS,CAAA;IAC3B,eAAe,EAAE,SAAS,CAAA;CAC3B,GAAG;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAWtD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Copyright (c) 2026 Tymofii Pidlisnyi
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { strictJCS, assertExactKeys } from './jcs.js';
|
|
5
|
+
export const DECISION_REF_TAG = 'APS-DECISION-REF-V1';
|
|
6
|
+
export const DECISION_COMPONENT_TAGS = {
|
|
7
|
+
authority: 'APS-DECISION-AUTHORITY-V1',
|
|
8
|
+
policy: 'APS-DECISION-POLICY-V1',
|
|
9
|
+
context: 'APS-DECISION-CONTEXT-V1',
|
|
10
|
+
output: 'APS-DECISION-OUTPUT-V1',
|
|
11
|
+
};
|
|
12
|
+
const HEX64 = /^[0-9a-f]{64}$/;
|
|
13
|
+
const tagged = (tag, canonical) => `${tag}\0${canonical}`;
|
|
14
|
+
const sha256Hex = (value) => createHash('sha256').update(value, 'utf8').digest('hex');
|
|
15
|
+
export function computeDecisionComponentRefV1(tag, value) {
|
|
16
|
+
return sha256Hex(tagged(DECISION_COMPONENT_TAGS[tag], strictJCS(value)));
|
|
17
|
+
}
|
|
18
|
+
export function validateDecisionRefInputV1(input) {
|
|
19
|
+
assertExactKeys(input, ['profile', 'action_ref', 'authority_state_ref', 'policy_ref', 'context_ref', 'decision_output_ref'], ['profile', 'action_ref', 'authority_state_ref', 'policy_ref', 'context_ref', 'decision_output_ref'], 'DecisionRefInputV1');
|
|
20
|
+
if (input.profile !== 'aps-decision-ref-v1')
|
|
21
|
+
throw new TypeError('DecisionRefInputV1: profile');
|
|
22
|
+
for (const [key, value] of Object.entries(input)) {
|
|
23
|
+
if (key !== 'profile' && (typeof value !== 'string' || !HEX64.test(value))) {
|
|
24
|
+
throw new TypeError(`DecisionRefInputV1: ${key} must be lowercase sha256 hex`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function computeDecisionRefV1(input) {
|
|
29
|
+
validateDecisionRefInputV1(input);
|
|
30
|
+
return sha256Hex(tagged(DECISION_REF_TAG, strictJCS(input)));
|
|
31
|
+
}
|
|
32
|
+
export function normalizeCoreDecisionOutputV1(input) {
|
|
33
|
+
assertExactKeys(input, ['profile', 'verdict', 'effective_authority_ref', 'constraints'], ['profile', 'verdict', 'effective_authority_ref', 'constraints'], 'CoreDecisionOutputV1');
|
|
34
|
+
strictJCS(input);
|
|
35
|
+
if (input.profile !== 'aps-core-decision-output-v1')
|
|
36
|
+
throw new TypeError('CoreDecisionOutputV1: profile');
|
|
37
|
+
if (!['permit', 'deny', 'narrow'].includes(input.verdict))
|
|
38
|
+
throw new TypeError('CoreDecisionOutputV1: verdict');
|
|
39
|
+
if (input.effective_authority_ref !== null && !HEX64.test(input.effective_authority_ref)) {
|
|
40
|
+
throw new TypeError('CoreDecisionOutputV1: effective_authority_ref');
|
|
41
|
+
}
|
|
42
|
+
if (input.verdict === 'deny' && input.effective_authority_ref !== null) {
|
|
43
|
+
throw new TypeError('CoreDecisionOutputV1: deny requires null effective_authority_ref');
|
|
44
|
+
}
|
|
45
|
+
if (input.verdict !== 'deny' && input.effective_authority_ref === null) {
|
|
46
|
+
throw new TypeError('CoreDecisionOutputV1: permit/narrow require effective_authority_ref');
|
|
47
|
+
}
|
|
48
|
+
if (!Array.isArray(input.constraints) || !input.constraints.every(v => typeof v === 'string')) {
|
|
49
|
+
throw new TypeError('CoreDecisionOutputV1: constraints');
|
|
50
|
+
}
|
|
51
|
+
const constraints = [...new Set(input.constraints.map(v => v.normalize('NFC')))]
|
|
52
|
+
.sort((a, b) => {
|
|
53
|
+
const aa = Array.from(a, c => c.codePointAt(0));
|
|
54
|
+
const bb = Array.from(b, c => c.codePointAt(0));
|
|
55
|
+
for (let i = 0; i < Math.min(aa.length, bb.length); i++)
|
|
56
|
+
if (aa[i] !== bb[i])
|
|
57
|
+
return aa[i] - bb[i];
|
|
58
|
+
return aa.length - bb.length;
|
|
59
|
+
});
|
|
60
|
+
return { ...input, constraints };
|
|
61
|
+
}
|
|
62
|
+
export function buildDecisionRefV1(input) {
|
|
63
|
+
if (!HEX64.test(input.action_ref))
|
|
64
|
+
throw new TypeError('action_ref must be lowercase sha256 hex');
|
|
65
|
+
const refInput = {
|
|
66
|
+
profile: 'aps-decision-ref-v1',
|
|
67
|
+
action_ref: input.action_ref,
|
|
68
|
+
authority_state_ref: computeDecisionComponentRefV1('authority', input.authority_state),
|
|
69
|
+
policy_ref: computeDecisionComponentRefV1('policy', input.policy_input),
|
|
70
|
+
context_ref: computeDecisionComponentRefV1('context', input.decision_context),
|
|
71
|
+
decision_output_ref: computeDecisionComponentRefV1('output', input.decision_output),
|
|
72
|
+
};
|
|
73
|
+
return { input: refInput, decision_ref: computeDecisionRefV1(refInput) };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=decision-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-ref.js","sourceRoot":"","sources":["../../../../src/v2/receipt-core/decision-ref.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JsonValue } from './types.js';
|
|
2
|
+
export declare class IJsonValidationError extends TypeError {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/** Validate the in-memory new-write input before RFC 8785 processing.
|
|
6
|
+
* No coercion is performed. In particular, undefined is not converted to null
|
|
7
|
+
* and Date is not converted to a string. */
|
|
8
|
+
export declare function assertIJson(value: unknown, path?: string, ancestors?: WeakSet<object>): asserts value is JsonValue;
|
|
9
|
+
export declare function strictJCS(value: unknown): string;
|
|
10
|
+
/** Parse bounded raw JSON without losing duplicate object names.
|
|
11
|
+
* Duplicate comparison is performed after JSON string decoding, so aliases
|
|
12
|
+
* such as "a" and "\u0061" are the same member name and are rejected. */
|
|
13
|
+
export declare function parseStrictIJson(raw: string, maxUtf8Bytes?: number, maxDepth?: number): JsonValue;
|
|
14
|
+
export declare function assertExactKeys(value: Record<string, unknown>, allowed: readonly string[], required: readonly string[], name: string): void;
|
|
15
|
+
//# sourceMappingURL=jcs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jcs.d.ts","sourceRoot":"","sources":["../../../../src/v2/receipt-core/jcs.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,qBAAa,oBAAqB,SAAQ,SAAS;IACjD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAmBD;;6CAE6C;AAC7C,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAM,EAAE,SAAS,kBAAwB,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAgCrH;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGhD;AAED;;0EAE0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,SAAY,EAAE,QAAQ,SAAM,GAAG,SAAS,CAiFjG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQ3I"}
|