@terminal3/t3n-sdk 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +207 -2
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/src/client/delegation.d.ts +216 -0
- package/dist/src/client/index.d.ts +1 -0
- package/dist/src/index.d.ts +2 -0
- package/package.json +4 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-to-Agent Delegation (T3-TS-030).
|
|
3
|
+
*
|
|
4
|
+
* TypeScript reference implementation of the delegation credential and
|
|
5
|
+
* envelope shapes defined in `node/tee_contracts/delegation-types`.
|
|
6
|
+
*
|
|
7
|
+
* The wire shape is byte-for-byte identical to the Rust source — pinned
|
|
8
|
+
* by the KAT fixtures under `tests/kat/`. Specifically:
|
|
9
|
+
*
|
|
10
|
+
* - `not_before_secs` / `not_after_secs` / `batch_cap_cents` are
|
|
11
|
+
* emitted as **JSON strings** (e.g. `"1700086400"`) so JS Number
|
|
12
|
+
* precision never enters the canonicalisation surface.
|
|
13
|
+
* - `nonce` (16 B), `vc_id` (16 B), `request_hash` (32 B),
|
|
14
|
+
* `agent_pubkey` (33 B compressed secp256k1), `user_sig`,
|
|
15
|
+
* `agent_sig` are emitted as **base64url-no-pad** strings.
|
|
16
|
+
* - `org_did` / `user_did` are emitted as `did:t3n:<40-hex>` (the
|
|
17
|
+
* `CompactDid` `Display` form).
|
|
18
|
+
*
|
|
19
|
+
* Canonicalisation uses the npm `canonicalize` package (RFC 8785 JCS).
|
|
20
|
+
* Cryptography uses `@noble/curves` (secp256k1) and `@noble/hashes`
|
|
21
|
+
* (sha256, keccak_256).
|
|
22
|
+
*/
|
|
23
|
+
/** Domain tag carried in `DelegationCredential.v`. */
|
|
24
|
+
export declare const DELEGATION_CREDENTIAL_DOMAIN: "ot3.delegation/1";
|
|
25
|
+
/** Domain tag prepended to the agent-side pre-image. */
|
|
26
|
+
export declare const DELEGATION_INVOCATION_DOMAIN: "ot3.invocation/1";
|
|
27
|
+
export declare const VC_ID_LEN = 16;
|
|
28
|
+
export declare const NONCE_LEN = 16;
|
|
29
|
+
export declare const REQUEST_HASH_LEN = 32;
|
|
30
|
+
export declare const AGENT_PUBKEY_LEN = 33;
|
|
31
|
+
export declare const ETH_SIG_LEN = 65;
|
|
32
|
+
export declare const MAX_CONTRACT_LEN = 46;
|
|
33
|
+
export declare const MAX_FUNCTION_LEN = 64;
|
|
34
|
+
export declare const MAX_SCOPE_LEN = 64;
|
|
35
|
+
export declare const MAX_SCOPES_PER_CREDENTIAL = 32;
|
|
36
|
+
export declare const MAX_METADATA_PER_CREDENTIAL = 16;
|
|
37
|
+
export declare const MAX_METADATA_KEY_LEN = 64;
|
|
38
|
+
export declare const MAX_METADATA_VALUE_LEN = 256;
|
|
39
|
+
/** User-to-agent delegation credential body. */
|
|
40
|
+
export interface DelegationCredential {
|
|
41
|
+
/** Domain tag, must equal {@link DELEGATION_CREDENTIAL_DOMAIN}. */
|
|
42
|
+
v: string;
|
|
43
|
+
/** `did:t3n:<40-hex>` user DID. */
|
|
44
|
+
user_did: string;
|
|
45
|
+
/** 33-byte compressed secp256k1 public key the agent uses per call. */
|
|
46
|
+
agent_pubkey: Uint8Array;
|
|
47
|
+
/** `did:t3n:<40-hex>` org DID. */
|
|
48
|
+
org_did: string;
|
|
49
|
+
/** Contract id, e.g. `"tee:payroll"`. */
|
|
50
|
+
contract: string;
|
|
51
|
+
/** Function name, e.g. `"run-payroll"`. */
|
|
52
|
+
function: string;
|
|
53
|
+
/** Org-data scopes the contract may read on this user's behalf. */
|
|
54
|
+
scopes: string[];
|
|
55
|
+
/** Flat key-value labels checked against the org grant. */
|
|
56
|
+
metadata: Record<string, string>;
|
|
57
|
+
/** Inclusive lower bound of the validity window (unix seconds). */
|
|
58
|
+
not_before_secs: bigint;
|
|
59
|
+
/** Inclusive upper bound of the validity window (unix seconds). */
|
|
60
|
+
not_after_secs: bigint;
|
|
61
|
+
/** Random 16-byte credential id. */
|
|
62
|
+
vc_id: Uint8Array;
|
|
63
|
+
}
|
|
64
|
+
/** Envelope wrapping a contract-specific request body. */
|
|
65
|
+
export interface DelegationEnvelope {
|
|
66
|
+
/** RFC 8785 JCS bytes of the credential, exactly as signed. */
|
|
67
|
+
credential_jcs: Uint8Array;
|
|
68
|
+
/** 65-byte EIP-191 signature over `credential_jcs`. */
|
|
69
|
+
user_sig: Uint8Array;
|
|
70
|
+
/** Per-call agent signature over the invocation pre-image. */
|
|
71
|
+
agent_sig: Uint8Array;
|
|
72
|
+
/** 16-byte agent-generated per-call nonce. */
|
|
73
|
+
nonce: Uint8Array;
|
|
74
|
+
/** SHA-256 of the canonical request body. */
|
|
75
|
+
request_hash: Uint8Array;
|
|
76
|
+
}
|
|
77
|
+
/** Payroll-specific request body wrapped by a delegation envelope. */
|
|
78
|
+
export interface PayrollRunRequest {
|
|
79
|
+
/** `did:t3n:<40-hex>` org id. */
|
|
80
|
+
org_id: string;
|
|
81
|
+
cycle_id: string;
|
|
82
|
+
pay_period_start: string;
|
|
83
|
+
pay_period_end: string;
|
|
84
|
+
/** Total cap on the run's net disbursement, in cents. */
|
|
85
|
+
batch_cap_cents: bigint;
|
|
86
|
+
/** `employee_id` → previous-cycle baseline net disbursement, cents (decimal string). */
|
|
87
|
+
historical_baselines: Record<string, string>;
|
|
88
|
+
}
|
|
89
|
+
/** Convenience wrapper paired with the matching delegation envelope. */
|
|
90
|
+
export interface PayrollInvocation {
|
|
91
|
+
envelope: DelegationEnvelope;
|
|
92
|
+
request: PayrollRunRequest;
|
|
93
|
+
}
|
|
94
|
+
/** Response from `tee:delegation.sign`. */
|
|
95
|
+
export interface SignDelegationResponse {
|
|
96
|
+
credential_jcs: Uint8Array;
|
|
97
|
+
user_sig: Uint8Array;
|
|
98
|
+
}
|
|
99
|
+
declare function b64uEncode(input: Uint8Array): string;
|
|
100
|
+
declare function b64uDecode(input: string): Uint8Array;
|
|
101
|
+
/**
|
|
102
|
+
* Encode raw bytes to base64url-no-pad (RFC 4648 §5 with padding
|
|
103
|
+
* dropped). The same encoding T3-TS-030 wire-shape uses for binary
|
|
104
|
+
* fields (`agent_pubkey`, `vc_id`, `nonce`, `agent_sig`, `user_sig`,
|
|
105
|
+
* `request_hash`, `credential_jcs`).
|
|
106
|
+
*
|
|
107
|
+
* Public API since v2.2: callers building `PayrollInvocation` JSON
|
|
108
|
+
* for the wire (e.g. the t3n-mcp `runPayroll` handler) need this
|
|
109
|
+
* encoder to match the contract's deserializer.
|
|
110
|
+
*/
|
|
111
|
+
export declare function b64uEncodeBytes(input: Uint8Array): string;
|
|
112
|
+
/**
|
|
113
|
+
* Decode a base64url-no-pad string. Strict — rejects standard-alphabet
|
|
114
|
+
* `+` / `/` and any padding `=`.
|
|
115
|
+
*/
|
|
116
|
+
export declare function b64uDecodeStrict(input: string): Uint8Array;
|
|
117
|
+
/** @internal — preserved alias for in-tree callers. Prefer
|
|
118
|
+
* {@link b64uEncodeBytes} / {@link b64uDecodeStrict}. */
|
|
119
|
+
export declare const _b64uEncode: typeof b64uEncode;
|
|
120
|
+
/** @internal — preserved alias for in-tree callers. Prefer
|
|
121
|
+
* {@link b64uEncodeBytes} / {@link b64uDecodeStrict}. */
|
|
122
|
+
export declare const _b64uDecode: typeof b64uDecode;
|
|
123
|
+
/** Build a `did:t3n:<40-hex>` from raw 20 bytes. */
|
|
124
|
+
export declare function compactDidFromBytes(bytes: Uint8Array): string;
|
|
125
|
+
/**
|
|
126
|
+
* Canonicalise a {@link DelegationCredential} to RFC 8785 JCS bytes.
|
|
127
|
+
*
|
|
128
|
+
* Output is byte-identical to the Rust `canonicalise_credential` in
|
|
129
|
+
* `delegation-types` (pinned by `tests/kat/credential.json`).
|
|
130
|
+
*/
|
|
131
|
+
export declare function canonicaliseCredential(credential: DelegationCredential): Uint8Array;
|
|
132
|
+
/** Canonicalise an arbitrary {@link PayrollRunRequest} to JCS bytes. */
|
|
133
|
+
export declare function canonicaliseRequest(request: PayrollRunRequest): Uint8Array;
|
|
134
|
+
/** SHA-256 of the canonicalised request body. */
|
|
135
|
+
export declare function requestHash(request: PayrollRunRequest): Uint8Array;
|
|
136
|
+
/**
|
|
137
|
+
* Build the agent-side pre-image bytes:
|
|
138
|
+
* `utf8(DELEGATION_INVOCATION_DOMAIN) || vc_id || nonce || request_hash`.
|
|
139
|
+
*
|
|
140
|
+
* SHA-256 of these bytes is what the agent's secp256k1 signature is
|
|
141
|
+
* verified against.
|
|
142
|
+
*/
|
|
143
|
+
export declare function buildInvocationPreimage(vcId: Uint8Array, nonce: Uint8Array, reqHash: Uint8Array): Uint8Array;
|
|
144
|
+
/** Options for {@link buildDelegationCredential}. */
|
|
145
|
+
export interface BuildDelegationCredentialOpts {
|
|
146
|
+
user_did: string;
|
|
147
|
+
agent_pubkey: Uint8Array;
|
|
148
|
+
org_did: string;
|
|
149
|
+
contract: string;
|
|
150
|
+
function: string;
|
|
151
|
+
scopes?: string[];
|
|
152
|
+
metadata?: Record<string, string>;
|
|
153
|
+
not_before_secs: bigint | number;
|
|
154
|
+
not_after_secs: bigint | number;
|
|
155
|
+
vc_id: Uint8Array;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Construct a {@link DelegationCredential} and validate body-level
|
|
159
|
+
* invariants (domain, lengths, validity window). Throws on the same
|
|
160
|
+
* conditions the Rust `validate_credential_body` rejects.
|
|
161
|
+
*/
|
|
162
|
+
export declare function buildDelegationCredential(opts: BuildDelegationCredentialOpts): DelegationCredential;
|
|
163
|
+
/**
|
|
164
|
+
* Body-level validation matching `delegation-types::validate_credential_body`,
|
|
165
|
+
* minus the `now`/`max_validity_secs` checks (which are caller-supplied).
|
|
166
|
+
* Throws with a message identifying the offending invariant.
|
|
167
|
+
*/
|
|
168
|
+
export declare function validateCredentialBody(c: DelegationCredential): void;
|
|
169
|
+
/** Compute the EIP-191 "personal_sign" digest of a message. */
|
|
170
|
+
export declare function eip191Digest(msg: Uint8Array): Uint8Array;
|
|
171
|
+
/**
|
|
172
|
+
* EIP-191 sign `jcs` under `secret`, returning a 65-byte signature
|
|
173
|
+
* (`r || s || v`, with `v` in 27/28 — Ethereum convention) and the
|
|
174
|
+
* recovered 20-byte ETH address.
|
|
175
|
+
*/
|
|
176
|
+
export declare function signCredential(jcs: Uint8Array, secret: Uint8Array): {
|
|
177
|
+
sig: Uint8Array;
|
|
178
|
+
addr: Uint8Array;
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Recover the 20-byte ETH address that signed `msg` under EIP-191.
|
|
182
|
+
* Mirrors `delegation-types::eth_recover_eip191`.
|
|
183
|
+
*
|
|
184
|
+
* **Signature malleability — accepted by design.** This routine does
|
|
185
|
+
* not enforce low-s. EIP-2 mandates low-s for *transaction* signatures,
|
|
186
|
+
* but EIP-191 / `personal_sign` has no such requirement, and ethers.js
|
|
187
|
+
* / MetaMask / web3.js produce both shapes. Two distinct `(r, s)` and
|
|
188
|
+
* `(r, n − s)` pairs verify under the same recovered address — replay
|
|
189
|
+
* protection comes from the envelope's `request_hash` + `nonce`, not
|
|
190
|
+
* from byte-uniqueness of the signature.
|
|
191
|
+
*/
|
|
192
|
+
export declare function ethRecoverEip191(msg: Uint8Array, sig: Uint8Array): Uint8Array;
|
|
193
|
+
/**
|
|
194
|
+
* Sign the agent-side invocation pre-image. The signature is raw
|
|
195
|
+
* compact ECDSA (64 bytes) over `sha256(preimage)` — what
|
|
196
|
+
* `delegation-types::verify_agent_sig` accepts as the 64-byte form.
|
|
197
|
+
*/
|
|
198
|
+
export declare function signAgentInvocation(preimage: Uint8Array, secret: Uint8Array): Uint8Array;
|
|
199
|
+
/** Options for {@link buildPayrollInvocation}. */
|
|
200
|
+
export interface BuildPayrollInvocationOpts {
|
|
201
|
+
credentialJcs: Uint8Array;
|
|
202
|
+
userSig: Uint8Array;
|
|
203
|
+
/** Credential's `vc_id` — needed for the agent pre-image. */
|
|
204
|
+
vcId: Uint8Array;
|
|
205
|
+
nonce: Uint8Array;
|
|
206
|
+
request: PayrollRunRequest;
|
|
207
|
+
agentSecret: Uint8Array;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Assemble a complete {@link PayrollInvocation} (envelope + request)
|
|
211
|
+
* given a user-signed credential and a per-call agent secret. Computes
|
|
212
|
+
* `request_hash` from the canonical request bytes and produces an
|
|
213
|
+
* `agent_sig` over `sha256(invocation_preimage)`.
|
|
214
|
+
*/
|
|
215
|
+
export declare function buildPayrollInvocation(opts: BuildPayrollInvocationOpts): PayrollInvocation;
|
|
216
|
+
export {};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export type { KycStatus, KycStatusKind, KycPollOptions, KycPollCadence, } from "
|
|
|
20
20
|
export { DEFAULT_KYC_POLL_CADENCE, TERMINAL_KYC_STATUSES, KycStatusTimeoutError, } from "./types/kyc";
|
|
21
21
|
export type { OtpChannel, OtpRequestInput, OtpRequestResult, OtpVerifyInput, OtpVerifyResult, OtpMergeSuggestion, UserInputProfile, SubmitUserInputArgs, SubmitUserInputResult, UserUpsertErrorKind, } from "./types/user";
|
|
22
22
|
export { UserUpsertError } from "./types/user";
|
|
23
|
+
export { DELEGATION_CREDENTIAL_DOMAIN, DELEGATION_INVOCATION_DOMAIN, VC_ID_LEN, NONCE_LEN, REQUEST_HASH_LEN, AGENT_PUBKEY_LEN, ETH_SIG_LEN, buildDelegationCredential, validateCredentialBody, canonicaliseCredential, canonicaliseRequest, requestHash, buildInvocationPreimage, eip191Digest, signCredential, ethRecoverEip191, signAgentInvocation, buildPayrollInvocation, compactDidFromBytes, b64uEncodeBytes, b64uDecodeStrict, _b64uEncode, } from "./client/delegation";
|
|
24
|
+
export type { DelegationCredential, DelegationEnvelope, PayrollRunRequest, PayrollInvocation, SignDelegationResponse, BuildDelegationCredentialOpts, BuildPayrollInvocationOpts, } from "./client/delegation";
|
|
23
25
|
export { metamask_sign, metamask_get_address, eth_get_address, createDefaultHandlers, createMlKemPublicKeyHandler, createRandomHandler, } from "./client/handlers";
|
|
24
26
|
export type { WasmComponent, ClientHandshake, ClientAuth, SessionCrypto, WasmNextResult, } from "./wasm";
|
|
25
27
|
export { loadWasmComponent } from "./wasm";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terminal3/t3n-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "T3n TypeScript SDK - A minimal SDK that mirrors the server's RPC handler approach",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -101,6 +101,9 @@
|
|
|
101
101
|
"dependencies": {
|
|
102
102
|
"@bytecodealliance/jco": "^1.17.6",
|
|
103
103
|
"@bytecodealliance/preview2-shim": "^0.17.8",
|
|
104
|
+
"@noble/curves": "^2.2.0",
|
|
105
|
+
"@noble/hashes": "^2.2.0",
|
|
106
|
+
"canonicalize": "^3.0.0",
|
|
104
107
|
"ethers": "^6.16.0"
|
|
105
108
|
},
|
|
106
109
|
"pnpm": {
|