@trustlayer-foundation/aria-sdk 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +7 -7
- package/README.md +154 -28
- package/package.json +19 -2
package/API.md
CHANGED
|
@@ -90,7 +90,7 @@ profiles. The level order is protocol, not configuration: `TRUST_LEVELS` lists t
|
|
|
90
90
|
lowest first and is frozen, so no consumer can reorder the ranking this verifier and
|
|
91
91
|
ARIA AP apply.
|
|
92
92
|
|
|
93
|
-
## Credential verification
|
|
93
|
+
## Credential verification
|
|
94
94
|
|
|
95
95
|
`verifyCredential(document)` accepts an object or JSON text up to 100 KB, works on a
|
|
96
96
|
private copy, and returns the first failure in this order:
|
|
@@ -105,7 +105,7 @@ private copy, and returns the first failure in this order:
|
|
|
105
105
|
5. both signature halves over the canonical document (`signature_invalid`);
|
|
106
106
|
6. strict RFC 3339 validity, ordered, current within the skew (`invalid_validity`,
|
|
107
107
|
`not_yet_valid`, `expired`);
|
|
108
|
-
7. the holder key: exactly 32 raw Ed25519 bytes in ARIA's own encoding
|
|
108
|
+
7. the holder key: exactly 32 raw Ed25519 bytes in ARIA's own encoding, under
|
|
109
109
|
the subject's DID, and acceptable by the authority's own rule — the canonical
|
|
110
110
|
encoding of a point, not of small order, torsion free
|
|
111
111
|
(`holder_key_invalid`). The identity point and other weak keys cannot establish
|
|
@@ -116,9 +116,9 @@ private copy, and returns the first failure in this order:
|
|
|
116
116
|
|
|
117
117
|
The result has no issuance time: `validFrom` and `validUntil` are the signed bounds and
|
|
118
118
|
`proof.created` is unsigned. `previousCredentialId` is returned as data and never fetched:
|
|
119
|
-
it relates a renewal to the credential before it
|
|
119
|
+
it relates a renewal to the credential before it, and the DID does not change.
|
|
120
120
|
|
|
121
|
-
## Status
|
|
121
|
+
## Status
|
|
122
122
|
|
|
123
123
|
`checkStatus(credential, { via })` concerns the exact document:
|
|
124
124
|
|
|
@@ -185,11 +185,11 @@ document is read under its own schema.
|
|
|
185
185
|
|
|
186
186
|
`spec_version` `"1.0"` (`schema/aid-1.0.json`, embedded byte for byte and checked by a
|
|
187
187
|
test) is the supported profile. Its holder key is 32 raw Ed25519 bytes under
|
|
188
|
-
`Ed25519VerificationKey2020` — ARIA's own encoding
|
|
188
|
+
`Ed25519VerificationKey2020` — ARIA's own encoding, `z` and base58btc of the raw
|
|
189
189
|
key, not the Multikey one; the SDK decodes exactly 32 bytes and projects `0xed01` only
|
|
190
190
|
when producing a Multikey. The proof metadata is outside the signed bytes: the SDK requires the supported
|
|
191
|
-
values, which does not make them signed
|
|
192
|
-
|
|
191
|
+
values, which does not make them signed. The suite is kept for 1.0: the dates that count are
|
|
192
|
+
the signed `validFrom` and `validUntil`, not `proof.created`.
|
|
193
193
|
|
|
194
194
|
## Package and runtimes
|
|
195
195
|
|
package/README.md
CHANGED
|
@@ -1,28 +1,154 @@
|
|
|
1
|
-
# ARIA SDK
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
status of that exact document.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
or
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
`
|
|
28
|
-
|
|
1
|
+
# ARIA SDK
|
|
2
|
+
|
|
3
|
+
`@trustlayer-foundation/aria-sdk` verifies an AI agent's ARIA credential (AID 1.0) and the
|
|
4
|
+
status of that exact document, under the issuers you choose to trust. It is the
|
|
5
|
+
TypeScript SDK of [ARIA 1.0](https://aria.bar/spec), for Node.js 20 or later, published by
|
|
6
|
+
TrustLayer Foundation under Apache-2.0.
|
|
7
|
+
|
|
8
|
+
## Which package do I need?
|
|
9
|
+
|
|
10
|
+
| You want to | Install |
|
|
11
|
+
|---|---|
|
|
12
|
+
| Show or record whether an agent's credential is genuine, current and not revoked | `@trustlayer-foundation/aria-sdk` |
|
|
13
|
+
| Decide whether an agent's request may run: authenticate it, admit it, run the operation once and sign its receipt; or call such a service as an agent | `@trustlayer-foundation/aria-sdk` and [`@trustlayer-foundation/aria-ap`](https://github.com/trustlayer-foundation/aria-protocol/tree/main/sdk/aria-ap-ts#readme) |
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @trustlayer-foundation/aria-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
[ARIA AP](https://github.com/trustlayer-foundation/aria-protocol/tree/main/sdk/aria-ap-ts#readme)
|
|
20
|
+
builds on this package's verifier and has no credential verification of its own. It
|
|
21
|
+
declares this package as a peer dependency, so a service that uses both installs both:
|
|
22
|
+
`npm install @trustlayer-foundation/aria-sdk @trustlayer-foundation/aria-ap`.
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
The SDK trusts no issuer by default. You state each issuer you accept in a trust profile.
|
|
27
|
+
Today's issuer, `did:aria:registry.aria.bar` behind [agent.bar](https://agent.bar), is a
|
|
28
|
+
demonstration: its credentials are not a production guarantee, and production ARIA 1.0
|
|
29
|
+
will use a new TrustLayer Foundation issuer and keys. It serves its keys at
|
|
30
|
+
`https://api.aria.bar/v1/keyset`. Being listed there grants no trust: you pin the anchor
|
|
31
|
+
fingerprint you obtained out of band, from the
|
|
32
|
+
[release manifest](https://github.com/trustlayer-foundation/aria-protocol/blob/main/release/aria-1.0.json),
|
|
33
|
+
and take the key it names. Save this as `quickstart.mjs` and run it with `node
|
|
34
|
+
quickstart.mjs`:
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import { canonicalJson, createVerifier } from '@trustlayer-foundation/aria-sdk';
|
|
38
|
+
|
|
39
|
+
/** A verifier trusting the key, in an issuer's published key set, that `pinned` names. */
|
|
40
|
+
export async function verifierFromKeyset({ keysetUrl, pinned, profile, fetch = globalThis.fetch }) {
|
|
41
|
+
const keyset = await (await fetch(keysetUrl, { redirect: 'error' })).json();
|
|
42
|
+
const entry = keyset.keys.find((k) => k.fingerprint === pinned && k.active_until === null);
|
|
43
|
+
if (!entry) throw new Error('the key set holds no active key with the pinned fingerprint');
|
|
44
|
+
const identity = canonicalJson({
|
|
45
|
+
key_id: entry.key_id,
|
|
46
|
+
suite: entry.suite,
|
|
47
|
+
public_key_mldsa65: entry.public_key_mldsa65,
|
|
48
|
+
public_key_ed25519: entry.public_key_ed25519,
|
|
49
|
+
});
|
|
50
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(identity));
|
|
51
|
+
if (`sha256:${Buffer.from(digest).toString('hex')}` !== pinned) throw new Error('the pinned key does not match');
|
|
52
|
+
return createVerifier({
|
|
53
|
+
...profile.verifier, // clock, fetch policy
|
|
54
|
+
trust: [{
|
|
55
|
+
id: profile.id, // 'demo' or 'production': your statement, not the issuer's
|
|
56
|
+
issuer: keyset.issuer,
|
|
57
|
+
verificationMethod: entry.key_id,
|
|
58
|
+
keys: { mldsa65: Buffer.from(entry.public_key_mldsa65, 'hex'), ed25519: Buffer.from(entry.public_key_ed25519, 'hex') },
|
|
59
|
+
maxLevel: profile.maxLevel,
|
|
60
|
+
statusLists: profile.statusLists,
|
|
61
|
+
}],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const verifier = await verifierFromKeyset({
|
|
66
|
+
keysetUrl: 'https://api.aria.bar/v1/keyset',
|
|
67
|
+
pinned: 'sha256:4117aaac21272740756d02305a9fa7e2d84398fdd859d390b476539d57ec67b3',
|
|
68
|
+
profile: {
|
|
69
|
+
id: 'demo',
|
|
70
|
+
maxLevel: 'L1',
|
|
71
|
+
statusLists: ['https://api.aria.bar/v1/status/1'],
|
|
72
|
+
verifier: { fetch: { allowedOrigins: ['https://api.aria.bar'] } },
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const credential = await (await fetch('https://api.aria.bar/v1/aids/did:aria:aria.bar:u-0dhNSrC9:commerce-search')).json();
|
|
77
|
+
const result = verifier.verifyCredential(credential);
|
|
78
|
+
if (!result.ok) throw new Error(`credential refused: ${result.reason}`);
|
|
79
|
+
const status = await verifier.checkStatus(result.credential);
|
|
80
|
+
const standing = verifier.standing(result.credential, status);
|
|
81
|
+
console.log(result.credential.did, result.credential.trustLevel, status.state, standing.state);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
It prints the agent's DID, its level, `active` and `good`. Alter one byte of either
|
|
85
|
+
signature half and `verifyCredential` refuses it with `signature_invalid`; pin another
|
|
86
|
+
fingerprint and the function throws.
|
|
87
|
+
|
|
88
|
+
## Trust is your configuration
|
|
89
|
+
|
|
90
|
+
A verifier trusts exactly the profiles it is created with. There is no global setting and
|
|
91
|
+
no embedded key. A profile states:
|
|
92
|
+
|
|
93
|
+
| Field | What you state |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `id` | Your name for this trust, such as `demo` or `production` |
|
|
96
|
+
| `issuer` | The issuer's DID |
|
|
97
|
+
| `verificationMethod` | The key id its proofs name, such as `did:aria:registry.aria.bar#key-1` |
|
|
98
|
+
| `keys` | Its two public keys, ML-DSA-65 and Ed25519, as bytes |
|
|
99
|
+
| `maxLevel` | The highest level you accept from it; a credential claiming more is refused |
|
|
100
|
+
| `statusLists` | The status lists it publishes; a credential naming another is refused |
|
|
101
|
+
| `onlineStatus` | Optional: an online status endpoint, asked only when you request it |
|
|
102
|
+
|
|
103
|
+
The fetch policy (`fetch.allowedOrigins`, timeouts, size bounds) bounds everything the SDK
|
|
104
|
+
fetches, and redirects are never followed. Without one, the verifier is offline and status
|
|
105
|
+
is `unavailable`. Credentials, status lists and online answers are untrusted input: nothing
|
|
106
|
+
in them selects a trust anchor or a fetch target.
|
|
107
|
+
|
|
108
|
+
## What each result tells you
|
|
109
|
+
|
|
110
|
+
| Call | Establishes | Does not establish |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| `verifyCredential(document)` returns `{ ok: true, credential }` or `{ ok: false, reason }` | The AID 1.0 schema; an issuer your profile names; the proof profile; both halves of the composite signature (ML-DSA-65 and Ed25519) over the canonical document; the signed validity window; the holder key; a level within your `maxLevel`; a status list in your `statusLists` | Who presents the credential; its status |
|
|
113
|
+
| `checkStatus(credential)` returns status evidence | The status of that exact document: `active` or `revoked` from the signed status list it names, verified under the same profile and fresh enough, or `unavailable` with a reason | Anything about another document of the same DID |
|
|
114
|
+
| `standing(credential, status)` | Whether that document stands now: `good`, `revoked`, `superseded`, `not_valid_now` or `unknown` | That anyone presents it, or may do anything with it |
|
|
115
|
+
| `inspectCredential(document)` | The fields a document carries, for display; `verified` is always `false` | Anything verified |
|
|
116
|
+
|
|
117
|
+
None of these results is permission to act. Whether an agent may do something is
|
|
118
|
+
decided by ARIA AP's admission, after the agent proves possession of its holder key.
|
|
119
|
+
`unknown` is not `good`. The SDK verifies credentials you hold; it is not a DID resolver.
|
|
120
|
+
|
|
121
|
+
## Documentation
|
|
122
|
+
|
|
123
|
+
- [API contract](https://github.com/trustlayer-foundation/aria-protocol/blob/main/sdk/aria-ts/API.md):
|
|
124
|
+
every result, failure reason, the trust boundary, status and historical authenticity.
|
|
125
|
+
- [Example: checking a credential and its standing](https://github.com/trustlayer-foundation/aria-protocol/blob/main/sdk/aria-ts/examples/verify-credential.ts).
|
|
126
|
+
- [Migration from `@aria-registry/verify` 1.x](https://github.com/trustlayer-foundation/aria-protocol/blob/main/sdk/aria-ts/MIGRATION.md),
|
|
127
|
+
which is no longer served by npm.
|
|
128
|
+
- [ARIA AP](https://github.com/trustlayer-foundation/aria-protocol/tree/main/sdk/aria-ap-ts#readme),
|
|
129
|
+
for requests, admission and receipts.
|
|
130
|
+
- [Developer guide](https://aria.bar/developers) and
|
|
131
|
+
[specification](https://aria.bar/spec).
|
|
132
|
+
- [Release manifest](https://github.com/trustlayer-foundation/aria-protocol/blob/main/release/aria-1.0.json):
|
|
133
|
+
the package integrities and the demonstration issuer's anchor.
|
|
134
|
+
- [Conformance vectors](https://github.com/trustlayer-foundation/aria-protocol/tree/main/conformance),
|
|
135
|
+
for any implementation.
|
|
136
|
+
|
|
137
|
+
## Support
|
|
138
|
+
|
|
139
|
+
- Questions and bugs:
|
|
140
|
+
[GitHub issues](https://github.com/trustlayer-foundation/aria-protocol/issues).
|
|
141
|
+
- Security vulnerabilities: security@trustlayer.foundation, never a public issue
|
|
142
|
+
([security policy](https://github.com/trustlayer-foundation/aria-protocol/blob/main/SECURITY.md)).
|
|
143
|
+
|
|
144
|
+
## Development
|
|
145
|
+
|
|
146
|
+
In the [repository](https://github.com/trustlayer-foundation/aria-protocol):
|
|
147
|
+
- `pnpm typecheck` compiles the sources, examples, tests and boundary checks.
|
|
148
|
+
- `pnpm test` runs the tests, with synthetic issuer keys made per run.
|
|
149
|
+
- `pnpm build` writes `dist/`.
|
|
150
|
+
- `node ../scripts/check-pair.mjs` packs this package and ARIA AP and checks both as
|
|
151
|
+
installed artifacts, alone and together.
|
|
152
|
+
|
|
153
|
+
The README that npm shows for a version is the one packed in it; this file is newer than
|
|
154
|
+
1.0.0's.
|
package/package.json
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trustlayer-foundation/aria-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "The ARIA SDK: inspect and verify an agent's credential and establish the status of that exact document. ARIA AP is the separate package built on it.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"aria",
|
|
7
|
+
"aria-protocol",
|
|
8
|
+
"ai-agents",
|
|
9
|
+
"agent-identity",
|
|
10
|
+
"verifiable-credentials",
|
|
11
|
+
"did",
|
|
12
|
+
"did-aria",
|
|
13
|
+
"credential-verification",
|
|
14
|
+
"status-list",
|
|
15
|
+
"post-quantum",
|
|
16
|
+
"ml-dsa",
|
|
17
|
+
"ed25519"
|
|
18
|
+
],
|
|
5
19
|
"license": "Apache-2.0",
|
|
6
20
|
"author": "TrustLayer Foundation",
|
|
7
|
-
"homepage": "https://aria
|
|
21
|
+
"homepage": "https://github.com/trustlayer-foundation/aria-protocol/tree/main/sdk/aria-ts#readme",
|
|
8
22
|
"repository": {
|
|
9
23
|
"type": "git",
|
|
10
24
|
"url": "git+https://github.com/trustlayer-foundation/aria-protocol.git",
|
|
11
25
|
"directory": "sdk/aria-ts"
|
|
12
26
|
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/trustlayer-foundation/aria-protocol/issues"
|
|
29
|
+
},
|
|
13
30
|
"type": "module",
|
|
14
31
|
"main": "./dist/index.js",
|
|
15
32
|
"types": "./dist/index.d.ts",
|