@trustlayer-foundation/aria-sdk 0.0.0-stage → 1.0.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/API.md +207 -0
- package/LICENSE +202 -0
- package/MIGRATION.md +86 -0
- package/README.md +27 -2
- package/dist/index.d.ts +435 -0
- package/dist/index.js +1029 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -3
- package/schemas/aid-1.0.json +394 -0
package/API.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# ARIA SDK 1.0 — API contract
|
|
2
|
+
|
|
3
|
+
Status: implemented, version 1.0.0: inspection, trust, credential verification,
|
|
4
|
+
exact-instance status and the trust interface ARIA AP works through.
|
|
5
|
+
|
|
6
|
+
This package verifies credentials and their status. Requests, admission, operations and
|
|
7
|
+
receipts are **ARIA AP**, the separate package in [`../aria-ap-ts`](../aria-ap-ts/API.md),
|
|
8
|
+
which builds on this one. A service that only checks credentials needs only this package.
|
|
9
|
+
|
|
10
|
+
## Results, kept apart
|
|
11
|
+
|
|
12
|
+
| Result | Says | Does not say |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `Inspection` (`inspectCredential`) | The fields a document carries | Anything verified: `verified` is always `false` |
|
|
15
|
+
| `VerifiedCredential` (`verifyCredential`) | This exact document conforms to its `spec_version`, is within its signed validity and verifies under a trusted issuer, both signature halves | Who presents it; its status |
|
|
16
|
+
| `StatusEvidence` (`checkStatus`) | The status of that exact document, its source, and its times | Anything about another document of the same DID |
|
|
17
|
+
| `Standing` (`standing`) | Whether that exact document stands now: valid, with fresh evidence of its status | That anyone presents it, or may do anything with it |
|
|
18
|
+
| `AuthenticCredential` (`verifyAuthenticity`) | A retained document verifies under a trusted issuer as `verifyCredential` checks it, except against the current time | That it is valid now, its status, or anything a current result says |
|
|
19
|
+
| `RetainedStatus` (`readRetainedStatus`) | What a retained, signed list said about that document during the list's own validity | Its status now |
|
|
20
|
+
|
|
21
|
+
None of them is a decision to run anything. Who presents a credential, and what they may
|
|
22
|
+
do, is ARIA AP's: its admission, not a field here, is what lets an operation run.
|
|
23
|
+
|
|
24
|
+
## Results are the verifier's own: runtime provenance
|
|
25
|
+
|
|
26
|
+
A result object is a deeply frozen **view**. The verifier that produced it keeps the
|
|
27
|
+
authoritative snapshot in private storage keyed by that object's identity, and every
|
|
28
|
+
consumer (`checkStatus`, `facts`, `standing`, and through them ARIA AP) reads the
|
|
29
|
+
snapshot, never the view's fields. Therefore:
|
|
30
|
+
|
|
31
|
+
- a spread copy, a copy with every own property and symbol, or a cast object is refused
|
|
32
|
+
(`AriaUsageError`), whatever it contains;
|
|
33
|
+
- a view cannot be altered in place: it is frozen, times are RFC 3339 strings and the
|
|
34
|
+
holder key is its multibase string (the 32 bytes stay inside the verifier);
|
|
35
|
+
- a result is accepted only by the verifier instance that produced it. A trust profile's
|
|
36
|
+
`id` (`demo`, `production`) is a label, not a trust identity: another verifier, even with
|
|
37
|
+
the same label or keys, refuses it;
|
|
38
|
+
- the trusted configuration is copied and frozen when the verifier is created; later
|
|
39
|
+
changes to the caller's key bytes or arrays change nothing;
|
|
40
|
+
- time-sensitive evidence is judged when it is used: `standing` judges at each call, so
|
|
41
|
+
a credential verified earlier can be expired at admission, and status evidence fresh
|
|
42
|
+
then can be stale now;
|
|
43
|
+
- two installed copies of this package are two separate records: each refuses the
|
|
44
|
+
other's results, so a duplicated install fails closed, never open.
|
|
45
|
+
|
|
46
|
+
Install one copy and create the verifier once per trust configuration; ARIA AP takes that
|
|
47
|
+
instance (`createAp({ credentials })`) instead of creating its own.
|
|
48
|
+
|
|
49
|
+
Types alone are not the boundary (a spread keeps the type); the runtime record is.
|
|
50
|
+
|
|
51
|
+
## Building on this package: `facts` and `standing`
|
|
52
|
+
|
|
53
|
+
ARIA AP, or any package built on this one, must reuse this verifier's work without
|
|
54
|
+
trusting a result's fields: a copy, a cast or another verifier's object carries the
|
|
55
|
+
same fields. Two methods are the whole interface:
|
|
56
|
+
|
|
57
|
+
- **`facts(credential)`** returns what the verifier recorded for one of its own
|
|
58
|
+
`VerifiedCredential` results: binding, DID, issuer, level, scopes, `hitlRequired`,
|
|
59
|
+
delegation depth, validity, and the holder key as its 32 raw bytes. Each call returns a
|
|
60
|
+
fresh copy; changing it changes nothing the verifier holds.
|
|
61
|
+
- **`standing(credential, status)`** judges, at the call and with the verifier's clock,
|
|
62
|
+
skew and maximum ages, whether that exact credential is inside its signed validity and
|
|
63
|
+
`status` is this verifier's evidence about that same result, available, fresh and
|
|
64
|
+
active. In order: `not_valid_now`; `unknown` (`other_document`, `unavailable`,
|
|
65
|
+
`stale`); `revoked`; `superseded`; `good`. Unknown is never good.
|
|
66
|
+
|
|
67
|
+
Both throw `AriaUsageError` for anything this verifier did not produce. What they return
|
|
68
|
+
is data and a judgment, not evidence: no entry point of this package or of ARIA AP
|
|
69
|
+
accepts them in place of a result. They exist so that a package built on this one never
|
|
70
|
+
reads a result's fields and never verifies a credential or its status a second time.
|
|
71
|
+
|
|
72
|
+
A result is evidence only inside the process and the verifier that produced it. Data
|
|
73
|
+
that crosses a process boundary is verified again where it arrives.
|
|
74
|
+
|
|
75
|
+
## Trust boundary
|
|
76
|
+
|
|
77
|
+
**Trusted configuration** — supplied by the adopter, never read from a message, copied
|
|
78
|
+
when the verifier is created: trust profiles (issuer DID, the `verificationMethod` its
|
|
79
|
+
proofs name, both public keys, highest level, the status lists it publishes, its online
|
|
80
|
+
status endpoint), the fetch policy (exact allowed origins, time and size bounds, the
|
|
81
|
+
fetch implementation; redirects are never followed), the clock, maximum status ages and
|
|
82
|
+
clock skew. ARIA AP adds its own (receiver identity, operations, stores, approvals).
|
|
83
|
+
|
|
84
|
+
**Untrusted input** — everything that arrives: credentials, status lists and online
|
|
85
|
+
answers. Nothing in them selects a trust anchor or a fetch target outside the allowed
|
|
86
|
+
origins.
|
|
87
|
+
|
|
88
|
+
There is no global configuration and nothing embedded: a verifier trusts exactly its
|
|
89
|
+
profiles. The level order is protocol, not configuration: `TRUST_LEVELS` lists the levels
|
|
90
|
+
lowest first and is frozen, so no consumer can reorder the ranking this verifier and
|
|
91
|
+
ARIA AP apply.
|
|
92
|
+
|
|
93
|
+
## Credential verification (S1)
|
|
94
|
+
|
|
95
|
+
`verifyCredential(document)` accepts an object or JSON text up to 100 KB, works on a
|
|
96
|
+
private copy, and returns the first failure in this order:
|
|
97
|
+
|
|
98
|
+
1. not a JSON object (`malformed`), `spec_version` other than `"1.0"` (`unsupported_version`);
|
|
99
|
+
2. the AID 1.0 schema (`malformed`, with a JSON pointer);
|
|
100
|
+
3. an issuer no profile names (`untrusted_issuer`);
|
|
101
|
+
4. proof metadata other than the profile's — `DataIntegrityProof`,
|
|
102
|
+
`mldsa65-ed25519-2026`, `assertionMethod`, the profile's `verificationMethod`
|
|
103
|
+
(`unsupported_proof`). These values are checked, not signed: the suite signs the
|
|
104
|
+
document without its `proof`;
|
|
105
|
+
5. both signature halves over the canonical document (`signature_invalid`);
|
|
106
|
+
6. strict RFC 3339 validity, ordered, current within the skew (`invalid_validity`,
|
|
107
|
+
`not_yet_valid`, `expired`);
|
|
108
|
+
7. the holder key: exactly 32 raw Ed25519 bytes in ARIA's own encoding (D6), under
|
|
109
|
+
the subject's DID, and acceptable by the authority's own rule — the canonical
|
|
110
|
+
encoding of a point, not of small order, torsion free
|
|
111
|
+
(`holder_key_invalid`). The identity point and other weak keys cannot establish
|
|
112
|
+
possession, so they are refused here, not only at issuance;
|
|
113
|
+
8. rules the schema cannot express: `hitlRequired` within `scope` (`semantic_invalid`);
|
|
114
|
+
9. a level above the profile's maximum (`level_not_trusted`);
|
|
115
|
+
10. a status list the profile does not publish (`status_list_untrusted`).
|
|
116
|
+
|
|
117
|
+
The result has no issuance time: `validFrom` and `validUntil` are the signed bounds and
|
|
118
|
+
`proof.created` is unsigned. `previousCredentialId` is returned as data and never fetched:
|
|
119
|
+
it relates a renewal to the credential before it (D11), and the DID does not change.
|
|
120
|
+
|
|
121
|
+
## Status (S1)
|
|
122
|
+
|
|
123
|
+
`checkStatus(credential, { via })` concerns the exact document:
|
|
124
|
+
|
|
125
|
+
- **`status-list`** (default) fetches the list the credential names, from an allowed
|
|
126
|
+
origin, and reads it only after it verifies under the same profile: issuer, proof
|
|
127
|
+
profile, both signatures, its signed `id` equal to the list the credential names
|
|
128
|
+
(another genuine list of the same issuer is refused), the supported subject
|
|
129
|
+
(`BitstringStatusList`, purpose `revocation`, one bit per entry), and `encodedList` as
|
|
130
|
+
multibase `u` + base64url GZIP, decompressed within 2 MiB and at least 131,072 entries.
|
|
131
|
+
Its times are then judged at completion, not when the request started: a validity
|
|
132
|
+
window of at most 24 hours that holds now, and an age from its own signed `validFrom`
|
|
133
|
+
within `statusMaxAgeSeconds` (default 3600). `fetchedAt` is that completion time,
|
|
134
|
+
reported apart from the list's signed times.
|
|
135
|
+
- **`online`** asks the profile's `onlineStatus` endpoint for the DID. Only a complete
|
|
136
|
+
answer counts — the DID, an exact document reference and a status; anything less is
|
|
137
|
+
`unavailable`. It has no signed time, is stamped when observed, is only as strong as
|
|
138
|
+
TLS to that configured endpoint, and `standing` treats it as fresh for
|
|
139
|
+
`onlineStatusMaxAgeSeconds` (default 60). A complete answer naming another current
|
|
140
|
+
document makes the presented one `superseded`; a revocation bit never does.
|
|
141
|
+
- Anything not established is `unavailable` with a reason (`offline`, `origin_not_allowed`,
|
|
142
|
+
`fetch_failed`, `too_large`, `malformed`, `signature_invalid`, `wrong_issuer`,
|
|
143
|
+
`not_valid_now`, `stale`, `no_online_endpoint`); its standing is `unknown`, which ARIA AP's
|
|
144
|
+
admission treats as `indeterminate`.
|
|
145
|
+
|
|
146
|
+
## Historical authenticity
|
|
147
|
+
|
|
148
|
+
Checking a past statement (an ARIA AP receipt signed by a receiver whose credential has
|
|
149
|
+
since expired) needs the document's authenticity, not its current validity. Three
|
|
150
|
+
methods give that, apart from everything that judges a credential now:
|
|
151
|
+
|
|
152
|
+
- **`verifyAuthenticity(document)`** runs the checks of `verifyCredential` in the same
|
|
153
|
+
order except `not_yet_valid` and `expired`: shape, version, schema, issuer, proof
|
|
154
|
+
profile, both signature halves, a validity interval, holder key, rules, level and
|
|
155
|
+
trusted status list. Its result is an `AuthenticCredential`, a provenance record of
|
|
156
|
+
its own kind: `facts`, `standing` and `checkStatus` refuse it, and so does everything
|
|
157
|
+
in ARIA AP that admits or signs.
|
|
158
|
+
- **`readRetainedStatus(credential, list)`** reads a retained list offline, as
|
|
159
|
+
`checkStatus` reads a fetched one (issuer, the exact list the credential names, both
|
|
160
|
+
signatures, the supported subject, at most 24 hours of validity), but never judges its
|
|
161
|
+
times against now: it reports them. A `RetainedStatus` is not status evidence.
|
|
162
|
+
- **`historicalFacts(credential, status?)`** is the read path, like `facts`: binding,
|
|
163
|
+
DID, holder key bytes, validity, and what the retained list said. It refuses anything
|
|
164
|
+
this verifier did not produce and a retained status about another document.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
const authentic = verifier.verifyAuthenticity(retainedDocument);
|
|
168
|
+
if (authentic.ok) {
|
|
169
|
+
const read = await verifier.readRetainedStatus(authentic.credential, retainedList);
|
|
170
|
+
// ARIA AP: ap.verifyHistoricalReceipt(receipt, { attempts, evidence: { credential: authentic.credential, status } })
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## `did:aria` identifiers
|
|
175
|
+
|
|
176
|
+
`parseDid(value)` returns the parts of a `did:aria` identifier, or `null`: one of the
|
|
177
|
+
four shapes of specification §3.1 (`agent-domain-form`, `agent-registry-form`,
|
|
178
|
+
`principal-domain-form`, `principal-registry-form`), with its domain or registry host,
|
|
179
|
+
account and agent name. It applies the same rules as the authority's parser and passes
|
|
180
|
+
the 22 shared cases in `conformance/vectors/abnf-cases.json`. Use it for identifiers being
|
|
181
|
+
created or compared; verifying a credential does not apply it, since a signed 1.0
|
|
182
|
+
document is read under its own schema.
|
|
183
|
+
|
|
184
|
+
## Credential profile
|
|
185
|
+
|
|
186
|
+
`spec_version` `"1.0"` (`schema/aid-1.0.json`, embedded byte for byte and checked by a
|
|
187
|
+
test) is the supported profile. Its holder key is 32 raw Ed25519 bytes under
|
|
188
|
+
`Ed25519VerificationKey2020` — ARIA's own encoding (D6), `z` and base58btc of the raw
|
|
189
|
+
key, not the Multikey one; the SDK decodes exactly 32 bytes and projects `0xed01` only
|
|
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 (D12: the suite is kept for 1.0; the dates that
|
|
192
|
+
count are the signed `validFrom` and `validUntil`, not `proof.created`).
|
|
193
|
+
|
|
194
|
+
## Package and runtimes
|
|
195
|
+
|
|
196
|
+
- ESM only, with type declarations; `exports` has the package entry, `package.json`, and
|
|
197
|
+
`schemas/aid-1.0.json`, a byte-identical copy of the protocol's schema, so that schemas
|
|
198
|
+
referring to it (ARIA AP's identity response) compile outside this repository.
|
|
199
|
+
The dependencies are `@noble/curves`, `@noble/hashes`, `@noble/post-quantum`, `ajv` and
|
|
200
|
+
`ajv-formats`.
|
|
201
|
+
- Node.js 20 and 22: everything (declared; the artifact check in
|
|
202
|
+
[`../scripts/check-pair.mjs`](../scripts/check-pair.mjs) runs on the Node.js it is given).
|
|
203
|
+
- Browsers and edge runtimes: offline credential checks, with two limits: the schema
|
|
204
|
+
validator compiles code at run time, which a strict Content Security Policy forbids,
|
|
205
|
+
and network status checks there cannot enforce private-network restrictions.
|
|
206
|
+
|
|
207
|
+
The package has no install scripts and reads no environment file.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# From `@aria-registry/verify` 1.x to the ARIA SDK 1.0 and ARIA AP
|
|
2
|
+
|
|
3
|
+
`@aria-registry/verify` 1.x is replaced by two packages in the same repository:
|
|
4
|
+
|
|
5
|
+
- **the ARIA SDK** (this package, `@trustlayer-foundation/aria-sdk`) for credentials
|
|
6
|
+
and their status;
|
|
7
|
+
- **ARIA AP** (`@trustlayer-foundation/aria-ap`, [`../aria-ap-ts`](../aria-ap-ts/README.md))
|
|
8
|
+
for authenticating requests, admitting them and receipts. It builds on the ARIA SDK's
|
|
9
|
+
verifier.
|
|
10
|
+
|
|
11
|
+
A credential-only consumer migrates to the first; a consumer that decides whether an
|
|
12
|
+
agent may do something needs both. `@aria-registry/verify` 1.x is no
|
|
13
|
+
longer served by npm; its source stays in `sdk/verify-ts/` for reference.
|
|
14
|
+
|
|
15
|
+
## The one change that matters
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// 1.x
|
|
19
|
+
const result = verifyAgent(credential, { policy });
|
|
20
|
+
if (result.valid) execute();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`valid` could be `true` with the signature check skipped, with the requested policy
|
|
24
|
+
failed, with the status never checked, and with nobody proving the holder key. It was
|
|
25
|
+
never a decision to run anything, and there is no compatibility wrapper that keeps it.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// 1.0: authenticate, then admit; only `allow` runs
|
|
29
|
+
const verifier = createVerifier({ trust }); // @trustlayer-foundation/aria-sdk
|
|
30
|
+
const ap = createAp({ credentials: verifier }); // @trustlayer-foundation/aria-ap
|
|
31
|
+
const presented = await ap.verifyPresentation(request, context);
|
|
32
|
+
if (!presented.ok) return presented.status;
|
|
33
|
+
const status = await verifier.checkStatus(presented.presentation.credential);
|
|
34
|
+
const admission = await ap.admit({ presentation: presented.presentation, status, authorize });
|
|
35
|
+
if (admission.decision !== 'allow') return admission.refusal.status;
|
|
36
|
+
await execute();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
An operation that must happen once, or that the caller needs a receipt for, runs
|
|
40
|
+
through ARIA AP's `OperationLedger` (see `../aria-ap-ts/examples/protected-handler.ts`).
|
|
41
|
+
|
|
42
|
+
A consumer that only displays or records whether a credential is genuine and current
|
|
43
|
+
uses `verifyCredential`, `checkStatus` and `standing` (see `examples/verify-credential.ts`),
|
|
44
|
+
and must not treat the answer as permission to act.
|
|
45
|
+
|
|
46
|
+
## Field by field
|
|
47
|
+
|
|
48
|
+
| 1.x | 1.0 |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `verifyAgent(c)` | `createVerifier({ trust }).verifyCredential(c)`; status and admission are separate calls |
|
|
51
|
+
| `verifyAgent(c, { skipSignatureCheck: true })` | `inspectCredential(c)`: returns an `Inspection`, never a verified result |
|
|
52
|
+
| `setRegistryKeys(...)`, embedded registry keys | `createVerifier({ trust: [profile] })`: explicit, per verifier, nothing global or embedded |
|
|
53
|
+
| `result.valid` | `CredentialResult.ok` for the document only; `standing(...).state === 'good'` for now; ARIA AP's `Admission.decision === 'allow'` to run |
|
|
54
|
+
| `result.reason` (free text) | fixed reasons: `CredentialFailure`, `StatusUnavailable`, standing states; in ARIA AP, `RequestInvalidReason`, `AuthenticationReason`, `AdmissionReason` |
|
|
55
|
+
| `result.signatures.pqValid/classicalValid` | both required; a failure is `signature_invalid` |
|
|
56
|
+
| `result.expired` | `not_yet_valid`, `expired` or `invalid_validity`, with strict instants |
|
|
57
|
+
| `result.issuedAt` | `validFrom` (signed, RFC 3339 string). There is no issuance time: `proof.created` is not signed |
|
|
58
|
+
| `result.expiresAt` | `validUntil` |
|
|
59
|
+
| `result.credentialId`, `previousCredentialId` | `credential.binding.credentialId`; `credential.previousCredentialId` as data, never fetched |
|
|
60
|
+
| `result.revocationStatus`, `revocationCheckedAt` | `checkStatus(credential)` → `StatusEvidence` with source, signed list times and `fetchedAt` |
|
|
61
|
+
| `checkRevocation(did)` | removed: it asked about a DID, not the presented document |
|
|
62
|
+
| `checkCredentialStatus(c, { via })` | `checkStatus(credential, { via: 'status-list' \| 'online' })`; the online endpoint is the profile's `onlineStatus` |
|
|
63
|
+
| `policy.requiredScopes`, `minTrustLevel` | ARIA AP: `OperationDescriptor.scope`, `minLevel`, enforced by `admit` |
|
|
64
|
+
| `policy.requireRevocationCheck`, `lastRevocationCheck`, `maxOfflineAge` | `statusMaxAgeSeconds`, from the signed list's `validFrom`, judged by `standing` at use; a fresh fetch time is not evidence |
|
|
65
|
+
| `result.hitlRequired` | `credential.hitlRequired`, a declaration; the approval is ARIA AP's `ApprovalEvidence` at `admit` |
|
|
66
|
+
| `PolicyLevel` presets | none: each operation states its level and scope |
|
|
67
|
+
| `canonicalJson` | `canonicalJson`, the ARIA canonical form (INVARIANTS §3) |
|
|
68
|
+
| results as plain objects you could copy or edit | frozen views the producing verifier recognises by identity; copies and other verifiers' results throw `AriaUsageError` |
|
|
69
|
+
|
|
70
|
+
## What the old characterizations become
|
|
71
|
+
|
|
72
|
+
The 1.x probes recorded behaviors; they are not all defects. In the 1.0 tests:
|
|
73
|
+
|
|
74
|
+
- **kept as controls**: a valid baseline passes schema and both signatures; altered signed
|
|
75
|
+
content and an expired credential are refused;
|
|
76
|
+
- **turned into rejections**: not-yet-valid, invalid or inverted validity bounds, a
|
|
77
|
+
missing holder key, the skipped signature check (now inspection only), a failed
|
|
78
|
+
requested scope (now an ARIA AP `deny`), a revoked status discarded by the old recipe
|
|
79
|
+
(now `revoked` standing and an ARIA AP `deny`), unsupported proof metadata (refused,
|
|
80
|
+
still unsigned);
|
|
81
|
+
- **checked at their own layer**: a copied credential still verifies as a document but
|
|
82
|
+
cannot be admitted without its holder key; offline verification succeeds with unknown
|
|
83
|
+
status and an `unknown` standing, while an ARIA AP admission that needs status is
|
|
84
|
+
`indeterminate`;
|
|
85
|
+
- **schema versus rules**: the schema alone accepts `hitlRequired` outside `scope`; the
|
|
86
|
+
SDK refuses it as `semantic_invalid`.
|
package/README.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ARIA SDK (TypeScript)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The ARIA SDK for ARIA 1.0: inspect and verify an agent's credential, and establish the
|
|
4
|
+
status of that exact document.
|
|
5
|
+
|
|
6
|
+
**Version 1.0.0.** This directory holds the API contract and its implementation:
|
|
7
|
+
inspection, per-verifier trust, credential verification, exact-instance status, and the
|
|
8
|
+
trust interface packages built on it use. It trusts no issuer by default: each verifier
|
|
9
|
+
states the issuers it accepts.
|
|
10
|
+
|
|
11
|
+
**Which package.** This repository has two SDK packages. A service that only checks
|
|
12
|
+
credentials installs this one. A service that authenticates agent requests, admits them
|
|
13
|
+
or exchanges receipts also installs [ARIA AP](../aria-ap-ts/README.md), which builds on
|
|
14
|
+
this package's verifier and has none of its own. `@aria-registry/verify` 1.x is no
|
|
15
|
+
longer served by npm; see the migration guide.
|
|
16
|
+
|
|
17
|
+
- [API contract](API.md): the results, runtime provenance, `facts` and `standing`, the
|
|
18
|
+
trust boundary, credential and status verification, historical authenticity, the
|
|
19
|
+
credential profile, runtimes.
|
|
20
|
+
- [Migration from `@aria-registry/verify` 1.x](MIGRATION.md).
|
|
21
|
+
- `examples/verify-credential.ts`: checking a credential and its standing, which is not
|
|
22
|
+
admitting a request.
|
|
23
|
+
- `test-d/`: the boundaries the types enforce.
|
|
24
|
+
|
|
25
|
+
`pnpm typecheck` compiles the sources, examples, tests and boundary checks; `pnpm test`
|
|
26
|
+
runs the tests, with synthetic issuer keys made per run; `pnpm build` writes `dist/`.
|
|
27
|
+
`node ../scripts/check-pair.mjs` packs this package and ARIA AP and checks both as
|
|
28
|
+
installed artifacts, alone and together.
|