@agentidentitytrustprotocol/aitp 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +160 -0
- package/index.d.ts +403 -0
- package/index.js +327 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# aitp — Node.js SDK
|
|
2
|
+
|
|
3
|
+
Node.js bindings for the **Agent Identity & Trust Protocol (AITP)**, built on
|
|
4
|
+
the pure-Rust `aitp-rs` protocol crates via [NAPI-rs](https://napi.rs).
|
|
5
|
+
|
|
6
|
+
A thin SDK: an `AitpAgent` plus initiator/responder session objects whose
|
|
7
|
+
methods take and return JSON strings — the HTTP request/response bodies — so
|
|
8
|
+
agent code never handles a Rust type across the FFI boundary. The API is the
|
|
9
|
+
symmetric counterpart of the Python SDK (`buildManifest` ↔ `build_manifest`).
|
|
10
|
+
|
|
11
|
+
## Build
|
|
12
|
+
|
|
13
|
+
This crate is **not** part of the `aitp-rs` Cargo workspace. Build it with
|
|
14
|
+
the [NAPI-rs CLI](https://napi.rs):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
npm run build:debug # default `.node` (v0.1 surface only)
|
|
19
|
+
npm run build:experimental:debug # default + post-v0.1 features
|
|
20
|
+
# Release:
|
|
21
|
+
npm run build # default release
|
|
22
|
+
npm run build:experimental # default + experimental, release
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This produces `aitp.node` and `index.js` in the package root. Generated
|
|
26
|
+
TypeScript typings (`index.d.ts`) include the experimental surface only
|
|
27
|
+
when the artifact was built with the `experimental` feature.
|
|
28
|
+
|
|
29
|
+
### Cargo features
|
|
30
|
+
|
|
31
|
+
The default `.node` exposes the v0.1 surface (handshake, TCT, delegation,
|
|
32
|
+
manifest verify, revocation-list signing, OIDC identity). Three post-v0.1
|
|
33
|
+
capabilities live behind opt-in Cargo features:
|
|
34
|
+
|
|
35
|
+
| Feature | Enables | RFC |
|
|
36
|
+
|---------------------------|--------------------------------------------------------------------------|----------------------|
|
|
37
|
+
| `experimental-renewal` | `AitpAgent.buildRenewalRequest` / `processRenewalRequest` | RFC-AITP-0005 §10 |
|
|
38
|
+
| `experimental-bundle` | `SessionBundleBuilder`, `verifySessionBundle` | RFC-AITP-0010 |
|
|
39
|
+
| `experimental-pinning` | `computeSpkiHash`, `SpkiPinVerifier` | HPKP (RFC 7469) |
|
|
40
|
+
| `experimental-multihop-delegation` | `verifyDelegationExperimentalMultihop` | RFC-AITP-0011 |
|
|
41
|
+
| `experimental` (umbrella) | All four above | |
|
|
42
|
+
|
|
43
|
+
Each post-v0.1 capability does **not** promise wire stability until the
|
|
44
|
+
underlying RFC graduates.
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import { AitpAgent } from '@agentidentitytrustprotocol/aitp';
|
|
50
|
+
|
|
51
|
+
const initiator = AitpAgent.generate();
|
|
52
|
+
const responder = AitpAgent.generate();
|
|
53
|
+
|
|
54
|
+
initiator.buildManifest({
|
|
55
|
+
displayName: 'initiator',
|
|
56
|
+
handshakeEndpoint: 'http://localhost:8100/aitp/handshake/',
|
|
57
|
+
offeredCaps: ['demo.echo'],
|
|
58
|
+
});
|
|
59
|
+
const respManifest = responder.buildManifest({
|
|
60
|
+
displayName: 'responder',
|
|
61
|
+
handshakeEndpoint: 'http://localhost:8200/aitp/handshake/',
|
|
62
|
+
offeredCaps: ['demo.write'],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Four-message mutual handshake — each call's output is the next peer's input.
|
|
66
|
+
const sess = initiator.newSession();
|
|
67
|
+
const rsess = responder.newResponder();
|
|
68
|
+
|
|
69
|
+
const hello = sess.buildHello(respManifest, ['demo.write']);
|
|
70
|
+
const { ackJson: helloAck, sessionId } = rsess.processHello(hello);
|
|
71
|
+
const commit = sess.processHelloAck(helloAck, sessionId);
|
|
72
|
+
const { ackJson: commitAck } = rsess.processCommit(commit);
|
|
73
|
+
const initiatorHeldTct = sess.complete(commitAck);
|
|
74
|
+
|
|
75
|
+
// Each peer now holds a TCT the other issued it.
|
|
76
|
+
const ident = initiator.verifyTct(initiatorHeldTct, 'demo.write');
|
|
77
|
+
console.log(ident.peerAid, ident.grants);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
In a real deployment each message moves over HTTP: `buildHello` returns the
|
|
81
|
+
`POST /aitp/handshake/hello` body, `processHello` returns the response body
|
|
82
|
+
plus the value for the `X-Aitp-Session-Id` header, and so on.
|
|
83
|
+
|
|
84
|
+
## API
|
|
85
|
+
|
|
86
|
+
The full public surface is described in the generated `index.d.ts`; below
|
|
87
|
+
is a summary. All `*Json` parameters and return values are JSON strings.
|
|
88
|
+
|
|
89
|
+
| Type | Default? | Notes |
|
|
90
|
+
|---------------------------|:--------:|----------------------------------------------------------------------------------------------------------------|
|
|
91
|
+
| `AitpAgent` | ✅ | `generate(opts?)` / `fromSeed(buffer, opts?)` (`opts.suite = "ed25519" \| "p256"`), `aid`, `buildManifest(opts)`, `newSession(jwks?, opts?)`, `newResponder(jwks?, opts?)`, `verifyTct(...)`, `buildDelegation(...)`, `issueTctForDelegatee(...)`, `signRevocationList(...)` |
|
|
92
|
+
| `InitiatorSession` | ✅ | `buildHello(peerManifest, grants, oidcMintJwt?)`, `processHelloAck(...)`, `complete(...)` |
|
|
93
|
+
| `ResponderSession` | ✅ | `processHello(hello, oidcMintJwt?)` → `{ ackJson, sessionId }`, `processCommit(commit)` → `{ ackJson, tctJson }` |
|
|
94
|
+
| `TctIdentity` | ✅ | `peerAid`, `grants`, `expiresAt`, `jti` |
|
|
95
|
+
| `DelegationVerified` | ✅ | `delegator`, `delegatee`, `issuedBy`, `grants`, `expiresAt`, `cnf` |
|
|
96
|
+
| `JwksProvider` | ✅ | OIDC JWKS map. `upsert(issuer, keys)`, `remove(issuer)`, `issuers()` |
|
|
97
|
+
| `TctStore` / `verifyTctCached()` | ✅ | Hot-path verify cache: skips the signature check for a byte-identical, still-valid TCT (keyed by SHA-256 of the envelope) |
|
|
98
|
+
| `verifyDelegation()` | ✅ | RFC-AITP-0006 — strict v0.1 single-hop; rejects any multi-hop `chain` |
|
|
99
|
+
| `verifyManifestJson()` | ✅ | Control-plane manifest enrollment |
|
|
100
|
+
| `buildRenewalRequest()` / `processRenewalRequest()` | `experimental-renewal` | RFC-AITP-0005 §10 |
|
|
101
|
+
| `SessionBundleBuilder`, `verifySessionBundle()` | `experimental-bundle` | RFC-AITP-0010 |
|
|
102
|
+
| `computeSpkiHash()`, `SpkiPinVerifier` | `experimental-pinning` | HPKP outbound pinning |
|
|
103
|
+
| `verifyDelegationExperimentalMultihop()` | `experimental-multihop-delegation` | RFC-AITP-0011 (draft) multi-hop opt-in |
|
|
104
|
+
|
|
105
|
+
### OIDC identity (RFC-AITP-0002)
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
import { AitpAgent, JwksProvider } from '@agentidentitytrustprotocol/aitp';
|
|
109
|
+
|
|
110
|
+
const jwks = new JwksProvider({
|
|
111
|
+
'https://idp.example/': [{ kty: 'OKP', crv: 'Ed25519', x: '...', kid: 'k1', alg: 'EdDSA' }],
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const agent = AitpAgent.generate();
|
|
115
|
+
agent.buildManifest({
|
|
116
|
+
displayName: 'alice',
|
|
117
|
+
handshakeEndpoint: 'https://alice.example/aitp/handshake/',
|
|
118
|
+
offeredCaps: ['demo.echo'],
|
|
119
|
+
identityType: 'oidc',
|
|
120
|
+
oidcIssuer: 'https://idp.example/',
|
|
121
|
+
oidcSubject: 'alice',
|
|
122
|
+
});
|
|
123
|
+
const sess = agent.newSession(jwks);
|
|
124
|
+
|
|
125
|
+
const mintJwt = (nonce) => myIdp.mintJwtSync({ nonce, sub: 'alice', aud: peerAid });
|
|
126
|
+
const hello = sess.buildHello(peerManifest, ['demo.echo'], mintJwt);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### P-256 signing (RFC-AITP-0001 §5.4.3)
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
const agent = AitpAgent.generate({ suite: 'p256' }); // aid:pubkey:p256:<44>
|
|
133
|
+
// Deterministic from a seed:
|
|
134
|
+
const seeded = AitpAgent.fromSeed(seed, { suite: 'p256' });
|
|
135
|
+
// All other methods identical; signatures emitted as `p256.<86b64u>`.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> **Breaking change in v0.2:** `AitpAgent.generateP256()` and
|
|
139
|
+
> `AitpAgent.fromP256Seed(seed)` were removed in favor of the
|
|
140
|
+
> parameterized `generate({ suite })` / `fromSeed(seed, { suite })`
|
|
141
|
+
> API. This matches the Python SDK's
|
|
142
|
+
> `AitpAgent.generate(suite="p256")` shape — CLAUDE.md mandates SDK
|
|
143
|
+
> symmetry. Migration: replace `generateP256()` with
|
|
144
|
+
> `generate({ suite: 'p256' })` and `fromP256Seed(seed)` with
|
|
145
|
+
> `fromSeed(seed, { suite: 'p256' })`.
|
|
146
|
+
|
|
147
|
+
> **Note.** In v0.1 the `pinned_key` identity_hint embeds an Ed25519 raw
|
|
148
|
+
> public key. P-256 agents must therefore use `identityType: 'oidc'` until
|
|
149
|
+
> the manifest's identity_hint shape is extended.
|
|
150
|
+
|
|
151
|
+
## Tests
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npm install
|
|
155
|
+
npm run build:debug
|
|
156
|
+
npm test # node --test tests/*.mjs
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The cross-language interop suite (Python ↔ Node) lives in
|
|
160
|
+
[`../interop`](../interop) — run it with `make interop` from the repo root.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Input shape for `signRevocationList`. Field names map to spec
|
|
8
|
+
* `RevocationEntry` (jti, revoked_at, reason).
|
|
9
|
+
*/
|
|
10
|
+
export interface RevocationEntryInput {
|
|
11
|
+
/** JTI of the revoked TCT (UUID string). */
|
|
12
|
+
jti: string
|
|
13
|
+
/**
|
|
14
|
+
* Unix seconds when the issuing peer revoked the TCT.
|
|
15
|
+
* Defaults to the current time when omitted.
|
|
16
|
+
*/
|
|
17
|
+
revokedAt?: number
|
|
18
|
+
/** Optional human-readable reason. Not used in trust decisions. */
|
|
19
|
+
reason?: string
|
|
20
|
+
}
|
|
21
|
+
/** Options for `buildManifest`. */
|
|
22
|
+
export interface ManifestOpts {
|
|
23
|
+
/** Human-readable agent name; also the pinned-key identity subject. */
|
|
24
|
+
displayName: string
|
|
25
|
+
/** Absolute URL of this agent's handshake endpoint. */
|
|
26
|
+
handshakeEndpoint: string
|
|
27
|
+
/** Capabilities this agent offers to peers. */
|
|
28
|
+
offeredCaps: Array<string>
|
|
29
|
+
/** Capabilities a peer must grant back (optional). */
|
|
30
|
+
requiredCaps?: Array<string>
|
|
31
|
+
/** Manifest TTL in seconds (optional; defaults to 3600). */
|
|
32
|
+
ttlSecs?: number
|
|
33
|
+
/** Identity presentation type — `"pinned_key"` (default) or `"oidc"`. */
|
|
34
|
+
identityType?: string
|
|
35
|
+
/** OIDC issuer URL (required when `identityType="oidc"`). */
|
|
36
|
+
oidcIssuer?: string
|
|
37
|
+
/** OIDC subject identifier (required when `identityType="oidc"`). */
|
|
38
|
+
oidcSubject?: string
|
|
39
|
+
/**
|
|
40
|
+
* Override the manifest's accepted_trust_anchors list. Defaults to
|
|
41
|
+
* `[oidc_issuer]` for OIDC mode and `[]` for pinned-key mode.
|
|
42
|
+
*/
|
|
43
|
+
acceptedTrustAnchors?: Array<string>
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Trust-anchor override for `newSession` / `newResponder`.
|
|
47
|
+
*
|
|
48
|
+
* JWKS provider is passed as a separate argument (napi-rs can't put a
|
|
49
|
+
* class reference inside an `#[napi(object)]` struct).
|
|
50
|
+
*/
|
|
51
|
+
export interface SessionOpts {
|
|
52
|
+
/**
|
|
53
|
+
* Override the agent manifest's accepted_trust_anchors. `null`
|
|
54
|
+
* reuses the manifest's list.
|
|
55
|
+
*/
|
|
56
|
+
trustAnchors?: Array<string>
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Options for `AitpAgent.generate` and `AitpAgent.fromSeed`.
|
|
60
|
+
*
|
|
61
|
+
* Mirrors the Python SDK's `suite="ed25519"|"p256"` keyword argument so
|
|
62
|
+
* the two SDKs share one shape per operation. `null`/omitted defaults
|
|
63
|
+
* to `"ed25519"`.
|
|
64
|
+
*/
|
|
65
|
+
export interface GenerateOpts {
|
|
66
|
+
/**
|
|
67
|
+
* Signing suite. Accepted values: `"ed25519"` (default) or
|
|
68
|
+
* `"p256"` (RFC-AITP-0001 §5.4.3).
|
|
69
|
+
*/
|
|
70
|
+
suite?: string
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Outcome shape returned by `verifySessionBundle`. `kind` is `"clear"`
|
|
74
|
+
* or `"degraded"`; `droppedAids` is empty in the `"clear"` case.
|
|
75
|
+
*/
|
|
76
|
+
export interface JsBundleOutcome {
|
|
77
|
+
kind: string
|
|
78
|
+
activeAids: Array<string>
|
|
79
|
+
droppedAids: Array<string>
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Verify a `SessionBundleEnvelope` JSON. `nowUnixSecs` defaults to
|
|
83
|
+
* the system clock. `revocationCheck` receives a JTI string and
|
|
84
|
+
* returns true if revoked.
|
|
85
|
+
*/
|
|
86
|
+
export declare function verifySessionBundle(bundleEnvelopeJson: string, verifierAid: string, nowUnixSecs?: number | undefined | null, revocationCheck?: (...args: any[]) => any | undefined | null): JsBundleOutcome
|
|
87
|
+
/**
|
|
88
|
+
* The verified delegation token's salient fields. Returned from
|
|
89
|
+
* `verifyDelegation` and consumed by `AitpAgent.issueTctForDelegatee`.
|
|
90
|
+
*/
|
|
91
|
+
export interface JsDelegationVerified {
|
|
92
|
+
/**
|
|
93
|
+
* AID of the ultimate grantor (the original TCT issuer that gave grants
|
|
94
|
+
* to `issuedBy`). The responder side checks this matches its own AID
|
|
95
|
+
* before redeeming.
|
|
96
|
+
*/
|
|
97
|
+
delegator: string
|
|
98
|
+
/** AID of the recipient (C) — who will receive a fresh TCT. */
|
|
99
|
+
delegatee: string
|
|
100
|
+
/** AID of the agent that issued this delegation (B in the RFC). */
|
|
101
|
+
issuedBy: string
|
|
102
|
+
/** Capabilities being delegated. Always a subset of the source TCT's grants. */
|
|
103
|
+
grants: Array<string>
|
|
104
|
+
/** Unix-seconds expiry of the delegation token itself. */
|
|
105
|
+
expiresAt: number
|
|
106
|
+
/**
|
|
107
|
+
* Delegatee's raw Ed25519 / P-256 public key, base64url-encoded. This is
|
|
108
|
+
* the `cnf` binding — proves which key the issuer should bind to the
|
|
109
|
+
* fresh TCT it mints.
|
|
110
|
+
*/
|
|
111
|
+
cnf: string
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Verify a `DelegationEnvelope` JSON under **strict AITP v0.1**
|
|
115
|
+
* (RFC-AITP-0006 single-hop). `verifierAid` is the verifier's own AID
|
|
116
|
+
* string — verification fails if it doesn't match the token's `delegator`
|
|
117
|
+
* field.
|
|
118
|
+
*
|
|
119
|
+
* Any token carrying a non-empty `chain` (a draft RFC-AITP-0011 multi-hop
|
|
120
|
+
* delegation) is **rejected** with `DELEGATION_MULTIHOP_NOT_SUPPORTED`,
|
|
121
|
+
* matching the Rust core default. To opt into multi-hop, build the SDK with
|
|
122
|
+
* the `experimental-multihop-delegation` feature and call
|
|
123
|
+
* `verifyDelegationExperimentalMultihop`.
|
|
124
|
+
*/
|
|
125
|
+
export declare function verifyDelegation(envelopeJson: string, verifierAid: string): JsDelegationVerified
|
|
126
|
+
/**
|
|
127
|
+
* Verify a `DelegationEnvelope` JSON allowing **draft RFC-AITP-0011
|
|
128
|
+
* multi-hop** chains up to `maxHops` total hops (`chain.length + 1`).
|
|
129
|
+
*
|
|
130
|
+
* This opts into behavior that is **not** part of AITP v0.1. It is only
|
|
131
|
+
* compiled in under the `experimental-multihop-delegation` feature; a
|
|
132
|
+
* default build exposes only the strict `verifyDelegation`.
|
|
133
|
+
*
|
|
134
|
+
* `maxHops` defaults to `DEFAULT_MAX_HOPS` (3, the RFC-AITP-0011 §2
|
|
135
|
+
* recommended ceiling). Pass a smaller value for a tighter bound;
|
|
136
|
+
* `maxHops = 0` reverts to strict v0.1 (rejects any non-empty chain).
|
|
137
|
+
*/
|
|
138
|
+
export declare function verifyDelegationExperimentalMultihop(envelopeJson: string, verifierAid: string, maxHops?: number | undefined | null): JsDelegationVerified
|
|
139
|
+
/**
|
|
140
|
+
* Compute the RFC 7638 JWK thumbprint of the public key embedded in
|
|
141
|
+
* an AID — the value an OIDC IdP MUST place in the JWT's `cnf.jkt`
|
|
142
|
+
* claim when proving the key binding (RFC-AITP-0002 §2.2.1).
|
|
143
|
+
*
|
|
144
|
+
* Works for both Ed25519 (`aid:pubkey:ed25519:...`) and P-256
|
|
145
|
+
* (`aid:pubkey:p256:...`) AIDs. Use this from your OIDC minter
|
|
146
|
+
* closure so the bound peer correctly verifies the cnf binding —
|
|
147
|
+
* implementing curve arithmetic by hand to derive the thumbprint
|
|
148
|
+
* in JavaScript is both error-prone and a divergence risk.
|
|
149
|
+
*/
|
|
150
|
+
export declare function computeAidJkt(aid: string): string
|
|
151
|
+
/**
|
|
152
|
+
* Compute the SHA-256 SPKI hash for an X.509 DER certificate. Returns
|
|
153
|
+
* a 32-byte Buffer. Throws if `certDer` is not a parseable certificate.
|
|
154
|
+
*/
|
|
155
|
+
export declare function computeSpkiHash(certDer: Buffer): Buffer
|
|
156
|
+
/** Result of `processHello`: response body plus session id. */
|
|
157
|
+
export interface JsHelloAckResult {
|
|
158
|
+
/** `MUTUAL_HELLO_ACK` envelope JSON — set as the HTTP response body. */
|
|
159
|
+
ackJson: string
|
|
160
|
+
/** Correlation id — set as the `X-Aitp-Session-Id` response header. */
|
|
161
|
+
sessionId: string
|
|
162
|
+
}
|
|
163
|
+
/** Result of `processCommit`: response body plus the held TCT. */
|
|
164
|
+
export interface JsCommitAckResult {
|
|
165
|
+
/** `MUTUAL_COMMIT_ACK` envelope JSON — set as the HTTP response body. */
|
|
166
|
+
ackJson: string
|
|
167
|
+
/** `TctEnvelope` JSON the initiator issued to us. */
|
|
168
|
+
tctJson: string
|
|
169
|
+
}
|
|
170
|
+
/** The verified peer identity carried by a TCT. */
|
|
171
|
+
export interface JsTctIdentity {
|
|
172
|
+
/** AID of the agent that issued (and is bound by) the TCT. */
|
|
173
|
+
peerAid: string
|
|
174
|
+
/** Capability grants the TCT authorizes. */
|
|
175
|
+
grants: Array<string>
|
|
176
|
+
/** Expiry, Unix seconds. */
|
|
177
|
+
expiresAt: number
|
|
178
|
+
/** TCT unique identifier (`jti`). */
|
|
179
|
+
jti: string
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Verify a `ManifestEnvelope` JSON string. Throws on signature,
|
|
183
|
+
* proof-of-possession, expiry, or identity-hint shape failures.
|
|
184
|
+
* Used by the AITP Control Plane during agent enrollment.
|
|
185
|
+
*/
|
|
186
|
+
export declare function verifyManifestJson(manifestEnvelopeJson: string): void
|
|
187
|
+
/** An AITP agent: a signing key and (once built) its Manifest. */
|
|
188
|
+
export declare class AitpAgent {
|
|
189
|
+
/**
|
|
190
|
+
* Generate an agent with a fresh random signing key.
|
|
191
|
+
*
|
|
192
|
+
* `opts.suite` selects the algorithm — `"ed25519"` (default) or
|
|
193
|
+
* `"p256"`. Symmetric with the Python SDK's
|
|
194
|
+
* `AitpAgent.generate(suite="ed25519")`.
|
|
195
|
+
*
|
|
196
|
+
* ```ts
|
|
197
|
+
* const ed = AitpAgent.generate(); // Ed25519
|
|
198
|
+
* const p = AitpAgent.generate({ suite: 'p256' }); // P-256
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
static generate(opts?: GenerateOpts | undefined | null): AitpAgent
|
|
202
|
+
/**
|
|
203
|
+
* Construct an agent from a 32-byte seed (deterministic).
|
|
204
|
+
*
|
|
205
|
+
* `opts.suite` matches `AitpAgent.generate`. For `"p256"`, a tiny
|
|
206
|
+
* fraction of 32-byte seeds are not valid private scalars (zero
|
|
207
|
+
* or ≥ curve order) and raise.
|
|
208
|
+
*
|
|
209
|
+
* Note: the prior `AitpAgent.fromP256Seed` factory and the
|
|
210
|
+
* no-arg `AitpAgent.generate*` variants were removed in favor of
|
|
211
|
+
* this parameterized API so the Node SDK matches the Python SDK
|
|
212
|
+
* surface (CLAUDE.md mandates SDK symmetry).
|
|
213
|
+
*/
|
|
214
|
+
static fromSeed(seed: Buffer, opts?: GenerateOpts | undefined | null): AitpAgent
|
|
215
|
+
/** The agent's AID string (`aid:pubkey:...`). */
|
|
216
|
+
get aid(): string
|
|
217
|
+
/**
|
|
218
|
+
* Build and sign the agent's Manifest. Returns `ManifestEnvelope`
|
|
219
|
+
* JSON and caches the Manifest for `newSession` / `newResponder`.
|
|
220
|
+
*
|
|
221
|
+
* See `ManifestOpts.identityType` for the OIDC switch.
|
|
222
|
+
*/
|
|
223
|
+
buildManifest(opts: ManifestOpts): string
|
|
224
|
+
/**
|
|
225
|
+
* Create a new outbound (initiator) handshake session.
|
|
226
|
+
*
|
|
227
|
+
* `jwks` is an optional `JwksProvider` used when the peer's
|
|
228
|
+
* manifest advertises an OIDC identity. `opts.trustAnchors`
|
|
229
|
+
* overrides the manifest's `accepted_trust_anchors`.
|
|
230
|
+
*/
|
|
231
|
+
newSession(jwks?: JwksProvider | undefined | null, opts?: SessionOpts | undefined | null): JsInitiatorSession
|
|
232
|
+
/**
|
|
233
|
+
* Create a new inbound (responder) handshake session. Mirror of
|
|
234
|
+
* `newSession`.
|
|
235
|
+
*/
|
|
236
|
+
newResponder(jwks?: JwksProvider | undefined | null, opts?: SessionOpts | undefined | null): JsResponderSession
|
|
237
|
+
/**
|
|
238
|
+
* Verify a TCT JSON string and require `requiredGrant`. Rejects on
|
|
239
|
+
* an invalid, mis-audienced, expired, or under-scoped TCT.
|
|
240
|
+
*
|
|
241
|
+
* `expectedAudience` defaults to `null`, which means "verify as the
|
|
242
|
+
* holder" (RFC-AITP-0005 §9 receipt model — `this.aid` is used).
|
|
243
|
+
* Resource servers verifying a TCT presented by a peer should pass
|
|
244
|
+
* the TCT's own `audience` field as `expectedAudience` (in v0.1 this
|
|
245
|
+
* equals `subject`).
|
|
246
|
+
*/
|
|
247
|
+
verifyTct(tctJson: string, requiredGrant: string, expectedAudience?: string | undefined | null): JsTctIdentity
|
|
248
|
+
/**
|
|
249
|
+
* Like `verifyTct`, but consults a `TctStore` first: a byte-identical,
|
|
250
|
+
* already-verified, still-valid TCT skips the signature check (the
|
|
251
|
+
* verification hot path for an agent that sees the same TCT on many
|
|
252
|
+
* requests). All cheap policy checks (expiry, audience, required grant)
|
|
253
|
+
* still run on every call; only the signature check is elided.
|
|
254
|
+
*/
|
|
255
|
+
verifyTctCached(tctJson: string, requiredGrant: string, store: JsTctStore, expectedAudience?: string | undefined | null): JsTctIdentity
|
|
256
|
+
/** Build a `DelegationEnvelope` JSON from a held TCT (RFC-AITP-0006). */
|
|
257
|
+
buildDelegation(heldTctEnvelopeJson: string, delegateeAid: string, delegateePubkeyB64U: string, scope: Array<string>, ttlSecs?: number | undefined | null): string
|
|
258
|
+
/**
|
|
259
|
+
* Mint a fresh `TctEnvelope` JSON for a delegatee after the verifier has
|
|
260
|
+
* confirmed the delegation. The subject_pubkey binding is taken from the
|
|
261
|
+
* verified token's `cnf` field.
|
|
262
|
+
*/
|
|
263
|
+
issueTctForDelegatee(verified: JsDelegationVerified, ttlSecs?: number | undefined | null): string
|
|
264
|
+
/**
|
|
265
|
+
* Sign a `RevocationList` with this agent's key. `entries` carries
|
|
266
|
+
* the revoked-TCT records; `expiresInSecs` defaults to 3600 s.
|
|
267
|
+
* Returns the on-wire `RevocationListEnvelope` JSON.
|
|
268
|
+
*/
|
|
269
|
+
signRevocationList(entries: Array<RevocationEntryInput>, expiresInSecs?: number | undefined | null): string
|
|
270
|
+
/**
|
|
271
|
+
* Holder side: build a `TctRenewalPayload` JSON for an in-band
|
|
272
|
+
* renewal of `currentTctEnvelopeJson` (RFC-AITP-0005 §10).
|
|
273
|
+
*
|
|
274
|
+
* **Gated by the `experimental-renewal` Cargo feature.** Off in
|
|
275
|
+
* the default `.node` artifact; build with
|
|
276
|
+
* `napi build --release -- --features experimental-renewal`.
|
|
277
|
+
*/
|
|
278
|
+
buildRenewalRequest(currentTctEnvelopeJson: string): string
|
|
279
|
+
/**
|
|
280
|
+
* Issuer side: verify a `TctRenewalPayload` JSON request and mint a
|
|
281
|
+
* fresh `TctEnvelope` JSON.
|
|
282
|
+
*
|
|
283
|
+
* **Gated by the `experimental-renewal` Cargo feature.**
|
|
284
|
+
*/
|
|
285
|
+
processRenewalRequest(requestPayloadJson: string, manifestExpUnixSecs: number, newTtlSecs: number): string
|
|
286
|
+
}
|
|
287
|
+
export type SessionBundleBuilderJs = SessionBundleBuilder
|
|
288
|
+
/**
|
|
289
|
+
* Fluent builder for issuing a `SessionBundleEnvelope`. Constructed
|
|
290
|
+
* from the coordinator's `AitpAgent`.
|
|
291
|
+
*
|
|
292
|
+
* The Rust struct is suffixed `Js` to avoid a name collision with the
|
|
293
|
+
* `aitp_session_bundle::SessionBundleBuilder` imported above; the
|
|
294
|
+
* `#[napi(js_name)]` attribute exposes it to JavaScript under the
|
|
295
|
+
* plain name `SessionBundleBuilder` for parity with the Python SDK.
|
|
296
|
+
*/
|
|
297
|
+
export declare class SessionBundleBuilder {
|
|
298
|
+
/** Construct a builder backed by `coordinator`'s signing key. */
|
|
299
|
+
constructor(coordinator: AitpAgent)
|
|
300
|
+
/** Set the session ID (UUIDv4 string). Defaults to a fresh one. */
|
|
301
|
+
sessionId(uuidStr: string): this
|
|
302
|
+
/** Override `issued_at` (unix seconds). Defaults to "now" at build. */
|
|
303
|
+
issuedAt(unixSecs: number): this
|
|
304
|
+
/** Add a participant entry. `tctEnvelopeJson` is a TctEnvelope JSON. */
|
|
305
|
+
participant(aid: string, tctEnvelopeJson: string): this
|
|
306
|
+
/** Construct, sign, and return the `SessionBundleEnvelope` JSON. */
|
|
307
|
+
build(): string
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* In-memory OIDC JWKS provider — issuer URL → list of JWK objects.
|
|
311
|
+
*
|
|
312
|
+
* The Node caller fetches the JWKS (the SDK has no HTTP client) and
|
|
313
|
+
* hands the parsed objects to this provider. Implements `JwksResolver`
|
|
314
|
+
* internally so the handshake state machine can dispatch through it.
|
|
315
|
+
*/
|
|
316
|
+
export declare class JwksProvider {
|
|
317
|
+
/**
|
|
318
|
+
* Construct from an object mapping issuer URLs to arrays of JWK
|
|
319
|
+
* objects. Each JWK must be a standard RFC 7517 representation
|
|
320
|
+
* (`kty`, `crv`, `x`, ...). Pass `{}` for an empty provider and
|
|
321
|
+
* `upsert` later.
|
|
322
|
+
*/
|
|
323
|
+
constructor(keys?: unknown | undefined | null)
|
|
324
|
+
/**
|
|
325
|
+
* Add or replace the JWKs for an issuer. `keys` is a JS array of
|
|
326
|
+
* JWK objects.
|
|
327
|
+
*/
|
|
328
|
+
upsert(issuer: string, keys: unknown): void
|
|
329
|
+
/** Drop all keys for an issuer. */
|
|
330
|
+
remove(issuer: string): void
|
|
331
|
+
/** Return the issuer URLs currently registered. */
|
|
332
|
+
issuers(): Array<string>
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Holds a list of 32-byte SPKI pins. `isPinned(certDer)` returns true
|
|
336
|
+
* iff the cert's SPKI hash is in the list.
|
|
337
|
+
*/
|
|
338
|
+
export declare class SpkiPinVerifier {
|
|
339
|
+
/**
|
|
340
|
+
* Construct from an array of 32-byte Buffers. Throws if any pin is
|
|
341
|
+
* not exactly 32 bytes.
|
|
342
|
+
*/
|
|
343
|
+
constructor(pins: Array<Buffer>)
|
|
344
|
+
/** Returns true iff the SPKI hash of `certDer` is in the pin list. */
|
|
345
|
+
isPinned(certDer: Buffer): boolean
|
|
346
|
+
/** Number of pins currently held. */
|
|
347
|
+
get len(): number
|
|
348
|
+
}
|
|
349
|
+
/** Outbound handshake session — drives the initiator side. */
|
|
350
|
+
export declare class JsInitiatorSession {
|
|
351
|
+
/**
|
|
352
|
+
* Step 1 — build the `MUTUAL_HELLO` envelope.
|
|
353
|
+
*
|
|
354
|
+
* `oidcMintJwt`: required for OIDC agents. Receives the handshake-
|
|
355
|
+
* generated `pop_nonce` (string) and must return the JWT (string).
|
|
356
|
+
*/
|
|
357
|
+
buildHello(peerManifestJson: string, requestedGrants: Array<string>, oidcMintJwt?: (...args: any[]) => any | undefined | null): string
|
|
358
|
+
/** Step 2 — process `MUTUAL_HELLO_ACK`, produce `MUTUAL_COMMIT`. */
|
|
359
|
+
processHelloAck(helloAckJson: string, sessionId: string): string
|
|
360
|
+
/**
|
|
361
|
+
* Step 3 — process `MUTUAL_COMMIT_ACK`. Returns the `TctEnvelope`
|
|
362
|
+
* JSON the peer issued to us.
|
|
363
|
+
*/
|
|
364
|
+
complete(commitAckJson: string): string
|
|
365
|
+
}
|
|
366
|
+
/** Inbound handshake session — drives the responder side. */
|
|
367
|
+
export declare class JsResponderSession {
|
|
368
|
+
/**
|
|
369
|
+
* Process an incoming `MUTUAL_HELLO` envelope.
|
|
370
|
+
*
|
|
371
|
+
* `oidcMintJwt`: required for OIDC agents (see `JsInitiatorSession.buildHello`).
|
|
372
|
+
*/
|
|
373
|
+
processHello(helloJson: string, oidcMintJwt?: (...args: any[]) => any | undefined | null): JsHelloAckResult
|
|
374
|
+
/** Process an incoming `MUTUAL_COMMIT` envelope. */
|
|
375
|
+
processCommit(commitJson: string): JsCommitAckResult
|
|
376
|
+
}
|
|
377
|
+
export type JsTctStore = TctStore
|
|
378
|
+
/**
|
|
379
|
+
* A bounded, in-memory cache of **successful** TCT verifications, keyed by
|
|
380
|
+
* the SHA-256 of the exact TCT envelope JSON bytes.
|
|
381
|
+
*
|
|
382
|
+
* Purpose: a high-throughput verifier (e.g. a writer agent checking a
|
|
383
|
+
* capability on every request) that repeatedly sees the *same* TCT can skip
|
|
384
|
+
* the Ed25519/P-256 signature verification after the first time.
|
|
385
|
+
*
|
|
386
|
+
* **Safety.** The key is a cryptographic hash of the exact signed bytes, so
|
|
387
|
+
* only a byte-identical envelope — whose signature was already verified once
|
|
388
|
+
* — can hit. A tampered token hashes differently, misses, and is fully
|
|
389
|
+
* verified. The cheap policy checks (expiry, audience, required grant) are
|
|
390
|
+
* re-run on **every** hit; only the signature check is elided. Eviction is
|
|
391
|
+
* FIFO once `maxEntries` is reached.
|
|
392
|
+
*/
|
|
393
|
+
export declare class TctStore {
|
|
394
|
+
/**
|
|
395
|
+
* Create a cache holding at most `maxEntries` verified TCTs (FIFO
|
|
396
|
+
* eviction). `maxEntries` must be >= 1.
|
|
397
|
+
*/
|
|
398
|
+
constructor(maxEntries: number)
|
|
399
|
+
/** Number of cached verifications currently held. */
|
|
400
|
+
len(): number
|
|
401
|
+
/** Drop all cached entries. */
|
|
402
|
+
clear(): void
|
|
403
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'aitp.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./aitp.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'aitp.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./aitp.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'aitp.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./aitp.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'aitp.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./aitp.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'aitp.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./aitp.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'aitp.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./aitp.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'aitp.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./aitp.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'aitp.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./aitp.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'aitp.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./aitp.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'aitp.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./aitp.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'aitp.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./aitp.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'aitp.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./aitp.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'aitp.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./aitp.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'aitp.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./aitp.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'aitp.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./aitp.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'aitp.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./aitp.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'aitp.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./aitp.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'aitp.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./aitp.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('@agentidentitytrustprotocol/aitp-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { AitpAgent, SessionBundleBuilder, verifySessionBundle, verifyDelegation, verifyDelegationExperimentalMultihop, computeAidJkt, JwksProvider, computeSpkiHash, SpkiPinVerifier, JsInitiatorSession, JsResponderSession, TctStore, verifyManifestJson } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.AitpAgent = AitpAgent
|
|
316
|
+
module.exports.SessionBundleBuilder = SessionBundleBuilder
|
|
317
|
+
module.exports.verifySessionBundle = verifySessionBundle
|
|
318
|
+
module.exports.verifyDelegation = verifyDelegation
|
|
319
|
+
module.exports.verifyDelegationExperimentalMultihop = verifyDelegationExperimentalMultihop
|
|
320
|
+
module.exports.computeAidJkt = computeAidJkt
|
|
321
|
+
module.exports.JwksProvider = JwksProvider
|
|
322
|
+
module.exports.computeSpkiHash = computeSpkiHash
|
|
323
|
+
module.exports.SpkiPinVerifier = SpkiPinVerifier
|
|
324
|
+
module.exports.JsInitiatorSession = JsInitiatorSession
|
|
325
|
+
module.exports.JsResponderSession = JsResponderSession
|
|
326
|
+
module.exports.TctStore = TctStore
|
|
327
|
+
module.exports.verifyManifestJson = verifyManifestJson
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentidentitytrustprotocol/aitp",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Agent Identity Trust Protocol — Node.js SDK",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/agentidentitytrustprotocol/aitp-rs.git",
|
|
9
|
+
"directory": "bindings/aitp-node"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/agentidentitytrustprotocol/aitp-rs/tree/main/bindings/aitp-node",
|
|
12
|
+
"main": "index.js",
|
|
13
|
+
"types": "index.d.ts",
|
|
14
|
+
"type": "commonjs",
|
|
15
|
+
"files": [
|
|
16
|
+
"index.js",
|
|
17
|
+
"index.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"napi": {
|
|
20
|
+
"name": "aitp",
|
|
21
|
+
"triples": {
|
|
22
|
+
"defaults": false,
|
|
23
|
+
"additional": [
|
|
24
|
+
"x86_64-apple-darwin",
|
|
25
|
+
"aarch64-apple-darwin",
|
|
26
|
+
"x86_64-unknown-linux-gnu",
|
|
27
|
+
"aarch64-unknown-linux-gnu"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "napi build --platform --release",
|
|
33
|
+
"build:debug": "napi build --platform",
|
|
34
|
+
"build:experimental": "napi build --platform --release --features experimental",
|
|
35
|
+
"build:experimental:debug": "napi build --platform --features experimental",
|
|
36
|
+
"artifacts": "napi artifacts",
|
|
37
|
+
"prepublishOnly": "napi prepublish -t npm",
|
|
38
|
+
"version": "napi version",
|
|
39
|
+
"test": "node --test tests/*.mjs"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@napi-rs/cli": "^2.18.0",
|
|
43
|
+
"node-forge": "^1.4.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=16"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"jose": "^6.2.3"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public",
|
|
53
|
+
"registry": "https://registry.npmjs.org/"
|
|
54
|
+
},
|
|
55
|
+
"optionalDependencies": {
|
|
56
|
+
"@agentidentitytrustprotocol/aitp-darwin-x64": "0.2.0",
|
|
57
|
+
"@agentidentitytrustprotocol/aitp-darwin-arm64": "0.2.0",
|
|
58
|
+
"@agentidentitytrustprotocol/aitp-linux-x64-gnu": "0.2.0",
|
|
59
|
+
"@agentidentitytrustprotocol/aitp-linux-arm64-gnu": "0.2.0"
|
|
60
|
+
}
|
|
61
|
+
}
|