@terminal3/t3n-sdk 4.38.0 → 4.39.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 CHANGED
@@ -965,1156 +965,1548 @@ declare class ContractResponseError extends T3nError {
965
965
  declare function parseContractResponse<T = unknown>(raw: string, schema?: ContractResponseSchema<T>): T;
966
966
 
967
967
  /**
968
- * Agent-auth grants — the standing on-chain authority a user delegates to
969
- * an agent (envelope-free authorisation).
968
+ * Org-data wire types mirroring the org-data contract wire shapes.
970
969
  *
971
- * `AGENT_AUTH_MAP` is keyed by the *user* DID — one policy document per
972
- * user, global across orgs, with at most one entry per agent DID. Reads
973
- * (`agent-auth-get`) and writes (`agent-auth-update`) on
974
- * `tee:authorisations/contracts` (the policy's owning contract) are
975
- * **SelfOnly**: only the user, authenticated as themselves, may read or
976
- * write their own grants. This is the user-approval
977
- * proof the per-call delegation credential's `user_sig` used to carry.
978
- *
979
- * The write shape gained `scopes` + a validity window: the
980
- * agent's delegated org-data scopes, and an optional `[valid_from_secs,
981
- * valid_until_secs]` window. The ≤ cap *length* check is enforced contract-
982
- * side at write time; the expiry gate is host-side at read time.
983
- *
984
- * The merge below is a script-level union (R59): writing a grant for one
985
- * `(agent_did, script_name)` preserves every other script row on that
986
- * agent's entry, and every other agent's entry, unchanged.
987
- */
988
- /** A single script grant in the camelCase write-request shape. */
989
- interface AgentAuthScriptGrant {
990
- /** Contract name, or `"*"`. */
991
- scriptName: string;
992
- /** Optional semver requirement; `null` to match any version. */
993
- versionReq?: string | null;
994
- /** Functions the agent may invoke on this contract. */
995
- functions: string[];
996
- /** Org-data scopes delegated to the agent for the contract functions to
997
- * read on its behalf. */
998
- scopes?: string[];
999
- /** Direct-read scopes the agent may enumerate itself, via whichever read
1000
- * function the contract exposes for direct enumeration. A strict subset of
1001
- * `scopes` (enforced contract-side). */
1002
- readScopes?: string[];
1003
- /** Optional validity-window start (unix seconds). */
1004
- validFromSecs?: number | null;
1005
- /** NEW: optional validity-window end (unix seconds). */
1006
- validUntilSecs?: number | null;
1007
- /** Egress hosts the agent may reach for this contract. */
1008
- allowedHosts: string[];
1009
- }
1010
- /** One agent's entry in the write-request shape. */
1011
- interface AgentAuthEntry {
1012
- agentDid: string;
1013
- scripts: AgentAuthScriptGrant[];
1014
- }
1015
- /**
1016
- * The full agent-auth policy document in the camelCase write shape:
1017
- * the per-agent grants plus the document-level discovery grants.
970
+ * Plain TypeScript interfaces (no zod) — the SDK does not use a
971
+ * validation library for domain types; see the existing `types/` files.
1018
972
  *
1019
- * `discoverDids` (contract wire: `discover_dids`) is the
1020
- * list of DIDs the user lets their registered agents *enumerate the
1021
- * contracts of* via `listContracts`: an org DID grants org-mode discovery,
1022
- * the user's own DID grants self-mode discovery. It lives at document
1023
- * level — not on a script grant — because discovery must surface contracts
1024
- * the agent cannot yet call. The node's discovery gate additionally
1025
- * requires the calling agent to be named in `agents` (subject binding), so
1026
- * an unregistered agent discovers nothing regardless of this list.
973
+ * Each response type below is paired with a shallow runtime predicate
974
+ * (`isMutationResponse`, `isOrgPolicyMeta`, etc.) so the org-data client
975
+ * can `assertShape` the decoded payload before returning to callers.
976
+ * Predicates check the top-level structure only; nested elements
977
+ * (e.g. each `BoundGrant` inside `OrgContractDelegation.grants`) are not
978
+ * deeply validated — see `utils/shape.ts` for the rationale.
979
+ *
980
+ * Reference: the org-data wire contract.
1027
981
  */
1028
- interface AgentAuthPolicy {
1029
- agents: AgentAuthEntry[];
1030
- discoverDids: string[];
1031
- }
1032
982
  /**
1033
- * Parse a full `agent-auth-get` response (the stored snake_case policy
1034
- * document) into the camelCase write shape, including the document-level
1035
- * `discover_dids`. A `null` / absent response is the empty policy.
1036
- */
1037
- declare function parseAgentAuthPolicy(response: unknown): AgentAuthPolicy;
1038
- /** Extract the `agents` array from an `agent-auth-get` response. */
1039
- declare function parseAgentAuthGet(response: unknown): AgentAuthEntry[];
1040
- interface AgentAuthMergeResult {
1041
- /** Full merged `agents` list, ready for `agent-auth-update`. */
1042
- agents: AgentAuthEntry[];
1043
- /** `"<agentDid> → <scriptName>"` rows preserved from the existing policy. */
1044
- preservedRows: string[];
983
+ * Validity time-box on an agent-edge grant — serialised under the JSON key
984
+ * `window`. Both bounds are optional unix-seconds; an omitted bound is
985
+ * defaulted contract-side (`valid_from_secs` → now, `valid_until_secs` → now +
986
+ * operator cap). Mirrors the org-data `Validity` wire shape. Absent bounds
987
+ * are omitted from the wire (never sent as `null`).
988
+ */
989
+ interface Validity {
990
+ valid_from_secs?: number;
991
+ valid_until_secs?: number;
992
+ }
993
+ /**
994
+ * A grantee-bound capability grant — the element of BOTH grant-management
995
+ * surfaces: the org edge (`org-delegation-set` input / `org-delegation-get`
996
+ * output) and the flat delegation edge (`member-delegation-get` output /
997
+ * `member-delegation-update` input). Stored inline on the unified `ROLE_ASSIGNMENTS_MAP`
998
+ * edge record.
999
+ *
1000
+ * Mirrors the org-data `BoundGrant` wire shape verbatim (snake_case, no casing
1001
+ * transform): `grantee` followed by the flattened capability body. The org edge
1002
+ * populates only `functions` + `scopes`; the delegation edge additionally
1003
+ * carries the qualifiers `version_req` / `read_scopes` / `allowed_hosts` and the
1004
+ * validity `window`. All qualifier fields are optional and omitted from the wire when
1005
+ * absent (never sent as `null`), so an org grant simply leaves them unset.
1006
+ */
1007
+ interface BoundGrant {
1008
+ /** The principal (`did:t3n:<40-hex>`) this grant applies to — a user or an
1009
+ * agent DID. */
1010
+ grantee: string;
1011
+ /** Target contract id (canonical name, e.g. `"tee:z-payroll/contracts"`), or
1012
+ * `"*"`. On a read this echoes the queried contract. */
1013
+ contract_id: string;
1014
+ /** WIT function names the grantee may invoke (e.g. `"set-records"`; `["*"]`
1015
+ * matches all). */
1016
+ functions: string[];
1017
+ /** Data scope paths the grantee may access (e.g. `"example/records"`). */
1018
+ scopes: string[];
1019
+ /** Agent edge only: optional semver requirement; omitted matches any version. */
1020
+ version_req?: string;
1021
+ /** Agent edge only: direct-read scopes the grantee may enumerate itself — a
1022
+ * subset of `scopes` (enforced contract-side). */
1023
+ read_scopes?: string[];
1024
+ /** Agent edge only: egress hosts the grantee may reach for this contract. */
1025
+ allowed_hosts?: string[];
1026
+ /** Agent edge only: optional validity time-box. */
1027
+ window?: Validity;
1045
1028
  }
1046
- /** Input to the full-document write {@link T3nClient.agentAuthUpdate}. The
1047
- * document IS the new state: an empty `agents` list revokes all agent
1048
- * access, and an omitted / empty `discoverDids` persists an empty
1049
- * discovery-grant list (the contract has no per-field merge). Mirrors the
1050
- * contract `AgentAuthPolicy`. */
1051
- interface AgentAuthUpdateInput {
1052
- agents: AgentAuthEntry[];
1053
- /** Document-level discovery grants — see {@link AgentAuthPolicy}. */
1054
- discoverDids?: string[];
1055
- }
1056
- /**
1057
- * Serialise a camelCase policy document to the contract's canonical
1058
- * snake_case `agent-auth-update` wire (`agent_did` / `script_name` /
1059
- * `version_req` / `read_scopes` / `valid_from_secs` / `valid_until_secs` /
1060
- * `allowed_hosts` / `discover_dids`), so neither write path relies on the
1061
- * contract's compatibility aliases. Absent optionals are omitted (never
1062
- * sent as `null`); empty `scopes` / `read_scopes` are omitted (the
1063
- * contract defaults both to empty). `functions` and `allowed_hosts` are
1064
- * always emitted — the contract requires explicit functions (`["*"]` =
1065
- * all) and reads an absent `allowed_hosts` as deny-all egress. The
1066
- * document-level `discover_dids` (strictly snake_case — the contract
1067
- * defines no camelCase alias for it) is emitted only when non-empty; the
1068
- * contract defaults an absent list to empty.
1069
- */
1070
- declare function toAgentAuthUpdateWire(agents: AgentAuthEntry[], discoverDids?: string[]): {
1071
- agents: Array<{
1072
- agent_did: string;
1073
- scripts: Array<Record<string, unknown>>;
1074
- }>;
1075
- discover_dids?: string[];
1076
- };
1077
- /**
1078
- * Order-preserving deduplicating union of discovery-grant DID lists —
1079
- * the read-merge-write counterpart of {@link mergeAgentAuthEntries} for
1080
- * the document-level `discoverDids` (the contract rejects duplicate
1081
- * entries, so the union must dedupe).
1082
- */
1083
- declare function mergeDiscoverDids(existing: string[], additions: string[]): string[];
1084
- /**
1085
- * Merge new agent entries into the existing policy with script-level union
1086
- * semantics: for an agent DID present on both sides, script rows whose
1087
- * `scriptName` is not being written are preserved; rows with a matching
1088
- * `scriptName` are replaced by the new grant. Entries for other agent DIDs
1089
- * pass through unchanged.
1090
- */
1091
- declare function mergeAgentAuthEntries(existing: AgentAuthEntry[], newEntries: AgentAuthEntry[]): AgentAuthMergeResult;
1092
-
1093
- /**
1094
- * KYC types for the `tee:user/contracts::kyc-status` short-poll
1095
- * function.
1096
- *
1097
- * The shape mirrors the `kyc-status` wire response.
1098
- * The bytes go straight from the contract
1099
- * through the JSON-RPC envelope into [[T3nClient.kycStatus]].
1100
- */
1101
-
1102
1029
  /**
1103
- * Terminal status for a Level 2 KYC verification, plus `pending`.
1030
+ * Policy record for an organisation's data tier.
1104
1031
  *
1105
- * - `pending` — provider has not delivered a verdict yet, or the
1106
- * webhook arrived but the post-action VC issuance hasn't completed.
1107
- * - `verified` — provider approved AND a VC has been issued. `vcIds`
1108
- * carries the issued credential ids.
1109
- * - `rejected` — provider declined / required resubmission /
1110
- * expired / the user abandoned the flow. `error` may carry a
1111
- * provider-supplied reason.
1112
- * - `orphan` — a Veriff webhook arrived with a `vendorData` that
1113
- * couldn't be matched to any user. Should not
1114
- * happen in the MetaMask flow but the contract surfaces it for
1115
- * completeness.
1032
+ * Mirrors the org-data policy-meta wire shape.
1116
1033
  */
1117
- type KycStatusKind = "pending" | "verified" | "rejected" | "orphan";
1034
+ interface OrgPolicyMeta {
1035
+ /** DIDs (`did:t3n:<40-hex>`) of users authorised to manage policy and read data. */
1036
+ admins: string[];
1037
+ /** Maximum number of admins allowed for this org. */
1038
+ max_admins: number;
1039
+ /** Unix timestamp (secs) when the policy was first created. */
1040
+ created_at_secs: number;
1041
+ /** Unix timestamp (secs) of the most recent policy update. */
1042
+ updated_at_secs: number;
1043
+ /**
1044
+ * Per-org ceiling on delegation-credential validity (seconds).
1045
+ *
1046
+ * Absent when no org-level cap is set — the contract omits the field
1047
+ * (never serialises null) and the cluster-wide
1048
+ * `delegation.max_credential_validity_secs` governs instead. When set,
1049
+ * the effective cap is `min(max_credential_validity_secs, cluster_ceiling)`.
1050
+ */
1051
+ max_credential_validity_secs?: number;
1052
+ }
1053
+ /** Shallow runtime guard for {@link OrgPolicyMeta}. */
1054
+ declare function isOrgPolicyMeta(value: unknown): value is OrgPolicyMeta;
1118
1055
  /**
1119
- * Snapshot returned by `tee:user/contracts::kyc-status`.
1056
+ * Effective org policy view returned by `org-policy-view`.
1120
1057
  *
1121
- * Field names use camelCase on the SDK boundary even though the
1122
- * wire is snake_case — the wrapper rewrites keys at the client edge
1123
- * so callers don't see the JSON shape leaking through.
1058
+ * Readable by any authenticated session (non-sensitive metadata).
1059
+ * Returns the **effective** credential validity cap:
1060
+ * `min(org.max_credential_validity_secs, cluster_ceiling)`, equal to the
1061
+ * cluster ceiling when the org has not set a per-org cap. The contract
1062
+ * always returns a value (or errors) — the field is never null.
1124
1063
  */
1125
- interface KycStatus {
1126
- /** Terminal status if reached, otherwise `pending`. */
1127
- status: KycStatusKind;
1128
- /**
1129
- * Provider being polled. Echoed back so callers that didn't
1130
- * supply one see the contract's default (`"veriff"` in phase one).
1131
- */
1132
- provider: string;
1133
- /**
1134
- * Unix-millis of the latest contract-visible event:
1135
- * VC issuance time, attestation arrival time, session-row
1136
- * `started_at_ms`, or orphan-record arrival time. Best-effort —
1137
- * `undefined` when no source carries a usable timestamp.
1138
- */
1139
- updatedAt?: number;
1140
- /**
1141
- * VC ids appended for this provider, in append order. Empty for
1142
- * `pending` / `rejected` / `orphan`.
1143
- */
1144
- vcIds: string[];
1064
+ interface OrgPolicyView {
1145
1065
  /**
1146
- * Provider-supplied reason for `rejected`, when available.
1066
+ * Effective delegation-credential validity cap in seconds:
1067
+ * `min(org value, cluster ceiling)`, equal to the cluster ceiling when the
1068
+ * org has not set a per-org cap. Always present — mirrors the contract's
1069
+ * `PolicyViewResponse.effective_validity_secs` (org-data `org-policy-view`).
1147
1070
  */
1148
- error?: string;
1071
+ effective_validity_secs: number;
1149
1072
  }
1073
+ /** Shallow runtime guard for {@link OrgPolicyView}. */
1074
+ declare function isOrgPolicyView(value: unknown): value is OrgPolicyView;
1150
1075
  /**
1151
- * Polling cadence for [[T3nClient.kycStatusPoll]]. Defaults:
1152
- * poll fast for the first 30 seconds, then back
1153
- * off, and bail after 5 minutes.
1076
+ * Caller-scoped admin status returned by `org-am-i-admin`.
1077
+ *
1078
+ * Reports only whether the **calling** session's DID is in the org's admin
1079
+ * list — never the roster itself (contrast {@link OrgPolicyMeta}, returned by
1080
+ * the admin-gated `org-policy-get`). Readable by any authenticated session.
1081
+ * Mirrors the org-data `AmIAdminResponse` wire shape.
1154
1082
  */
1155
- interface KycPollCadence {
1156
- /** Poll interval in ms while `elapsed < switchAtMs`. Default: 2000. */
1157
- fastMs: number;
1158
- /** Poll interval in ms once `elapsed >= switchAtMs`. Default: 5000. */
1159
- slowMs: number;
1160
- /** Elapsed-ms threshold to switch from fast to slow cadence. Default: 30_000. */
1161
- switchAtMs: number;
1162
- /**
1163
- * Maximum total time to spend polling before rejecting with
1164
- * [[KycStatusTimeoutError]]. Default: 300_000 (5 minutes).
1165
- */
1166
- timeoutMs: number;
1083
+ interface OrgAdminStatus {
1084
+ /** Whether the calling session is an admin of the queried org. */
1085
+ is_admin: boolean;
1167
1086
  }
1087
+ /** Shallow runtime guard for {@link OrgAdminStatus}. */
1088
+ declare function isOrgAdminStatus(value: unknown): value is OrgAdminStatus;
1168
1089
  /**
1169
- * Optional knobs for [[T3nClient.kycStatusPoll]]. Most callers won't
1170
- * touch any of these — the cadence defaults are baked in.
1090
+ * Standard response returned by all policy write and data mutation operations.
1091
+ *
1092
+ * Mirrors the org-data `MutationResponse` wire shape.
1171
1093
  */
1172
- interface KycPollOptions {
1173
- /**
1174
- * Cancellation signal. When aborted, the helper rejects with
1175
- * `signal.reason` (or a generic `AbortError` if the consumer
1176
- * didn't supply a reason). The currently-in-flight `kycStatus()`
1177
- * call also receives the signal so it can short-circuit.
1178
- */
1179
- signal?: AbortSignal;
1180
- /**
1181
- * Called with every snapshot the helper receives, including
1182
- * non-terminal `pending` ones. Useful for surfacing intermediate
1183
- * UI states (e.g. "still waiting on provider…"). Errors thrown
1184
- * from this callback are caught and ignored — they must not
1185
- * sink the poll loop.
1186
- */
1187
- onUpdate?: (status: KycStatus) => void;
1188
- /**
1189
- * Override one or more cadence fields. Anything not specified
1190
- * uses the defaults from [[DEFAULT_KYC_POLL_CADENCE]].
1191
- */
1192
- cadence?: Partial<KycPollCadence>;
1094
+ interface MutationResponse {
1193
1095
  /**
1194
- * Provider id to poll. Defaults to the contract default
1195
- * (`"veriff"` in phase one). Mirrored on the wire as
1196
- * `input.provider_id`.
1096
+ * `"created"`, `"updated"`, `"deleted"`, or — for the agent-card mutations —
1097
+ * `"published"` / `"unpublished"`.
1197
1098
  */
1198
- providerId?: string;
1099
+ status: string;
1100
+ /** Hex-encoded entry ID; present on data write/delete operations. */
1101
+ entry_id?: string;
1102
+ /** Whether the target key existed before deletion; present on single-entry deletes. */
1103
+ deleted?: boolean;
1104
+ /** Number of entries removed; present on `org-data-delete-scope`. */
1105
+ deleted_entries?: number;
1106
+ tx_hash: string | null;
1199
1107
  }
1200
1108
  /**
1201
- * Default cadence used by [[T3nClient.kycStatusPoll]] when the caller
1202
- * doesn't override `cadence.*`.
1109
+ * Shallow runtime guard for {@link MutationResponse}.
1110
+ *
1111
+ * Only the always-present fields are checked — `status` is mandatory on
1112
+ * every mutation; `tx_hash` is non-optional but nullable. The optional
1113
+ * fields (`entry_id`, `deleted`, `deleted_entries`) are not validated
1114
+ * because their presence depends on which mutation ran.
1203
1115
  */
1204
- declare const DEFAULT_KYC_POLL_CADENCE: KycPollCadence;
1116
+ declare function isMutationResponse(value: unknown): value is MutationResponse;
1205
1117
  /**
1206
- * Subset of [[KycStatusKind]] that ends a poll. `pending` is the
1207
- * only non-terminal value.
1118
+ * Response type alias for org-writers-get.
1119
+ *
1120
+ * The wire body is `{ writers: string[] }` where each entry is
1121
+ * `did:t3n:<40-hex>`.
1208
1122
  */
1209
- declare const TERMINAL_KYC_STATUSES: ReadonlySet<KycStatusKind>;
1123
+ interface OrgWriters {
1124
+ writers: string[];
1125
+ }
1126
+ /** Shallow runtime guard for {@link OrgWriters}. */
1127
+ declare function isOrgWriters(value: unknown): value is OrgWriters;
1210
1128
  /**
1211
- * Thrown by [[T3nClient.kycStatusPoll]] when the cadence's
1212
- * `timeoutMs` elapses without a terminal status arriving. The
1213
- * `lastStatus` field is the most recent (necessarily `pending`)
1214
- * snapshot the helper saw, useful for surfacing "we tried for N
1215
- * minutes but Veriff is still working" UX.
1129
+ * Response type alias for org-delegation-get.
1130
+ *
1131
+ * The wire body echoes the `contract_id` alongside the grant list.
1216
1132
  */
1217
- declare class KycStatusTimeoutError extends T3nError {
1218
- /** The timeout (ms) the helper exhausted before a terminal status arrived. */
1219
- readonly timeoutMs: number;
1220
- /** The last `pending` snapshot before timeout, if any. */
1221
- readonly lastStatus?: KycStatus | undefined;
1222
- constructor(
1223
- /** The timeout (ms) the helper exhausted before a terminal status arrived. */
1224
- timeoutMs: number,
1225
- /** The last `pending` snapshot before timeout, if any. */
1226
- lastStatus?: KycStatus | undefined);
1133
+ interface OrgContractDelegation {
1134
+ contract_id: string;
1135
+ grants: BoundGrant[];
1227
1136
  }
1228
-
1229
1137
  /**
1230
- * Wire types for the explicit `otp-request` /
1231
- * `otp-verify` / slim `user-upsert` exports on `tee:user/contracts`
1232
- * (`tee:user@2.0.0`).
1233
- *
1234
- * Pre-2.0.0 the user contract dispatched OTP request and OTP verify
1235
- * implicitly from the input shape of a single `user-upsert` call.
1236
- * 2.0.0 splits that surface into three explicit functions; the
1237
- * shapes here mirror the OTP / user-upsert wire contract.
1138
+ * Shallow runtime guard for {@link OrgContractDelegation}.
1238
1139
  *
1239
- * Bytes flow directly from the contract
1240
- * through the JSON-RPC envelope into the SDK wrappers
1241
- * (`T3nClient.otpRequest`, `T3nClient.otpVerify`,
1242
- * `T3nClient.submitUserInput`).
1140
+ * Validates the immediate envelope (`contract_id: string`, `grants:
1141
+ * array`) without recursing into each `BoundGrant`. The Rust contract
1142
+ * is the source of truth for grant element shape; widening the predicate
1143
+ * here would create maintenance churn against benign field additions.
1243
1144
  */
1244
-
1145
+ declare function isOrgContractDelegation(value: unknown): value is OrgContractDelegation;
1245
1146
  /**
1246
- * OTP delivery channel. Matches the `OtpContactChannel` Rust enum
1247
- * with `serde(rename_all = "snake_case")`.
1147
+ * One grant inside a role: a capability body (functions + scopes, without the
1148
+ * grantee, which is bound at assignment time) plus the target contract.
1149
+ * Mirrors the org-data `RoleGrant` wire shape.
1248
1150
  */
1249
- type OtpChannel = "email" | "sms";
1151
+ interface RoleGrant {
1152
+ /** Target contract (canonical name, e.g. `"tee:z-payroll/contracts"`). */
1153
+ contract_id: string;
1154
+ /** WIT function names this grant confers. */
1155
+ functions: string[];
1156
+ /** Data scope paths this grant confers (canonicalised lowercase). */
1157
+ scopes: string[];
1158
+ }
1250
1159
  /**
1251
- * Discriminated OTP contact target. Mirrors the Rust `OtpRequest` enum
1252
- * (`email_channel` / `sms_channel` on the wire). Exactly one branch is
1253
- * set — no parallel optional email + phone with a separate channel tag.
1254
- *
1255
- * The legacy `keys.generic_api.otp_channel` body shadow was removed
1256
- * in 2.0.0 — the contract rejects calls carrying it with a
1257
- * `legacy_field` error.
1258
- */
1259
- type OtpRequestInput = {
1260
- emailChannel: {
1261
- emailAddress: string;
1262
- };
1263
- } | {
1264
- smsChannel: {
1265
- phoneNumber: string;
1266
- };
1267
- };
1268
- /**
1269
- * Response returned by `otp-request`. Mirrors the OTP wire response.
1270
- *
1271
- * - `contact` echoes the OTP destination so clients that race
1272
- * multiple channels can correlate replies.
1273
- * - `expiresAtSec` is the Unix-second TTL the host minted for the
1274
- * pending OTP. Absent in `skip_otp` test environments.
1275
- * - `status` is `"otp_pending"` on the happy path. `"otp_failed"`
1276
- * only appears on retry without a fresh request — usually you
1277
- * shouldn't see it on `otp-request`.
1278
- * - `txHash` is the host-enriched ledger ref for the OTP-pending
1279
- * write (the contract leaves it `null`; the host injects).
1280
- * - `isNewProfile` is `true` on a fresh DID's first OTP request —
1281
- * read this to detect "did the user just register".
1160
+ * A role: a named bundle of grants and/or composed sub-roles.
1161
+ * Mirrors the org-data `RoleDefinition` wire shape.
1282
1162
  */
1283
- interface OtpRequestResult {
1284
- contact: string;
1285
- channel: OtpChannel;
1286
- expiresAtSec?: number;
1287
- status?: string;
1288
- txHash?: string;
1289
- isNewProfile?: boolean;
1163
+ interface RoleDefinition {
1164
+ /** Org-unique role identifier (slug; function-name grammar). */
1165
+ role_id: string;
1166
+ /** Human-facing label. */
1167
+ label: string;
1168
+ /** Composite: other role ids in the same org whose grants this role confers. */
1169
+ includes: string[];
1170
+ /** Grants this role confers directly. */
1171
+ grants: RoleGrant[];
1290
1172
  }
1291
1173
  /**
1292
- * Input to `T3nClient.otpVerify`. `otpCode` is mandatory; `request`
1293
- * repeats the same discriminated contact shape as {@link OtpRequestInput}.
1174
+ * The roles assigned to one grantee within one org.
1175
+ * Mirrors the org-data `RoleAssignments` wire shape.
1294
1176
  */
1295
- interface OtpVerifyInput {
1296
- otpCode: string;
1297
- request: OtpRequestInput;
1177
+ interface RoleAssignments {
1178
+ /** Assigned role ids. */
1179
+ roles: string[];
1298
1180
  }
1299
- /**
1300
- * Suggestion surfaced when the bind-target contact already belongs
1301
- * to another DID. The contract refuses to silently steal the
1302
- * authenticator; the caller must resolve the merge (typically via
1303
- * `merge-profiles`) before re-attempting verify.
1304
- */
1305
- interface OtpMergeSuggestion {
1306
- existingDid: string;
1307
- currentDid: string;
1308
- email?: string;
1309
- phone?: string;
1310
- channel: OtpChannel;
1181
+ /** Response for `org-role-get`; `role` is `null` when the id is unknown. */
1182
+ interface RoleGetResponse {
1183
+ role: RoleDefinition | null;
1311
1184
  }
1185
+ /** Shallow runtime guard for {@link RoleGetResponse}. */
1186
+ declare function isRoleGetResponse(value: unknown): value is RoleGetResponse;
1312
1187
  /**
1313
- * Response returned by `otp-verify`. Mirrors the OTP-verify wire response.
1188
+ * One org-owned agent's outbound host allow-list for a single contract.
1314
1189
  *
1315
- * - `email` is populated on `channel = "email"` success;
1316
- * `phone` on `channel = "sms"` success. Mutually exclusive on
1317
- * the happy path.
1318
- * - `status` carries `"otp_failed"` / `"otp_expired"` on retry; the
1319
- * happy path leaves it `undefined`.
1320
- * - `mergeSuggestion` is set when the contact-to-bind is already
1321
- * owned by another DID. Wire it into your merge UX.
1190
+ * Egress only — it carries no data scopes by construction, so it can never be
1191
+ * a second path to org data (that stays with `org-delegation-set`).
1322
1192
  */
1323
- interface OtpVerifyResult {
1324
- txHash?: string;
1325
- did: string;
1326
- channel: OtpChannel;
1327
- email?: string;
1328
- phone?: string;
1329
- status?: string;
1330
- mergeSuggestion?: OtpMergeSuggestion;
1331
- isNewProfile?: boolean;
1193
+ interface AgentEgressEntry {
1194
+ contract_id: string;
1195
+ /** Bare lowercase hostnames, matched exactly by the node. */
1196
+ allowed_hosts: string[];
1197
+ /** WIT functions covered; `["*"]` means all of them. */
1198
+ functions: string[];
1199
+ /** Present only when the allow-list is pinned to a version range. */
1200
+ version_req?: string;
1332
1201
  }
1333
1202
  /**
1334
- * Level-1 user-input fields accepted by the slim `user-upsert`. Field names
1335
- * are the on-the-wire names — `submitUserInput` sends this object verbatim,
1336
- * so keys must match the contract exactly (snake_case). The canonical Level-1
1337
- * set is the six fields below; the shape is intentionally open so callers can
1338
- * add provider-specific fields the contract knows how to merge.
1339
- *
1340
- * `email_address` / `phone_number` are normally bound via the OTP roundtrip
1341
- * before `submitUserInput`, but the contract accepts them directly here too.
1203
+ * Response for `org-agent-egress-get`; `egress` is `null` when the agent holds
1204
+ * no egress entry for the requested contract.
1342
1205
  */
1343
- interface UserInputProfile {
1344
- first_name?: string;
1345
- last_name?: string;
1346
- country_of_residence?: string;
1347
- document_issuance_country?: string;
1348
- ssn?: string;
1349
- address?: string;
1350
- email_address?: string;
1351
- phone_number?: string;
1352
- campaign_code?: string;
1353
- role?: string;
1354
- [key: string]: unknown;
1206
+ interface AgentEgressGetResponse {
1207
+ egress: AgentEgressEntry | null;
1208
+ }
1209
+ /** Runtime guard for {@link AgentEgressGetResponse}. */
1210
+ declare function isAgentEgressGetResponse(value: unknown): value is AgentEgressGetResponse;
1211
+ /** Response for `org-role-assignments-get`. */
1212
+ interface RoleAssignmentsResponse {
1213
+ /** Echoed back so callers don't need to track which request this answers. */
1214
+ grantee_did: string;
1215
+ /** The grantee's assigned role ids (empty when none). */
1216
+ roles: string[];
1355
1217
  }
1218
+ /** Shallow runtime guard for {@link RoleAssignmentsResponse}. */
1219
+ declare function isRoleAssignmentsResponse(value: unknown): value is RoleAssignmentsResponse;
1356
1220
  /**
1357
- * Input to `T3nClient.submitUserInput`. Maps onto the slim
1358
- * `user-upsert` request shape: `{ profile, organisation_did?,
1359
- * attestations?, keys? }`.
1221
+ * Input for `listAgents` — the org plus optional pagination. Omit both `cursor`
1222
+ * and `limit` for the first page at the default limit; pass a previous
1223
+ * response's `next_cursor` back as `cursor` to fetch the following page.
1360
1224
  */
1361
- interface SubmitUserInputArgs {
1362
- profile: UserInputProfile;
1363
- organisationDid?: string;
1364
- attestations?: unknown;
1365
- keys?: Record<string, unknown>;
1366
- /**
1367
- * KYC webhook orphan-attestation flow. When set, the contract
1368
- * skips the email-not-verified gate and only records the
1369
- * attestation if the DID has no profile yet.
1370
- * Most callers should leave this `undefined`.
1371
- */
1372
- requireExistingUser?: boolean;
1373
- /**
1374
- * Testnet self-admit. When `true`, the contract additionally
1375
- * runs the self-admit side-effect after the profile commit: writes
1376
- * the caller's DID into `idx:_tenants` + `idx:_tenant_quotas` and
1377
- * mints any operator-configured welcome credits. Inspect the
1378
- * `tenantAdmit` field on the response for the outcome.
1379
- *
1380
- * Testnet-only. Production clusters return
1381
- * `tenantAdmit.status = "refused"` with
1382
- * `reason = "not_testnet" | "self_admit_disabled" | "not_eth_derived"`.
1383
- * The profile commit always succeeds regardless of the inner outcome.
1384
- *
1385
- * Most callers should leave this `undefined`.
1386
- */
1387
- becomeDevTenant?: boolean;
1225
+ interface ListAgentsInput {
1226
+ orgDid: string;
1227
+ /** Opaque cursor from a previous response's `next_cursor`. */
1228
+ cursor?: string;
1229
+ /** Maximum agents to return in this page. */
1230
+ limit?: number;
1388
1231
  }
1389
1232
  /**
1390
- * Testnet self-admit projection from `user-upsert`. Present only
1391
- * when the caller set `becomeDevTenant: true` on the request.
1392
- *
1393
- * - `status: "admitted"` — first call for this DID; tenant record
1394
- * committed and (if configured) welcome credits minted into
1395
- * `grantedCredits`.
1396
- * - `status: "already-admitted"` — replay; idempotent no-op.
1397
- * - `status: "refused"` — the cluster declined the self-admit;
1398
- * `reason` is the machine-readable cause (`not_testnet`,
1399
- * `self_admit_disabled`, `not_eth_derived`), `detail` is a
1400
- * human-readable string.
1233
+ * One org-owned agent in a {@link ListAgentsResponse}: the agent's DID, its
1234
+ * display name, and the number of distinct contracts it can access via a direct
1235
+ * grant. Mirrors the org-data `AgentSummary` wire shape. The name comes from the
1236
+ * agent's private card (falling back to the DID), so the FE no longer needs to
1237
+ * fetch each `public:agent_cards` entry to render the roster.
1401
1238
  */
1402
- type TenantAdmitStatus = "admitted" | "already-admitted" | "refused";
1403
- interface TenantAdmitProjection {
1404
- status: TenantAdmitStatus;
1405
- grantedCredits?: string;
1406
- reason?: string;
1407
- detail?: string;
1239
+ interface AgentSummary {
1240
+ /** The agent's DID (`did:t3n:<40-hex>`). */
1241
+ did: string;
1242
+ /** The agent's display name, from its private card (DID when unavailable). */
1243
+ name: string;
1244
+ /** Count of distinct contracts the agent holds a direct grant on. */
1245
+ contract_count: number;
1246
+ }
1247
+ /** Response for `org-data-list-agents`. */
1248
+ interface ListAgentsResponse {
1249
+ /** One PAGE of the org's org-owned agents, sorted by DID. */
1250
+ agents: AgentSummary[];
1251
+ /** Opaque cursor for the next page; absent on the last page. */
1252
+ next_cursor?: string;
1408
1253
  }
1254
+ /** A human member's org role. The closed wire domain of {@link HumanMember}. */
1255
+ type MemberRole = "admin" | "member";
1409
1256
  /**
1410
- * Response shape returned by the slim `user-upsert`. Carries the
1411
- * post-merge tx hash plus the Level-1 merge diagnostics
1412
- * (`refusedFields`, `mergeSuggestion`) the pre-2.0.0 omnibus
1413
- * `UpsertResponse` already surfaced.
1257
+ * Input for `listHumanMembers` — the org plus optional pagination. Omit both
1258
+ * `cursor` and `limit` for the first page at the default limit; pass a previous
1259
+ * response's `next_cursor` back as `cursor` to fetch the following page.
1414
1260
  */
1415
- interface SubmitUserInputResult {
1416
- txHash?: string;
1417
- refusedFields?: string[];
1418
- mergeSuggestion?: OtpMergeSuggestion;
1419
- userFound?: boolean;
1420
- /**
1421
- * Testnet self-admit projection. Present only when the caller
1422
- * set `becomeDevTenant: true` on the request.
1423
- */
1424
- tenantAdmit?: TenantAdmitProjection;
1261
+ interface ListHumanMembersInput {
1262
+ orgDid: string;
1263
+ /** Opaque cursor from a previous response's `next_cursor`. */
1264
+ cursor?: string;
1265
+ /** Maximum members to return in this page. */
1266
+ limit?: number;
1425
1267
  }
1426
1268
  /**
1427
- * Discriminator for {@link UserUpsertError}. Mirrors the
1428
- * `UserUpsertError` wire enum and its `<code>:<detail>` wire
1429
- * format. Branch with a `switch` over `kind`.
1430
- *
1431
- * - `EmailNotVerified` — the slim `user-upsert` was called against
1432
- * a DID that has no verified email and no proving authenticator.
1433
- * Run `otpRequest` + `otpVerify` first (or accept an
1434
- * OIDC/Email-authed session).
1435
- * - `LegacyField` — caller passed a pre-2.0.0 dispatch field
1436
- * (`otp_code` to a non-verify export, or
1437
- * `keys.generic_api.otp_channel` anywhere). Migrate the call
1438
- * site to the new explicit functions.
1439
- * - `UserNotFound` — `requireExistingUser` was set but no profile
1440
- * exists for the DID. The attestation is recorded for audit;
1441
- * no profile created.
1269
+ * One direct human member: DID plus org role. No profile PII (name/email are
1270
+ * out of scope and owned by `tee:user`). Mirrors the org-data `HumanMember`
1271
+ * wire shape.
1442
1272
  */
1443
- type UserUpsertErrorKind = "EmailNotVerified" | "LegacyField" | "UserNotFound";
1444
- /**
1445
- * Typed wrapper for the `<code>:<detail>` errors the slim
1446
- * `user-upsert` and the OTP entry points emit. `kind` is the
1447
- * structured discriminator the SDK derives from the error code
1448
- * prefix; `code` and `detail` retain the wire components for
1449
- * fall-through logging.
1450
- *
1451
- * Throw site: `T3nClient.submitUserInput` (and friends) when the
1452
- * contract returns a string error matching the
1453
- * `<code>:<detail>` shape.
1454
- */
1455
- declare class UserUpsertError extends T3nError {
1456
- readonly kind: UserUpsertErrorKind | "Unknown";
1457
- readonly detail: string;
1458
- constructor(code: string, detail: string);
1459
- /**
1460
- * Try to parse a contract error string into a `UserUpsertError`.
1461
- * Returns `null` if `raw` doesn't match the `<code>:<detail>`
1462
- * shape — caller falls back to a generic error.
1463
- */
1464
- static fromWire(raw: string): UserUpsertError | null;
1273
+ interface HumanMember {
1274
+ /** The member's DID (`did:t3n:<40-hex>`). */
1275
+ did: string;
1276
+ /** The member's org role. */
1277
+ role: MemberRole;
1278
+ }
1279
+ /** Response for `org-data-list-human-members`. */
1280
+ interface ListHumanMembersResponse {
1281
+ /** One PAGE of the org's direct human members, sorted by DID. */
1282
+ members: HumanMember[];
1283
+ /** Opaque cursor for the next page; absent on the last page. */
1284
+ next_cursor?: string;
1285
+ }
1286
+ /** Shallow runtime guard for {@link ListHumanMembersResponse}. */
1287
+ declare function isListHumanMembersResponse(value: unknown): value is ListHumanMembersResponse;
1288
+ /** Shallow runtime guard for {@link ListAgentsResponse}. */
1289
+ declare function isListAgentsResponse(value: unknown): value is ListAgentsResponse;
1290
+ /** Response for `org-data-list`. */
1291
+ interface DataListResponse {
1292
+ /** Hex-encoded entry IDs for this page. */
1293
+ entry_ids: string[];
1294
+ /** Offset to pass for the next page. `null` when this is the last page. */
1295
+ next_offset: number | null;
1296
+ /** Total number of entries in the scope (across all pages). */
1297
+ total: number;
1298
+ }
1299
+ /** Shallow runtime guard for {@link DataListResponse}. */
1300
+ declare function isDataListResponse(value: unknown): value is DataListResponse;
1301
+ /** Secret shape discriminator (mirrors the contract `SecretKind`). */
1302
+ type SecretKind = "single_value" | "json";
1303
+ /** Metadata common to every {@link SecretView} entry. */
1304
+ interface SecretViewBase {
1305
+ /** Secret name (the `(org, name)` key tail). */
1306
+ name: string;
1307
+ /** Monotonic version, bumped on each value rotation and ACL edit. */
1308
+ version: number;
1309
+ /** Unix seconds of the most recent write. */
1310
+ updated_at_secs: number;
1465
1311
  }
1466
-
1467
1312
  /**
1468
- * Token-metering wire shapes.
1469
- *
1470
- * Mirrors the token-metering wire contract. `u128` fields land on the
1471
- * wire as JSON numbers (same convention as the existing
1472
- * `token.get-balance` response) — JS clients with histories that
1473
- * exceed 2⁵³ tokens should switch to a streaming JSON parser; the
1474
- * common case fits in `number` losslessly.
1313
+ * The redacted per-secret summary `org-secret-list` returns — a discriminated
1314
+ * union on `kind`. The value is NEVER present: a single-value exposes only its
1315
+ * last four characters and a json secret only its sorted top-level field names.
1475
1316
  */
1317
+ type SecretView = (SecretViewBase & {
1318
+ kind: "single_value";
1319
+ /** Last four characters of the value (whole value when ≤ 4 chars). */
1320
+ last4: string;
1321
+ }) | (SecretViewBase & {
1322
+ kind: "json";
1323
+ /** Sorted top-level object field names (keys only, no values). */
1324
+ field_names: string[];
1325
+ });
1326
+ /** Shallow runtime guard for {@link SecretView}. */
1327
+ declare function isSecretView(value: unknown): value is SecretView;
1476
1328
  /**
1477
- * The token `BalanceRow` wire shape — caller's credit row.
1478
- *
1479
- * `available` and `reserved` are `u128` on the server; the wire
1480
- * format is a JSON number. Callers should not assume bigint until
1481
- * the SDK migrates to a streaming parser (tracked separately).
1482
- *
1483
- * ⚠️ Amounts are in **base units** (`1 token = `
1484
- * {@link BASE_UNITS_PER_TOKEN}), not whole tokens. Use
1485
- * {@link formatTokens} to display them.
1329
+ * Full secret record returned by `org-secret-get` — the value IS included
1330
+ * (the deliberate read-back path the READ axis exists for), along with all
1331
+ * three ACLs.
1486
1332
  */
1487
- interface BalanceRow {
1488
- /** Spendable balance, in base units (see {@link formatTokens}). */
1489
- available: number;
1490
- /** Reserved balance, in base units. */
1491
- reserved: number;
1492
- last_settled_seq_no: number;
1333
+ interface SecretRecord {
1334
+ name: string;
1335
+ kind: SecretKind;
1336
+ /** The value as text: the scalar for a single-value, canonical JSON object for a json secret. */
1337
+ value: string;
1493
1338
  version: number;
1494
- credit_exhausted: boolean;
1339
+ /** READ axis — DIDs allowed to read the value back. */
1340
+ reader_dids: string[];
1341
+ /** READ axis — role ids allowed to read the value back. */
1342
+ reader_roles: string[];
1343
+ /** MANAGE axis — DIDs allowed to rotate the value. */
1344
+ manager_dids: string[];
1345
+ /** MANAGE axis — role ids allowed to rotate the value. */
1346
+ manager_roles: string[];
1347
+ /** USE axis — canonical contract ids allowed to have the value injected. */
1348
+ contract_allowlist: string[];
1349
+ created_at_secs: number;
1350
+ updated_at_secs: number;
1351
+ /** DID of the caller who last wrote the record. */
1352
+ updated_by: string;
1495
1353
  }
1354
+ /** Shallow runtime guard for {@link SecretRecord}. */
1355
+ declare function isSecretRecord(value: unknown): value is SecretRecord;
1356
+ /** Response for `org-secret-list`: redacted per-kind views, no values. */
1357
+ interface SecretListResponse {
1358
+ secrets: SecretView[];
1359
+ }
1360
+ /** Shallow runtime guard for {@link SecretListResponse}. */
1361
+ declare function isSecretListResponse(value: unknown): value is SecretListResponse;
1362
+ /** Response for `org-data-get`. */
1363
+ interface DataGetResponse {
1364
+ entry_id: string;
1365
+ /** Hex-encoded raw payload bytes. */
1366
+ payload_hex: string;
1367
+ }
1368
+ /** Shallow runtime guard for {@link DataGetResponse}. */
1369
+ declare function isDataGetResponse(value: unknown): value is DataGetResponse;
1496
1370
  /**
1497
- * The token-tx-kind wire alphabet (snake_case). Every
1498
- * value listed here is accepted by the server-side
1499
- * `token.get-usage` `kinds` filter.
1500
- */
1501
- type TokenTxKind = "mint" | "burn" | "charge" | "transfer" | "bridge_mint_attest" | "bridge_burn_attest";
1502
- /**
1503
- * Per-caller view direction. `"in"` = caller's balance went up;
1504
- * `"out"` = caller's balance went down. Derived host-side from
1505
- * `(caller_did, tx.src, tx.dst)`; the same `seq_no` appears in both
1506
- * parties' usage feeds with opposite directions on a transfer.
1371
+ * Return shape of `agentCardGet` — composed client-side from the generic
1372
+ * `org-data-get` read of the card's entry (there is no card-specific read
1373
+ * operation on the contract). To check whether a public copy exists, probe
1374
+ * the anonymous `GET /api/agent-card/{did}` endpoint.
1507
1375
  */
1508
- type Direction = "in" | "out";
1376
+ interface AgentCardResponse {
1377
+ /** The agent whose card this is (`did:t3n:<40-hex>`). */
1378
+ agent_did: string;
1379
+ /** The stored card JSON body, verbatim. */
1380
+ card: string;
1381
+ }
1382
+ /** Shallow runtime guard for {@link AgentCardResponse}. */
1383
+ declare function isAgentCardResponse(value: unknown): value is AgentCardResponse;
1509
1384
  /**
1510
- * Discriminated union mirroring the charge-reason wire union.
1511
- * Present only when the row's `kind === "charge"`.
1385
+ * Legacy direct-route org-data envelope shape retained for compatibility.
1386
+ *
1387
+ * This mirrors the removed `/api/user-contract/execute` body format from
1388
+ * the transitional transport. New callers should use `OrgDataClient`,
1389
+ * which now dispatches through authenticated `/api/rpc` +
1390
+ * `action.execute` instead.
1512
1391
  */
1513
- type ChargeReason = {
1514
- kind: "contract_register";
1515
- script_name: string;
1516
- version: string;
1517
- } | {
1518
- kind: "invocation";
1519
- script_name: string;
1392
+ interface OrgDataActionWire {
1393
+ nonce: string;
1394
+ user_did: string;
1395
+ authenticator_id: string;
1396
+ contract_id: string;
1520
1397
  function: string;
1521
- fuel_consumed: number;
1522
- fuel_tokens: number;
1523
- host_call_count: number;
1524
- host_call_tokens: number;
1525
- } | {
1526
- kind: "kv_bytes";
1527
- map: string;
1528
- } | {
1529
- kind: "cas_bytes";
1530
- backend: string;
1531
- } | {
1532
- kind: "outbox_egress";
1533
- upstream: string;
1534
- };
1535
- /**
1536
- * One row in the caller's usage feed — a per-caller projection of
1537
- * the underlying `TokenTx`. `counterparty` is the other party from
1538
- * the caller's perspective: `tx.dst` on outbound entries, `tx.src`
1539
- * on inbound. `null` when the underlying tx has no counterparty
1540
- * (mints have no `src`; burns and charges have no `dst`).
1541
- */
1542
- interface UsageEntry {
1543
- seq_no: number;
1544
- kind: TokenTxKind;
1545
- /** Amount moved, in base units (`1 token = `{@link BASE_UNITS_PER_TOKEN}); see {@link formatTokens}. */
1546
- amount: number;
1547
- timestamp_ms: number;
1548
- direction: Direction;
1549
- counterparty?: string | null;
1550
- reason?: ChargeReason | null;
1551
- note?: string | null;
1398
+ args_hash: string;
1399
+ expires_at_secs: number;
1400
+ signature: string;
1552
1401
  }
1402
+
1553
1403
  /**
1554
- * Response shape of `token.get-usage` — caller's balance plus a
1555
- * paginated slice of their most-recent `token:tx_log` entries.
1404
+ * Delegation grants — the standing on-chain authority a member delegates to
1405
+ * a delegatee (envelope-free authorisation).
1556
1406
  *
1557
- * `next_cursor` is the inclusive upper-bound `seq_no` to pass back
1558
- * as `after_seq` to fetch the next page. `null` (or absent) means
1559
- * the caller's history is fully drained.
1407
+ * The document is one flat list of {@link BoundGrant} rows plus the
1408
+ * document-level discovery grants: `{ grants, discover_dids }`. Each grant's
1409
+ * `grantee` is the delegatee DID it authorises, so there is no per-delegatee
1410
+ * grouping — a member's whole delegation surface is the single `grants` array.
1411
+ * Reads (`member-delegation-get`) and writes (`member-delegation-update`) on
1412
+ * `tee:authorisations/contracts` (the policy's owning contract) are
1413
+ * **SelfOnly**: only the member, authenticated as themselves, may read or write
1414
+ * their own grants. This is the user-approval proof the per-call delegation
1415
+ * credential's `user_sig` used to carry.
1416
+ *
1417
+ * A grant carries `functions`, the agent's delegated org-data `scopes`, the
1418
+ * direct-enumerable `read_scopes`, egress `allowed_hosts`, an optional semver
1419
+ * `version_req`, and an optional validity `window`. The ≤ cap *length* check is
1420
+ * enforced contract-side at write time; the expiry gate is host-side at read
1421
+ * time.
1422
+ *
1423
+ * The SDK is a literal snake_case mirror of the wire: {@link BoundGrant} IS the
1424
+ * wire grant shape, so reads and writes pass through untouched — there is no
1425
+ * casing transform. The only glue here is the read-merge-write helper
1426
+ * ({@link mergeGrants}) that lets a single-grant write preserve every other row
1427
+ * (the contract has no per-field merge; the document IS the new state).
1560
1428
  */
1561
- interface UsagePage {
1562
- balance: BalanceRow;
1563
- entries: UsageEntry[];
1564
- next_cursor?: number | null;
1429
+
1430
+ /**
1431
+ * The full delegation policy document — the shape of BOTH the `member-delegation-get`
1432
+ * output and the `member-delegation-update` input (they are identical). A flat list of
1433
+ * grant rows plus the document-level discovery grants; mirrors the contract
1434
+ * `MemberDelegationDoc` wire shape verbatim (snake_case).
1435
+ *
1436
+ * `discover_dids` is the list of DIDs the member lets their registered agents
1437
+ * *enumerate the contracts of* via `listContracts`: an org DID grants org-mode
1438
+ * discovery, the member's own DID grants self-mode discovery. It lives at
1439
+ * document level — not on a grant — because discovery must surface contracts the
1440
+ * agent cannot yet call. The node's discovery gate additionally requires the
1441
+ * calling agent to be the `grantee` of at least one grant (subject binding), so
1442
+ * an unregistered agent discovers nothing regardless of this list.
1443
+ *
1444
+ * The document IS the new state on a write: an empty `grants` list revokes all
1445
+ * delegated access, and an empty `discover_dids` persists an empty
1446
+ * discovery-grant list (there is no per-field merge). Use {@link mergeGrants} /
1447
+ * {@link mergeDiscoverDids} to read-merge-write a single grant without dropping
1448
+ * the rest.
1449
+ */
1450
+ interface MemberDelegationDoc {
1451
+ /** Every standing delegation-edge grant, each keyed by its `grantee` DID. */
1452
+ grants: BoundGrant[];
1453
+ /** Document-level discovery grants (`did:t3n:<40-hex>` entries). */
1454
+ discover_dids: string[];
1455
+ }
1456
+ /**
1457
+ * Decode a `member-delegation-get` response into a {@link MemberDelegationDoc}. The wire is
1458
+ * already snake_case, so grant rows pass through unchanged — this only defaults
1459
+ * a `null` / absent response (the empty policy) and a missing field to an empty
1460
+ * list. NOT a casing transform.
1461
+ */
1462
+ declare function parseMemberDelegationDoc(response: unknown): MemberDelegationDoc;
1463
+ interface GrantsMergeResult {
1464
+ /** Full merged grant list, ready for `member-delegation-update`. */
1465
+ grants: BoundGrant[];
1466
+ /** `"<grantee> → <contract_id>"` rows preserved from the existing policy. */
1467
+ preservedRows: string[];
1565
1468
  }
1566
1469
  /**
1567
- * Request shape — all fields optional. `limit` clamps to
1568
- * `1..=200` server-side; out-of-range values snap silently to the
1569
- * bounds. `kinds: []` is treated as "no filter".
1470
+ * Merge new grant rows into the existing flat list with `(grantee, contract_id)`
1471
+ * union semantics: an existing row whose `(grantee, contract_id)` matches a new
1472
+ * row is replaced; every other existing row is preserved (and reported in
1473
+ * `preservedRows` as an audit aid). New rows for a `(grantee, contract_id)` not
1474
+ * already present are appended.
1570
1475
  */
1571
- interface GetUsageOptions {
1572
- limit?: number;
1573
- after_seq?: number;
1574
- kinds?: TokenTxKind[];
1575
- }
1476
+ declare function mergeGrants(existing: BoundGrant[], additions: BoundGrant[]): GrantsMergeResult;
1477
+ /**
1478
+ * Order-preserving deduplicating union of discovery-grant DID lists — the
1479
+ * read-merge-write counterpart of {@link mergeGrants} for the document-level
1480
+ * `discover_dids` (the contract rejects duplicate entries, so the union must
1481
+ * dedupe).
1482
+ */
1483
+ declare function mergeDiscoverDids(existing: string[], additions: string[]): string[];
1576
1484
 
1577
1485
  /**
1578
- * Tenant audit-event wire shapes.
1486
+ * KYC types for the `tee:user/contracts::kyc-status` short-poll
1487
+ * function.
1579
1488
  *
1580
- * Mirrors `tenant_types::AuditEvent` and the `audit.get-mine` response
1581
- * (`service::tenant_logs::{AuditBatch, AuditPage}`). A tenant contract
1582
- * emits an audit event via the `logging::audit` host call; the host
1583
- * stamps the identity fields (`subject` / `actor` / `vc_id`) from the
1584
- * verified dispatch context, so a contract can never forge who acted or
1585
- * on whom. Events are permanent (encrypted, append-only) and scoped to a
1586
- * user — distinct from the evicting debug ring read via `getContractLogs`.
1489
+ * The shape mirrors the `kyc-status` wire response.
1490
+ * The bytes go straight from the contract
1491
+ * through the JSON-RPC envelope into [[T3nClient.kycStatus]].
1587
1492
  */
1493
+
1588
1494
  /**
1589
- * One host-stamped audit event. `subject` / `actor` are canonical DID
1590
- * strings. On a self-call `actor === subject` and `vc_id` is `null`; on a
1591
- * delegated call `actor` is the agent and `vc_id` is the delegation
1592
- * credential. The remaining fields are supplied verbatim by the contract.
1593
- */
1594
- interface AuditEvent {
1595
- /** Cluster-deterministic flush timestamp (ms). */
1596
- ts_ms: number;
1597
- /** The user whose data the call touched (host-stamped `pii_did`). */
1598
- subject: string;
1599
- /** The agent (delegated) or user (self-call) who acted (host-stamped). */
1600
- actor: string;
1601
- /** Delegation credential id on a delegated call; `null` on a self-call. */
1602
- vc_id?: string | null;
1603
- /** Contract-supplied: what happened, e.g. `"kyc.approve"`. */
1604
- action: string;
1605
- /** Contract-supplied: what it acted on, e.g. `"user-profile"`. */
1606
- target: string;
1607
- /** Contract-supplied: the result, e.g. `"success"` / `"denied"`. */
1608
- outcome: string;
1609
- /** Contract-supplied: optional free-text / JSON detail. */
1610
- details?: string | null;
1611
- }
1612
- /**
1613
- * One archived batch — the events committed in a single tenant dispatch.
1614
- * Every event in a batch shares the same `subject` / `actor` / `vc_id`.
1615
- */
1616
- interface AuditBatch {
1617
- /** Hex of the archive key — usable directly as `cursor` for the next page. */
1618
- key: string;
1619
- /**
1620
- * Host-stamped: did the emitting dispatch's contract transaction
1621
- * commit? `false` means the call rolled back or trapped, so an event's
1622
- * `outcome: "success"` in this batch is the contract's *claim*, not a
1623
- * committed fact — filter on this when you need only durable events.
1624
- */
1625
- committed: boolean;
1626
- events: AuditEvent[];
1627
- }
1628
- /**
1629
- * `audit.get-mine` response — a page of audit batches, newest scan order.
1630
- * `next_cursor` is present (a key hex) when more batches remain; `null`
1631
- * once the scan reaches the end.
1632
- */
1633
- interface AuditPage {
1634
- batches: AuditBatch[];
1635
- next_cursor?: string | null;
1636
- }
1637
- /**
1638
- * Request shape for {@link T3nClient.getAuditEvents} — all fields
1639
- * optional. Omit `pii_did` to read your own trail (all actors); set it to
1640
- * another user's DID to read, as a delegated agent, the events you
1641
- * performed for them — admitted only while that user's agent-auth grant
1642
- * to you is live. `cursor` is the `next_cursor` from a prior page.
1643
- */
1644
- interface GetAuditEventsOptions {
1645
- pii_did?: string;
1646
- limit?: number;
1647
- cursor?: string;
1648
- }
1649
-
1650
- /**
1651
- * Agent-activity audit-log wire shapes (the node's `auditlog` RPC).
1652
- *
1653
- * Mirrors `service::activity_audit::{ActivityReport, ReportEntry}` and
1654
- * `primitives::audit_log::AuditLogEntry`. One entry per audited contract
1655
- * dispatch — who called, for whom, which contract + function, and how it
1656
- * ended. Entries are reconstructed from the append-only ledger on read, so
1657
- * `seq_no` (the ledger index) and `hash` are derived server-side rather than
1658
- * stored with the record.
1495
+ * Terminal status for a Level 2 KYC verification, plus `pending`.
1659
1496
  *
1660
- * Scope is the caller's **own organisation**, resolved node-side from the
1661
- * session DID: there is no scope parameter, and a page carries **every
1662
- * member's** activity in that org, not just the caller's own. Metadata only —
1663
- * DIDs, never display names, call arguments, or payloads.
1664
- */
1665
- /**
1666
- * Whether the actor is a registered agent or a human / self principal.
1667
- * Decided node-side by an existence check on the actor DID in the agent
1668
- * registry — never inferred from the DID's shape.
1497
+ * - `pending` — provider has not delivered a verdict yet, or the
1498
+ * webhook arrived but the post-action VC issuance hasn't completed.
1499
+ * - `verified` — provider approved AND a VC has been issued. `vcIds`
1500
+ * carries the issued credential ids.
1501
+ * - `rejected` — provider declined / required resubmission /
1502
+ * expired / the user abandoned the flow. `error` may carry a
1503
+ * provider-supplied reason.
1504
+ * - `orphan` — a Veriff webhook arrived with a `vendorData` that
1505
+ * couldn't be matched to any user. Should not
1506
+ * happen in the MetaMask flow but the contract surfaces it for
1507
+ * completeness.
1669
1508
  */
1670
- type ActivityCallerType = "agent" | "human";
1509
+ type KycStatusKind = "pending" | "verified" | "rejected" | "orphan";
1671
1510
  /**
1672
- * Host-stamped outcome of an audited dispatch.
1511
+ * Snapshot returned by `tee:user/contracts::kyc-status`.
1673
1512
  *
1674
- * - `success` — the business transaction committed.
1675
- * - `denied` — authorisation refused the call.
1676
- * - `error` — the call was allowed but failed / rolled back.
1513
+ * Field names use camelCase on the SDK boundary even though the
1514
+ * wire is snake_case — the wrapper rewrites keys at the client edge
1515
+ * so callers don't see the JSON shape leaking through.
1677
1516
  */
1678
- type ActivityOutcome = "success" | "denied" | "error";
1679
- /** One audited call. */
1680
- interface ActivityEntry {
1517
+ interface KycStatus {
1518
+ /** Terminal status if reached, otherwise `pending`. */
1519
+ status: KycStatusKind;
1681
1520
  /**
1682
- * Ledger index of the entry — its unique, ordered id. Use it as the row key
1683
- * and as the ordering key: it is monotonic, whereas {@link timestamp_ms} is
1684
- * per-node wall clock.
1521
+ * Provider being polled. Echoed back so callers that didn't
1522
+ * supply one see the contract's default (`"veriff"` in phase one).
1685
1523
  */
1686
- seq_no: number;
1687
- /** Hex SHA-256 of the stored entry (64 chars) — read-time tamper evidence. */
1688
- hash: string;
1524
+ provider: string;
1689
1525
  /**
1690
- * Call time in Unix ms, stamped on the node that took the request. NOT a
1691
- * cluster-assigned time, so entries from different nodes can be skewed by
1692
- * their clock offset — order by {@link seq_no}, not by this.
1526
+ * Unix-millis of the latest contract-visible event:
1527
+ * VC issuance time, attestation arrival time, session-row
1528
+ * `started_at_ms`, or orphan-record arrival time. Best-effort —
1529
+ * `undefined` when no source carries a usable timestamp.
1693
1530
  */
1694
- timestamp_ms: number;
1695
- /** Agent vs human, from the agent-registry check on {@link actor}. */
1696
- caller_type: ActivityCallerType;
1697
- /** DID that actually invoked the contract. */
1698
- actor: string;
1531
+ updatedAt?: number;
1699
1532
  /**
1700
- * DID of the owner the caller acted for. Equals {@link actor} on a self /
1701
- * own-authority call — never null.
1533
+ * VC ids appended for this provider, in append order. Empty for
1534
+ * `pending` / `rejected` / `orphan`.
1702
1535
  */
1703
- on_behalf_of: string;
1536
+ vcIds: string[];
1704
1537
  /**
1705
- * Organisation the acting principal belongs to — the report's scope key, so
1706
- * it is identical on every row of a page. Falls back to `on_behalf_of` when
1707
- * that principal is in no organisation.
1538
+ * Provider-supplied reason for `rejected`, when available.
1708
1539
  */
1709
- org: string;
1710
- /** Contract that ran, e.g. `tee:user/contracts`. */
1711
- contract: string;
1712
- /** Contract function invoked, e.g. `user-upsert`. */
1713
- function: string;
1714
- /** success / denied / error — host-stamped from the dispatch result. */
1715
- outcome: ActivityOutcome;
1540
+ error?: string;
1541
+ }
1542
+ /**
1543
+ * Polling cadence for [[T3nClient.kycStatusPoll]]. Defaults:
1544
+ * poll fast for the first 30 seconds, then back
1545
+ * off, and bail after 5 minutes.
1546
+ */
1547
+ interface KycPollCadence {
1548
+ /** Poll interval in ms while `elapsed < switchAtMs`. Default: 2000. */
1549
+ fastMs: number;
1550
+ /** Poll interval in ms once `elapsed >= switchAtMs`. Default: 5000. */
1551
+ slowMs: number;
1552
+ /** Elapsed-ms threshold to switch from fast to slow cadence. Default: 30_000. */
1553
+ switchAtMs: number;
1716
1554
  /**
1717
- * Role ids the acting authority carried at call time: the actor's role in
1718
- * the organisation on a self-call, the roles the owner granted the agent on
1719
- * a delegated call. Omitted when the authority carried no role (direct
1720
- * grants, an individual, or an entry recorded before roles were captured).
1721
- * On a `denied` entry this is the caller's *claimed* authority, not a
1722
- * validated one.
1555
+ * Maximum total time to spend polling before rejecting with
1556
+ * [[KycStatusTimeoutError]]. Default: 300_000 (5 minutes).
1723
1557
  */
1724
- roles?: string[];
1558
+ timeoutMs: number;
1725
1559
  }
1726
1560
  /**
1727
- * One page of the organisation's activity report — **newest first**, i.e.
1728
- * descending `seq_no`.
1561
+ * Optional knobs for [[T3nClient.kycStatusPoll]]. Most callers won't
1562
+ * touch any of these — the cadence defaults are baked in.
1729
1563
  */
1730
- interface ActivityReport {
1731
- entries: ActivityEntry[];
1564
+ interface KycPollOptions {
1732
1565
  /**
1733
- * Cursor to resume from — pass it back as
1734
- * {@link GetActivityLogOptions.before_seq}. `null` once the requested window
1735
- * is exhausted.
1736
- *
1737
- * A live cursor with **fewer rows than `limit`, or none at all**, is normal:
1738
- * the node also caps how much ledger one call decrypts, and that cap can trip
1739
- * before the window ends. Page until this is `null`, never on a short or
1740
- * empty page.
1566
+ * Cancellation signal. When aborted, the helper rejects with
1567
+ * `signal.reason` (or a generic `AbortError` if the consumer
1568
+ * didn't supply a reason). The currently-in-flight `kycStatus()`
1569
+ * call also receives the signal so it can short-circuit.
1741
1570
  */
1742
- next_seq: number | null;
1743
- }
1744
- /** Params for one activity-report page. All optional; `{}` is valid. */
1745
- interface GetActivityLogOptions {
1746
- /** Window start, Unix ms, inclusive. Defaults to 0 (no lower bound). */
1747
- from_ms?: number;
1748
- /** Window end, Unix ms, inclusive. Defaults to unbounded. */
1749
- to_ms?: number;
1571
+ signal?: AbortSignal;
1750
1572
  /**
1751
- * Cursor, inclusive — the highest `seq_no` this page may return. Omitted ⇒
1752
- * start at the newest entry in the window. Pages walk downwards, so this is
1753
- * the previous page's {@link ActivityReport.next_seq}.
1573
+ * Called with every snapshot the helper receives, including
1574
+ * non-terminal `pending` ones. Useful for surfacing intermediate
1575
+ * UI states (e.g. "still waiting on provider…"). Errors thrown
1576
+ * from this callback are caught and ignored — they must not
1577
+ * sink the poll loop.
1754
1578
  */
1755
- before_seq?: number;
1579
+ onUpdate?: (status: KycStatus) => void;
1756
1580
  /**
1757
- * Rows returned this page. Clamped server-side to 1–1000 (default 200).
1758
- *
1759
- * A page can still be shorter than this (or empty) with a live `next_seq` —
1760
- * the node's own scan cap can trip first. See {@link ActivityReport.next_seq}.
1581
+ * Override one or more cadence fields. Anything not specified
1582
+ * uses the defaults from [[DEFAULT_KYC_POLL_CADENCE]].
1761
1583
  */
1762
- limit?: number;
1584
+ cadence?: Partial<KycPollCadence>;
1585
+ /**
1586
+ * Provider id to poll. Defaults to the contract default
1587
+ * (`"veriff"` in phase one). Mirrored on the wire as
1588
+ * `input.provider_id`.
1589
+ */
1590
+ providerId?: string;
1591
+ }
1592
+ /**
1593
+ * Default cadence used by [[T3nClient.kycStatusPoll]] when the caller
1594
+ * doesn't override `cadence.*`.
1595
+ */
1596
+ declare const DEFAULT_KYC_POLL_CADENCE: KycPollCadence;
1597
+ /**
1598
+ * Subset of [[KycStatusKind]] that ends a poll. `pending` is the
1599
+ * only non-terminal value.
1600
+ */
1601
+ declare const TERMINAL_KYC_STATUSES: ReadonlySet<KycStatusKind>;
1602
+ /**
1603
+ * Thrown by [[T3nClient.kycStatusPoll]] when the cadence's
1604
+ * `timeoutMs` elapses without a terminal status arriving. The
1605
+ * `lastStatus` field is the most recent (necessarily `pending`)
1606
+ * snapshot the helper saw, useful for surfacing "we tried for N
1607
+ * minutes but Veriff is still working" UX.
1608
+ */
1609
+ declare class KycStatusTimeoutError extends T3nError {
1610
+ /** The timeout (ms) the helper exhausted before a terminal status arrived. */
1611
+ readonly timeoutMs: number;
1612
+ /** The last `pending` snapshot before timeout, if any. */
1613
+ readonly lastStatus?: KycStatus | undefined;
1614
+ constructor(
1615
+ /** The timeout (ms) the helper exhausted before a terminal status arrived. */
1616
+ timeoutMs: number,
1617
+ /** The last `pending` snapshot before timeout, if any. */
1618
+ lastStatus?: KycStatus | undefined);
1763
1619
  }
1764
1620
 
1765
1621
  /**
1766
- * Contract-discovery wire shapes.
1622
+ * Wire types for the explicit `otp-request` /
1623
+ * `otp-verify` / slim `user-upsert` exports on `tee:user/contracts`
1624
+ * (`tee:user@2.0.0`).
1767
1625
  *
1768
- * Field-for-field mirrors of the node's `contracts.list` and `delegation.check`
1769
- * JSON-RPC responses (`service::contract_discovery::{ListedContract,
1770
- * ListContractsResponse}` and `service::grant_check::{GrantRef,
1771
- * GrantCheckResponse}`). Both methods are session-authenticated plaintext reads
1772
- * dispatched over `/api/rpc` — the same posture as `token.get-usage` — so the
1773
- * SDK wrappers return the parsed `result` object directly.
1626
+ * Pre-2.0.0 the user contract dispatched OTP request and OTP verify
1627
+ * implicitly from the input shape of a single `user-upsert` call.
1628
+ * 2.0.0 splits that surface into three explicit functions; the
1629
+ * shapes here mirror the OTP / user-upsert wire contract.
1630
+ *
1631
+ * Bytes flow directly from the contract
1632
+ * through the JSON-RPC envelope into the SDK wrappers
1633
+ * (`T3nClient.otpRequest`, `T3nClient.otpVerify`,
1634
+ * `T3nClient.submitUserInput`).
1774
1635
  */
1775
- /** The navigable starting points of the discovery funnel. */
1776
- type ListContractsScope = "core" | "org" | "self";
1777
- /** Params for `contracts.list` (every field optional; `{}` lists core). */
1778
- interface ListContractsParams {
1779
- /** `"core"` (default) | `"org"` | `"self"`. */
1780
- scope?: ListContractsScope;
1781
- /** Target org DID (required for scope `"org"`). */
1782
- org_did?: string;
1783
- /** The member the agent acts for (required for scope `"org"` / `"self"`). */
1784
- pii_did?: string;
1785
- /** Page offset (defaults to 0 server-side). */
1786
- offset?: number;
1787
- /** Page size (defaults + clamped server-side). */
1788
- limit?: number;
1789
- }
1790
- /** Contract kind — `"core"` platform system contract, `"tenant"` z-space. */
1791
- type ContractKind = "core" | "tenant";
1792
- /** One contract as presented by `contracts.list`. */
1793
- interface ListedContract {
1794
- /** Canonical name: `tee:<name>` for core, `z:<tid>:<tail>` for tenant. */
1795
- name: string;
1796
- kind: ContractKind;
1797
- /** Current registered version; `null` when the contract is not registered. */
1798
- version: string | null;
1799
- /** Descriptor summary, or empty when no descriptor is published. */
1800
- summary: string;
1801
- /** Descriptor tags, or empty. */
1802
- tags: string[];
1803
- /** Owning DID: the org DID (org mode) or the member's own DID (self mode). */
1804
- owner_org_did?: string;
1805
- /**
1806
- * Human-facing short name: the trailing segment of `name` (`payroll` from
1807
- * `z:<tid>:payroll`, `user` from `tee:user`). Present this to people instead
1808
- * of the full canonical `name`, which remains the dispatch key.
1809
- */
1810
- short_name: string;
1811
- }
1812
- /** Response body for `contracts.list`. */
1813
- interface ListContractsResult {
1814
- scope: string;
1815
- contracts: ListedContract[];
1816
- next_offset: number | null;
1817
- }
1818
- /** Which standing grant a satisfied/missing entry refers to. */
1819
- type DelegationGrantKind = "agent_auth" | "user_grant";
1820
- /** Params for `delegation.check` (the generic capability read). */
1821
- interface GrantCheckParams {
1822
- /** The target contract whose requirements are checked. */
1823
- contract: string;
1824
- /** The member the agent wants to act for (the subject). */
1825
- pii_did: string;
1826
- /** Functions the intended action needs. */
1827
- functions: string[];
1828
- /** Org-data scopes the intended action needs. */
1829
- scopes: string[];
1830
- }
1831
- /** One grant requirement — satisfied or missing. */
1832
- interface DelegationGrantRef {
1833
- grant: DelegationGrantKind;
1834
- /** The target contract's canonical name. */
1835
- contract: string;
1836
- functions: string[];
1837
- scopes: string[];
1838
- }
1636
+
1839
1637
  /**
1840
- * Response for `delegation.check`: the `agent_auth ∩ UserGrant` verdict.
1841
- *
1842
- * `disclosed` is `true` only when the agent is registered under `pii_did`, so
1843
- * org-side status was safe to disclose; `false` yields the uniform,
1844
- * non-disclosive verdict (`authorised:false, satisfied:[], missing:[]`) that is
1845
- * byte-invariant to the requested capability (R5 anti-enumeration).
1638
+ * OTP delivery channel. Matches the `OtpContactChannel` Rust enum
1639
+ * with `serde(rename_all = "snake_case")`.
1846
1640
  */
1847
- interface GrantCheckResult {
1848
- authorised: boolean;
1849
- disclosed: boolean;
1850
- satisfied: DelegationGrantRef[];
1851
- missing: DelegationGrantRef[];
1852
- }
1853
- /** Response for the `whoami` operation: who the key resolves to, and where. */
1854
- interface WhoamiResult {
1855
- /** The DID the relayed api key resolves to. */
1856
- did: string;
1857
- /**
1858
- * The org DIDs the agent itself belongs to (its own agent-keyed membership),
1859
- * or `[]` when it belongs to none. Each is a valid `org_did` for
1860
- * `contracts.list` scope `"org"`, so this is the seed for browsing the agent's
1861
- * own orgs.
1862
- */
1863
- organisations: string[];
1864
- /**
1865
- * The agent's owning / managing DID — usually the org that created it. `null`
1866
- * for a missing record (agents created without a hosted card or agent URI have
1867
- * no registry record), a record with no owner link, or a malformed record
1868
- * (decode failure is logged at `WARN`, never a silent authority downgrade); a
1869
- * snapshot read failure is surfaced as an error, not reported as `null`. The
1870
- * owner link is mutable and may have changed since creation, so treat this as
1871
- * best-effort, not an authority.
1872
- */
1873
- owner: string | null;
1874
- }
1875
- /** Params for the `describe.contract` operation. */
1876
- interface DescribeContractParams {
1877
- /**
1878
- * Registry name: `tee:<name>/contracts` (core) or `z:<tid>:<tail>` (tenant).
1879
- * The bare core form `contracts.list` presents (`tee:<name>` / `y:<name>`) is
1880
- * also accepted — the node maps it onto the `/contracts` registry key — so a
1881
- * `ListedContract.name` feeds straight in.
1882
- */
1883
- contract: string;
1884
- /** Explicit version; omitted resolves the current registered version. */
1885
- version?: string;
1886
- }
1887
- /** Params for the `describe.function` operation. */
1888
- interface DescribeFunctionParams {
1889
- /**
1890
- * Registry name: `tee:<name>/contracts` (core) or `z:<tid>:<tail>` (tenant).
1891
- * The bare core form `contracts.list` presents (`tee:<name>` / `y:<name>`) is
1892
- * also accepted — the node maps it onto the `/contracts` registry key.
1893
- */
1894
- contract: string;
1895
- /** The single function to project from the contract's descriptor. */
1896
- function: string;
1897
- /** Explicit version; omitted resolves the current registered version. */
1898
- version?: string;
1899
- }
1641
+ type OtpChannel = "email" | "sms";
1900
1642
  /**
1901
- * One function's descriptor entry — the `describe.function` result and the
1902
- * element type of a {@link ContractDescriptorDocument}'s `functions` array.
1643
+ * Discriminated OTP contact target. Mirrors the Rust `OtpRequest` enum
1644
+ * (`email_channel` / `sms_channel` on the wire). Exactly one branch is
1645
+ * set — no parallel optional email + phone with a separate channel tag.
1903
1646
  *
1904
- * Left open-ended: the descriptor document's full schema (argument schema,
1905
- * wire projection, auth requirements) is owned by the contract descriptor
1906
- * registry and served verbatim by the node. The named fields are the ones the
1907
- * node's descriptor path always presents.
1647
+ * The legacy `keys.generic_api.otp_channel` body shadow was removed
1648
+ * in 2.0.0 — the contract rejects calls carrying it with a
1649
+ * `legacy_field` error.
1908
1650
  */
1909
- interface FunctionDescriptorEntry {
1910
- /** Contract function name (e.g. `compute-payroll`). */
1911
- name: string;
1912
- summary?: string;
1913
- /** Whether the function mutates state. */
1914
- mutates?: boolean;
1915
- [key: string]: unknown;
1916
- }
1651
+ type OtpRequestInput = {
1652
+ emailChannel: {
1653
+ emailAddress: string;
1654
+ };
1655
+ } | {
1656
+ smsChannel: {
1657
+ phoneNumber: string;
1658
+ };
1659
+ };
1917
1660
  /**
1918
- * The node's descriptor document for a contract — the `descriptor` field of a
1919
- * {@link DescribeContractResult}. Open-ended for the same reason as
1920
- * {@link FunctionDescriptorEntry}: the node returns the registry's descriptor
1921
- * document verbatim.
1661
+ * Response returned by `otp-request`. Mirrors the OTP wire response.
1662
+ *
1663
+ * - `contact` echoes the OTP destination so clients that race
1664
+ * multiple channels can correlate replies.
1665
+ * - `expiresAtSec` is the Unix-second TTL the host minted for the
1666
+ * pending OTP. Absent in `skip_otp` test environments.
1667
+ * - `status` is `"otp_pending"` on the happy path. `"otp_failed"`
1668
+ * only appears on retry without a fresh request — usually you
1669
+ * shouldn't see it on `otp-request`.
1670
+ * - `txHash` is the host-enriched ledger ref for the OTP-pending
1671
+ * write (the contract leaves it `null`; the host injects).
1672
+ * - `isNewProfile` is `true` on a fresh DID's first OTP request —
1673
+ * read this to detect "did the user just register".
1922
1674
  */
1923
- interface ContractDescriptorDocument {
1924
- name?: string;
1925
- version?: string;
1926
- summary?: string;
1927
- tags?: string[];
1928
- functions?: FunctionDescriptorEntry[];
1929
- [key: string]: unknown;
1675
+ interface OtpRequestResult {
1676
+ contact: string;
1677
+ channel: OtpChannel;
1678
+ expiresAtSec?: number;
1679
+ status?: string;
1680
+ txHash?: string;
1681
+ isNewProfile?: boolean;
1930
1682
  }
1931
1683
  /**
1932
- * Result of the `describe.contract` operation. The node wraps the descriptor
1933
- * document with the resolved dispatch `version`, so an authorised describe hands
1934
- * back the exact `scriptVersion` an {@link invoke} call needs alongside the
1935
- * schema. Returned only on the authorised path; a gate miss or unknown contract
1936
- * yields the uniform non-disclosive error, never this wrapper.
1684
+ * Input to `T3nClient.otpVerify`. `otpCode` is mandatory; `request`
1685
+ * repeats the same discriminated contact shape as {@link OtpRequestInput}.
1937
1686
  */
1938
- interface DescribeContractResult {
1939
- /** The canonical registry name, echoed from the request. */
1940
- contract: string;
1941
- /** The resolved dispatch version — pass as `scriptVersion` to `invoke`. */
1942
- version: string;
1943
- /** The contract's full descriptor document. */
1944
- descriptor: ContractDescriptorDocument;
1687
+ interface OtpVerifyInput {
1688
+ otpCode: string;
1689
+ request: OtpRequestInput;
1945
1690
  }
1946
1691
  /**
1947
- * Result of the `describe.function` operation: the resolved dispatch `version`
1948
- * paired with the single projected function entry. Same authorised-path-only
1949
- * guarantee as {@link DescribeContractResult}.
1692
+ * Suggestion surfaced when the bind-target contact already belongs
1693
+ * to another DID. The contract refuses to silently steal the
1694
+ * authenticator; the caller must resolve the merge (typically via
1695
+ * `merge-profiles`) before re-attempting verify.
1950
1696
  */
1951
- interface DescribeFunctionResult {
1952
- /** The canonical registry name, echoed from the request. */
1953
- contract: string;
1954
- /** The resolved dispatch version — pass as `scriptVersion` to `invoke`. */
1955
- version: string;
1956
- /** The single projected function's descriptor entry. */
1957
- descriptor: FunctionDescriptorEntry;
1697
+ interface OtpMergeSuggestion {
1698
+ existingDid: string;
1699
+ currentDid: string;
1700
+ email?: string;
1701
+ phone?: string;
1702
+ channel: OtpChannel;
1958
1703
  }
1959
-
1960
1704
  /**
1961
- * T3n Client - Main SDK class
1705
+ * Response returned by `otp-verify`. Mirrors the OTP-verify wire response.
1962
1706
  *
1963
- * Provides a simple interface for establishing secure sessions with T3n nodes.
1964
- * All cryptographic complexity is handled in WASM components.
1707
+ * - `email` is populated on `channel = "email"` success;
1708
+ * `phone` on `channel = "sms"` success. Mutually exclusive on
1709
+ * the happy path.
1710
+ * - `status` carries `"otp_failed"` / `"otp_expired"` on retry; the
1711
+ * happy path leaves it `undefined`.
1712
+ * - `mergeSuggestion` is set when the contact-to-bind is already
1713
+ * owned by another DID. Wire it into your merge UX.
1965
1714
  */
1966
-
1715
+ interface OtpVerifyResult {
1716
+ txHash?: string;
1717
+ did: string;
1718
+ channel: OtpChannel;
1719
+ email?: string;
1720
+ phone?: string;
1721
+ status?: string;
1722
+ mergeSuggestion?: OtpMergeSuggestion;
1723
+ isNewProfile?: boolean;
1724
+ }
1967
1725
  /**
1968
- * Main T3n SDK Client
1969
- */
1970
- declare class T3nClient {
1971
- private readonly config;
1972
- private readonly transport;
1973
- /**
1974
- * Resolved node base URL. Snapshotted in the constructor so the
1975
- * typed contract wrappers (`kycStatus`, `getSelfEthAddress`, …)
1976
- * can call `getScriptVersion()` against the same host the
1977
- * transport talks to. Used only by the `script_version: "latest"`
1978
- * resolution path in {@link executeUserContract}.
1979
- */
1980
- private readonly effectiveBaseUrl;
1981
- /**
1982
- * Server-minted session ID, set by {@link handshake} from the
1983
- * `Session-Id` response header. `null`
1984
- * until the handshake completes. Client code cannot set it — a
1985
- * client-supplied session id is rejected, closing the
1986
- * session-fixation vector.
1987
- */
1988
- private sessionId;
1989
- /**
1990
- * Set by {@link sendRpcRequest} when an `auth.handshake` RPC is
1991
- * actually issued. Decouples the "flow completed without talking
1992
- * to a server" case (unit-test mocks that only exercise handler
1993
- * delegation) from the real "server must mint the id" invariant:
1994
- * we only enforce the mint requirement when a round-trip happened.
1995
- */
1996
- private handshakeSentRpc;
1997
- private readonly logger;
1998
- private readonly encryption;
1999
- private status;
2000
- /**
2001
- * In-flight WASM state-machine bytes. Holds the opaque state
2002
- * returned by `flow[method].next()` between iterations of
2003
- * `runFlow`. Always cleared at the top of `runFlow` and again
2004
- * once `tryFinalize` has extracted the terminal payload — so
2005
- * outside of an active loop these slots are always `null`.
2006
- */
2007
- private wasmState;
2008
- /**
2009
- * Terminal payloads produced by `flow[method].finish()`:
2010
- * - `handshake` → serialized session blob, used by
2011
- * `getSessionState()` for subsequent `session.encrypt` calls.
2012
- * - `auth` → serialized DID; the public `authenticate()` decodes
2013
- * it into `this.did` and the slot is otherwise unused.
2014
- * - `execute` → unused (executes return immediately to the caller).
2015
- *
2016
- * Stored in a dedicated field instead of reusing `wasmState`
2017
- * because the two meanings — "in-flight state machine" vs
2018
- * "finalized payload" — are semantically different and merging
2019
- * them re-introduces the bug-class this guard exists to prevent.
2020
- */
2021
- private finalizedPayload;
2022
- private did;
2023
- private handshakeResult;
2024
- constructor(config: T3nClientConfig);
2025
- /**
2026
- * Start the handshake process with the T3n node
2027
- */
2028
- handshake(): Promise<HandshakeResult>;
2029
- /**
2030
- * Authenticate with the T3n node.
2031
- *
2032
- * For OIDC, this runs a two-step nonce-bound flow:
2033
- * 1. Sends `InitOidcAuth` to server → receives session-binding nonce.
2034
- * 2. Calls `getIdToken(nonce)` callback so the app can include the
2035
- * nonce in the Google authorization URL.
2036
- * 3. Sends `SubmitIdToken` with the nonce-bearing token → receives DID.
2037
- */
2038
- authenticate(authInput: AuthInput): Promise<Did>;
1726
+ * Level-1 user-input fields accepted by the slim `user-upsert`. Field names
1727
+ * are the on-the-wire names — `submitUserInput` sends this object verbatim,
1728
+ * so keys must match the contract exactly (snake_case). The canonical Level-1
1729
+ * set is the six fields below; the shape is intentionally open so callers can
1730
+ * add provider-specific fields the contract knows how to merge.
1731
+ *
1732
+ * `email_address` / `phone_number` are normally bound via the OTP roundtrip
1733
+ * before `submitUserInput`, but the contract accepts them directly here too.
1734
+ */
1735
+ interface UserInputProfile {
1736
+ first_name?: string;
1737
+ last_name?: string;
1738
+ country_of_residence?: string;
1739
+ document_issuance_country?: string;
1740
+ ssn?: string;
1741
+ address?: string;
1742
+ email_address?: string;
1743
+ phone_number?: string;
1744
+ campaign_code?: string;
1745
+ role?: string;
1746
+ [key: string]: unknown;
1747
+ }
1748
+ /**
1749
+ * Input to `T3nClient.submitUserInput`. Maps onto the slim
1750
+ * `user-upsert` request shape: `{ profile, organisation_did?,
1751
+ * attestations?, keys? }`.
1752
+ */
1753
+ interface SubmitUserInputArgs {
1754
+ profile: UserInputProfile;
1755
+ organisationDid?: string;
1756
+ attestations?: unknown;
1757
+ keys?: Record<string, unknown>;
2039
1758
  /**
2040
- * Add an Ethereum wallet as an additional authenticator on the
2041
- * already-authenticated account.
2042
- *
2043
- * Proves control of the wallet via SIWE and links it to the session's
2044
- * EXISTING DID (resolved server-side from the session) — it does NOT
2045
- * mint a new DID and does NOT change the session: `this.did` and
2046
- * `this.status` are left untouched, and no new cookie is issued.
2047
- *
2048
- * Requires a completed {@link authenticate} first (e.g. an OIDC
2049
- * login). Only Ethereum is supported — OIDC/email identities are
2050
- * established at login, not added afterwards.
2051
- *
2052
- * Reuses the same client-side eth state machine as login, but posts
2053
- * to the authenticated `auth.add-authenticator` route. If the wallet
2054
- * is already linked to a different account, the server rejects with a
2055
- * typed `eth_auth_map_conflict` error (resolve via account merge).
2056
- *
2057
- * @returns the existing DID the wallet was linked to.
1759
+ * KYC webhook orphan-attestation flow. When set, the contract
1760
+ * skips the email-not-verified gate and only records the
1761
+ * attestation if the DID has no profile yet.
1762
+ * Most callers should leave this `undefined`.
2058
1763
  */
2059
- addAuthMethod(authInput: EthAuthInput): Promise<Did>;
1764
+ requireExistingUser?: boolean;
2060
1765
  /**
2061
- * OIDC two-step authentication with session-binding nonce.
1766
+ * Testnet self-admit. When `true`, the contract additionally
1767
+ * runs the self-admit side-effect after the profile commit: writes
1768
+ * the caller's DID into `idx:_tenants` + `idx:_tenant_quotas` and
1769
+ * mints any operator-configured welcome credits. Inspect the
1770
+ * `tenantAdmit` field on the response for the outcome.
2062
1771
  *
2063
- * Bypasses the WASM client state machine and makes two encrypted
2064
- * RPC calls directly:
2065
- * 1. `InitOidcAuth { provider }` → server generates nonce → returns
2066
- * `ProvideNonce { nonce }`.
2067
- * 2. App calls `getIdToken(nonce)` to obtain a nonce-bound `id_token`.
2068
- * 3. `SubmitIdToken { id_token }` → server verifies token + nonce →
2069
- * returns `Finish { did }`.
2070
- */
2071
- private authenticateOidc;
2072
- /**
2073
- * Parse a `Finish { did }` reply shared by the manual (non-WASM) auth flows
2074
- * that bypass the client state machine (interactive OIDC, keyless workload).
1772
+ * Testnet-only. Production clusters return
1773
+ * `tenantAdmit.status = "refused"` with
1774
+ * `reason = "not_testnet" | "self_admit_disabled" | "not_eth_derived"`.
1775
+ * The profile commit always succeeds regardless of the inner outcome.
2075
1776
  *
2076
- * Validates the `oidc_auth_action` tag before reading `did`: a decodable but
2077
- * non-`Finish` reply is reported as such rather than silently misread as a
2078
- * missing DID (which would discard whatever the server actually said). Returns
2079
- * the session {@link Did}.
1777
+ * Most callers should leave this `undefined`.
2080
1778
  */
2081
- private parseFinishDid;
1779
+ becomeDevTenant?: boolean;
1780
+ }
1781
+ /**
1782
+ * Testnet self-admit projection from `user-upsert`. Present only
1783
+ * when the caller set `becomeDevTenant: true` on the request.
1784
+ *
1785
+ * - `status: "admitted"` — first call for this DID; tenant record
1786
+ * committed and (if configured) welcome credits minted into
1787
+ * `grantedCredits`.
1788
+ * - `status: "already-admitted"` — replay; idempotent no-op.
1789
+ * - `status: "refused"` — the cluster declined the self-admit;
1790
+ * `reason` is the machine-readable cause (`not_testnet`,
1791
+ * `self_admit_disabled`, `not_eth_derived`), `detail` is a
1792
+ * human-readable string.
1793
+ */
1794
+ type TenantAdmitStatus = "admitted" | "already-admitted" | "refused";
1795
+ interface TenantAdmitProjection {
1796
+ status: TenantAdmitStatus;
1797
+ grantedCredits?: string;
1798
+ reason?: string;
1799
+ detail?: string;
1800
+ }
1801
+ /**
1802
+ * Response shape returned by the slim `user-upsert`. Carries the
1803
+ * post-merge tx hash plus the Level-1 merge diagnostics
1804
+ * (`refusedFields`, `mergeSuggestion`) the pre-2.0.0 omnibus
1805
+ * `UpsertResponse` already surfaced.
1806
+ */
1807
+ interface SubmitUserInputResult {
1808
+ txHash?: string;
1809
+ refusedFields?: string[];
1810
+ mergeSuggestion?: OtpMergeSuggestion;
1811
+ userFound?: boolean;
2082
1812
  /**
2083
- * Workload (keyless hosted-agent) single-call authentication.
2084
- *
2085
- * A hosted agent authenticates with its OWN OIDC workload identity —
2086
- * a machine `id_token` whose `(iss, sub)` the caller has already
2087
- * fetched — forwarded through this transport by value. Distinct from
2088
- * the interactive {@link authenticateOidc} flow: there is NO
2089
- * session-binding nonce and NO `InitOidcAuth` round-trip. We make a
2090
- * SINGLE encrypted RPC call:
2091
- *
2092
- * 1. `SubmitWorkloadToken { provider, id_token }` → the node verifies
2093
- * the token and mints/resolves the DID `oidc:<iss>:<sub>` →
2094
- * returns `Finish { did }`.
2095
- *
2096
- * Bypasses the WASM client state machine (mirrors `authenticateOidc` /
2097
- * `authenticateEmailOtp`); the `SubmitWorkloadToken` action tag is
2098
- * matched server-side.
1813
+ * Testnet self-admit projection. Present only when the caller
1814
+ * set `becomeDevTenant: true` on the request.
2099
1815
  */
2100
- private authenticateWorkload;
1816
+ tenantAdmit?: TenantAdmitProjection;
1817
+ }
1818
+ /**
1819
+ * Discriminator for {@link UserUpsertError}. Mirrors the
1820
+ * `UserUpsertError` wire enum and its `<code>:<detail>` wire
1821
+ * format. Branch with a `switch` over `kind`.
1822
+ *
1823
+ * - `EmailNotVerified` — the slim `user-upsert` was called against
1824
+ * a DID that has no verified email and no proving authenticator.
1825
+ * Run `otpRequest` + `otpVerify` first (or accept an
1826
+ * OIDC/Email-authed session).
1827
+ * - `LegacyField` — caller passed a pre-2.0.0 dispatch field
1828
+ * (`otp_code` to a non-verify export, or
1829
+ * `keys.generic_api.otp_channel` anywhere). Migrate the call
1830
+ * site to the new explicit functions.
1831
+ * - `UserNotFound` — `requireExistingUser` was set but no profile
1832
+ * exists for the DID. The attestation is recorded for audit;
1833
+ * no profile created.
1834
+ */
1835
+ type UserUpsertErrorKind = "EmailNotVerified" | "LegacyField" | "UserNotFound";
1836
+ /**
1837
+ * Typed wrapper for the `<code>:<detail>` errors the slim
1838
+ * `user-upsert` and the OTP entry points emit. `kind` is the
1839
+ * structured discriminator the SDK derives from the error code
1840
+ * prefix; `code` and `detail` retain the wire components for
1841
+ * fall-through logging.
1842
+ *
1843
+ * Throw site: `T3nClient.submitUserInput` (and friends) when the
1844
+ * contract returns a string error matching the
1845
+ * `<code>:<detail>` shape.
1846
+ */
1847
+ declare class UserUpsertError extends T3nError {
1848
+ readonly kind: UserUpsertErrorKind | "Unknown";
1849
+ readonly detail: string;
1850
+ constructor(code: string, detail: string);
2101
1851
  /**
2102
- * Email-OTP two-step authentication.
2103
- *
2104
- * Symmetric with {@link authenticateOidc}: bypasses the WASM client
2105
- * state machine and makes two encrypted RPC calls directly:
2106
- * 1. `InitEmailOtp { email }` → node sends a one-time code → returns
2107
- * an `OtpSent` ack.
2108
- * 2. App calls `getOtpCode()` to obtain the code the user received.
2109
- * 3. `SubmitOtpCode { code }` → node verifies the code, resolves the
2110
- * DID on the shared `email:<addr>` key → returns `Finish { did }`.
2111
- *
2112
- * Because the DID is keyed on the (server-lowercased) email, a user
2113
- * who previously signed in with the same address via Google (OIDC)
2114
- * authenticates to the SAME DID — one identity, no double account.
1852
+ * Try to parse a contract error string into a `UserUpsertError`.
1853
+ * Returns `null` if `raw` doesn't match the `<code>:<detail>`
1854
+ * shape — caller falls back to a generic error.
2115
1855
  */
2116
- private authenticateEmailOtp;
2117
- /**
1856
+ static fromWire(raw: string): UserUpsertError | null;
1857
+ }
1858
+
1859
+ /**
1860
+ * Token-metering wire shapes.
1861
+ *
1862
+ * Mirrors the token-metering wire contract. `u128` fields land on the
1863
+ * wire as JSON numbers (same convention as the existing
1864
+ * `token.get-balance` response) — JS clients with histories that
1865
+ * exceed 2⁵³ tokens should switch to a streaming JSON parser; the
1866
+ * common case fits in `number` losslessly.
1867
+ */
1868
+ /**
1869
+ * The token `BalanceRow` wire shape — caller's credit row.
1870
+ *
1871
+ * `available` and `reserved` are `u128` on the server; the wire
1872
+ * format is a JSON number. Callers should not assume bigint until
1873
+ * the SDK migrates to a streaming parser (tracked separately).
1874
+ *
1875
+ * ⚠️ Amounts are in **base units** (`1 token = `
1876
+ * {@link BASE_UNITS_PER_TOKEN}), not whole tokens. Use
1877
+ * {@link formatTokens} to display them.
1878
+ */
1879
+ interface BalanceRow {
1880
+ /** Spendable balance, in base units (see {@link formatTokens}). */
1881
+ available: number;
1882
+ /** Reserved balance, in base units. */
1883
+ reserved: number;
1884
+ last_settled_seq_no: number;
1885
+ version: number;
1886
+ credit_exhausted: boolean;
1887
+ }
1888
+ /**
1889
+ * The token-tx-kind wire alphabet (snake_case). Every
1890
+ * value listed here is accepted by the server-side
1891
+ * `token.get-usage` `kinds` filter.
1892
+ */
1893
+ type TokenTxKind = "mint" | "burn" | "charge" | "transfer" | "bridge_mint_attest" | "bridge_burn_attest";
1894
+ /**
1895
+ * Per-caller view direction. `"in"` = caller's balance went up;
1896
+ * `"out"` = caller's balance went down. Derived host-side from
1897
+ * `(caller_did, tx.src, tx.dst)`; the same `seq_no` appears in both
1898
+ * parties' usage feeds with opposite directions on a transfer.
1899
+ */
1900
+ type Direction = "in" | "out";
1901
+ /**
1902
+ * Discriminated union mirroring the charge-reason wire union.
1903
+ * Present only when the row's `kind === "charge"`.
1904
+ */
1905
+ type ChargeReason = {
1906
+ kind: "contract_register";
1907
+ script_name: string;
1908
+ version: string;
1909
+ } | {
1910
+ kind: "invocation";
1911
+ script_name: string;
1912
+ function: string;
1913
+ fuel_consumed: number;
1914
+ fuel_tokens: number;
1915
+ host_call_count: number;
1916
+ host_call_tokens: number;
1917
+ } | {
1918
+ kind: "kv_bytes";
1919
+ map: string;
1920
+ } | {
1921
+ kind: "cas_bytes";
1922
+ backend: string;
1923
+ } | {
1924
+ kind: "outbox_egress";
1925
+ upstream: string;
1926
+ };
1927
+ /**
1928
+ * One row in the caller's usage feed — a per-caller projection of
1929
+ * the underlying `TokenTx`. `counterparty` is the other party from
1930
+ * the caller's perspective: `tx.dst` on outbound entries, `tx.src`
1931
+ * on inbound. `null` when the underlying tx has no counterparty
1932
+ * (mints have no `src`; burns and charges have no `dst`).
1933
+ */
1934
+ interface UsageEntry {
1935
+ seq_no: number;
1936
+ kind: TokenTxKind;
1937
+ /** Amount moved, in base units (`1 token = `{@link BASE_UNITS_PER_TOKEN}); see {@link formatTokens}. */
1938
+ amount: number;
1939
+ timestamp_ms: number;
1940
+ direction: Direction;
1941
+ counterparty?: string | null;
1942
+ reason?: ChargeReason | null;
1943
+ note?: string | null;
1944
+ }
1945
+ /**
1946
+ * Response shape of `token.get-usage` — caller's balance plus a
1947
+ * paginated slice of their most-recent `token:tx_log` entries.
1948
+ *
1949
+ * `next_cursor` is the inclusive upper-bound `seq_no` to pass back
1950
+ * as `after_seq` to fetch the next page. `null` (or absent) means
1951
+ * the caller's history is fully drained.
1952
+ */
1953
+ interface UsagePage {
1954
+ balance: BalanceRow;
1955
+ entries: UsageEntry[];
1956
+ next_cursor?: number | null;
1957
+ }
1958
+ /**
1959
+ * Request shape — all fields optional. `limit` clamps to
1960
+ * `1..=200` server-side; out-of-range values snap silently to the
1961
+ * bounds. `kinds: []` is treated as "no filter".
1962
+ */
1963
+ interface GetUsageOptions {
1964
+ limit?: number;
1965
+ after_seq?: number;
1966
+ kinds?: TokenTxKind[];
1967
+ }
1968
+
1969
+ /**
1970
+ * Tenant audit-event wire shapes.
1971
+ *
1972
+ * Mirrors `tenant_types::AuditEvent` and the `audit.get-mine` response
1973
+ * (`service::tenant_logs::{AuditBatch, AuditPage}`). A tenant contract
1974
+ * emits an audit event via the `logging::audit` host call; the host
1975
+ * stamps the identity fields (`subject` / `actor` / `vc_id`) from the
1976
+ * verified dispatch context, so a contract can never forge who acted or
1977
+ * on whom. Events are permanent (encrypted, append-only) and scoped to a
1978
+ * user — distinct from the evicting debug ring read via `getContractLogs`.
1979
+ */
1980
+ /**
1981
+ * One host-stamped audit event. `subject` / `actor` are canonical DID
1982
+ * strings. On a self-call `actor === subject` and `vc_id` is `null`; on a
1983
+ * delegated call `actor` is the agent and `vc_id` is the delegation
1984
+ * credential. The remaining fields are supplied verbatim by the contract.
1985
+ */
1986
+ interface AuditEvent {
1987
+ /** Cluster-deterministic flush timestamp (ms). */
1988
+ ts_ms: number;
1989
+ /** The user whose data the call touched (host-stamped `pii_did`). */
1990
+ subject: string;
1991
+ /** The agent (delegated) or user (self-call) who acted (host-stamped). */
1992
+ actor: string;
1993
+ /** Delegation credential id on a delegated call; `null` on a self-call. */
1994
+ vc_id?: string | null;
1995
+ /** Contract-supplied: what happened, e.g. `"kyc.approve"`. */
1996
+ action: string;
1997
+ /** Contract-supplied: what it acted on, e.g. `"user-profile"`. */
1998
+ target: string;
1999
+ /** Contract-supplied: the result, e.g. `"success"` / `"denied"`. */
2000
+ outcome: string;
2001
+ /** Contract-supplied: optional free-text / JSON detail. */
2002
+ details?: string | null;
2003
+ }
2004
+ /**
2005
+ * One archived batch — the events committed in a single tenant dispatch.
2006
+ * Every event in a batch shares the same `subject` / `actor` / `vc_id`.
2007
+ */
2008
+ interface AuditBatch {
2009
+ /** Hex of the archive key — usable directly as `cursor` for the next page. */
2010
+ key: string;
2011
+ /**
2012
+ * Host-stamped: did the emitting dispatch's contract transaction
2013
+ * commit? `false` means the call rolled back or trapped, so an event's
2014
+ * `outcome: "success"` in this batch is the contract's *claim*, not a
2015
+ * committed fact — filter on this when you need only durable events.
2016
+ */
2017
+ committed: boolean;
2018
+ events: AuditEvent[];
2019
+ }
2020
+ /**
2021
+ * `audit.get-mine` response — a page of audit batches, newest scan order.
2022
+ * `next_cursor` is present (a key hex) when more batches remain; `null`
2023
+ * once the scan reaches the end.
2024
+ */
2025
+ interface AuditPage {
2026
+ batches: AuditBatch[];
2027
+ next_cursor?: string | null;
2028
+ }
2029
+ /**
2030
+ * Request shape for {@link T3nClient.getAuditEvents} — all fields
2031
+ * optional. Omit `pii_did` to read your own trail (all actors); set it to
2032
+ * another user's DID to read, as a delegated agent, the events you
2033
+ * performed for them — admitted only while that user's delegation grant
2034
+ * to you is live. `cursor` is the `next_cursor` from a prior page.
2035
+ */
2036
+ interface GetAuditEventsOptions {
2037
+ pii_did?: string;
2038
+ limit?: number;
2039
+ cursor?: string;
2040
+ }
2041
+
2042
+ /**
2043
+ * Agent-activity audit-log wire shapes (the node's `auditlog` RPC).
2044
+ *
2045
+ * Mirrors `service::activity_audit::{ActivityReport, ReportEntry}` and
2046
+ * `primitives::audit_log::AuditLogEntry`. One entry per audited contract
2047
+ * dispatch — who called, for whom, which contract + function, and how it
2048
+ * ended. Entries are reconstructed from the append-only ledger on read, so
2049
+ * `seq_no` (the ledger index) and `hash` are derived server-side rather than
2050
+ * stored with the record.
2051
+ *
2052
+ * Scope is the caller's **own organisation**, resolved node-side from the
2053
+ * session DID: there is no scope parameter, and a page carries **every
2054
+ * member's** activity in that org, not just the caller's own. Metadata only —
2055
+ * DIDs, never display names, call arguments, or payloads.
2056
+ */
2057
+ /**
2058
+ * Whether the actor is a registered agent or a human / self principal.
2059
+ * Decided node-side by an existence check on the actor DID in the agent
2060
+ * registry — never inferred from the DID's shape.
2061
+ */
2062
+ type ActivityCallerType = "agent" | "human";
2063
+ /**
2064
+ * Host-stamped outcome of an audited dispatch.
2065
+ *
2066
+ * - `success` — the business transaction committed.
2067
+ * - `denied` — authorisation refused the call.
2068
+ * - `error` — the call was allowed but failed / rolled back.
2069
+ */
2070
+ type ActivityOutcome = "success" | "denied" | "error";
2071
+ /** One audited call. */
2072
+ interface ActivityEntry {
2073
+ /**
2074
+ * Ledger index of the entry — its unique, ordered id. Use it as the row key
2075
+ * and as the ordering key: it is monotonic, whereas {@link timestamp_ms} is
2076
+ * per-node wall clock.
2077
+ */
2078
+ seq_no: number;
2079
+ /** Hex SHA-256 of the stored entry (64 chars) — read-time tamper evidence. */
2080
+ hash: string;
2081
+ /**
2082
+ * Call time in Unix ms, stamped on the node that took the request. NOT a
2083
+ * cluster-assigned time, so entries from different nodes can be skewed by
2084
+ * their clock offset — order by {@link seq_no}, not by this.
2085
+ */
2086
+ timestamp_ms: number;
2087
+ /** Agent vs human, from the agent-registry check on {@link actor}. */
2088
+ caller_type: ActivityCallerType;
2089
+ /** DID that actually invoked the contract. */
2090
+ actor: string;
2091
+ /**
2092
+ * DID of the owner the caller acted for. Equals {@link actor} on a self /
2093
+ * own-authority call — never null.
2094
+ */
2095
+ on_behalf_of: string;
2096
+ /**
2097
+ * Organisation the acting principal belongs to — the report's scope key, so
2098
+ * it is identical on every row of a page. Falls back to `on_behalf_of` when
2099
+ * that principal is in no organisation.
2100
+ */
2101
+ org: string;
2102
+ /** Contract that ran, e.g. `tee:user/contracts`. */
2103
+ contract: string;
2104
+ /** Contract function invoked, e.g. `user-upsert`. */
2105
+ function: string;
2106
+ /** success / denied / error — host-stamped from the dispatch result. */
2107
+ outcome: ActivityOutcome;
2108
+ /**
2109
+ * Role ids the acting authority carried at call time: the actor's role in
2110
+ * the organisation on a self-call, the roles the owner granted the agent on
2111
+ * a delegated call. Omitted when the authority carried no role (direct
2112
+ * grants, an individual, or an entry recorded before roles were captured).
2113
+ * On a `denied` entry this is the caller's *claimed* authority, not a
2114
+ * validated one.
2115
+ */
2116
+ roles?: string[];
2117
+ }
2118
+ /**
2119
+ * One page of the organisation's activity report — **newest first**, i.e.
2120
+ * descending `seq_no`.
2121
+ */
2122
+ interface ActivityReport {
2123
+ entries: ActivityEntry[];
2124
+ /**
2125
+ * Cursor to resume from — pass it back as
2126
+ * {@link GetActivityLogOptions.before_seq}. `null` once the requested window
2127
+ * is exhausted.
2128
+ *
2129
+ * A live cursor with **fewer rows than `limit`, or none at all**, is normal:
2130
+ * the node also caps how much ledger one call decrypts, and that cap can trip
2131
+ * before the window ends. Page until this is `null`, never on a short or
2132
+ * empty page.
2133
+ */
2134
+ next_seq: number | null;
2135
+ }
2136
+ /** Params for one activity-report page. All optional; `{}` is valid. */
2137
+ interface GetActivityLogOptions {
2138
+ /** Window start, Unix ms, inclusive. Defaults to 0 (no lower bound). */
2139
+ from_ms?: number;
2140
+ /** Window end, Unix ms, inclusive. Defaults to unbounded. */
2141
+ to_ms?: number;
2142
+ /**
2143
+ * Cursor, inclusive — the highest `seq_no` this page may return. Omitted ⇒
2144
+ * start at the newest entry in the window. Pages walk downwards, so this is
2145
+ * the previous page's {@link ActivityReport.next_seq}.
2146
+ */
2147
+ before_seq?: number;
2148
+ /**
2149
+ * Rows returned this page. Clamped server-side to 1–1000 (default 200).
2150
+ *
2151
+ * A page can still be shorter than this (or empty) with a live `next_seq` —
2152
+ * the node's own scan cap can trip first. See {@link ActivityReport.next_seq}.
2153
+ */
2154
+ limit?: number;
2155
+ }
2156
+
2157
+ /**
2158
+ * Contract-discovery wire shapes.
2159
+ *
2160
+ * Field-for-field mirrors of the node's `contracts.list` and `delegation.check`
2161
+ * JSON-RPC responses (`service::contract_discovery::{ListedContract,
2162
+ * ListContractsResponse}` and `service::grant_check::{GrantRef,
2163
+ * GrantCheckResponse}`). Both methods are session-authenticated plaintext reads
2164
+ * dispatched over `/api/rpc` — the same posture as `token.get-usage` — so the
2165
+ * SDK wrappers return the parsed `result` object directly.
2166
+ */
2167
+ /** The navigable starting points of the discovery funnel. */
2168
+ type ListContractsScope = "core" | "org" | "self";
2169
+ /** Params for `contracts.list` (every field optional; `{}` lists core). */
2170
+ interface ListContractsParams {
2171
+ /** `"core"` (default) | `"org"` | `"self"`. */
2172
+ scope?: ListContractsScope;
2173
+ /** Target org DID (required for scope `"org"`). */
2174
+ org_did?: string;
2175
+ /** The member the agent acts for (required for scope `"org"` / `"self"`). */
2176
+ pii_did?: string;
2177
+ /** Page offset (defaults to 0 server-side). */
2178
+ offset?: number;
2179
+ /** Page size (defaults + clamped server-side). */
2180
+ limit?: number;
2181
+ }
2182
+ /** Contract kind — `"core"` platform system contract, `"tenant"` z-space. */
2183
+ type ContractKind = "core" | "tenant";
2184
+ /** One contract as presented by `contracts.list`. */
2185
+ interface ListedContract {
2186
+ /** Canonical name: `tee:<name>` for core, `z:<tid>:<tail>` for tenant. */
2187
+ name: string;
2188
+ kind: ContractKind;
2189
+ /** Current registered version; `null` when the contract is not registered. */
2190
+ version: string | null;
2191
+ /** Descriptor summary, or empty when no descriptor is published. */
2192
+ summary: string;
2193
+ /** Descriptor tags, or empty. */
2194
+ tags: string[];
2195
+ /** Owning DID: the org DID (org mode) or the member's own DID (self mode). */
2196
+ owner_org_did?: string;
2197
+ /**
2198
+ * Human-facing short name: the trailing segment of `name` (`payroll` from
2199
+ * `z:<tid>:payroll`, `user` from `tee:user`). Present this to people instead
2200
+ * of the full canonical `name`, which remains the dispatch key.
2201
+ */
2202
+ short_name: string;
2203
+ }
2204
+ /** Response body for `contracts.list`. */
2205
+ interface ListContractsResult {
2206
+ scope: string;
2207
+ contracts: ListedContract[];
2208
+ next_offset: number | null;
2209
+ }
2210
+ /** Which standing grant a satisfied/missing entry refers to. */
2211
+ type DelegationGrantKind = "member_delegation" | "org_delegation";
2212
+ /** Params for `delegation.check` (the generic capability read). */
2213
+ interface GrantCheckParams {
2214
+ /** The target contract whose requirements are checked. */
2215
+ contract: string;
2216
+ /** The member the agent wants to act for (the subject). */
2217
+ pii_did: string;
2218
+ /** Functions the intended action needs. */
2219
+ functions: string[];
2220
+ /** Org-data scopes the intended action needs. */
2221
+ scopes: string[];
2222
+ }
2223
+ /** One grant requirement — satisfied or missing. */
2224
+ interface DelegationGrantRef {
2225
+ grant: DelegationGrantKind;
2226
+ /** The target contract's canonical name. */
2227
+ contract: string;
2228
+ functions: string[];
2229
+ scopes: string[];
2230
+ }
2231
+ /**
2232
+ * Response for `delegation.check`: the `member_delegation ∩ org_delegation` verdict.
2233
+ *
2234
+ * `disclosed` is `true` only when the agent is registered under `pii_did`, so
2235
+ * org-side status was safe to disclose; `false` yields the uniform,
2236
+ * non-disclosive verdict (`authorised:false, satisfied:[], missing:[]`) that is
2237
+ * byte-invariant to the requested capability (R5 anti-enumeration).
2238
+ */
2239
+ interface GrantCheckResult {
2240
+ authorised: boolean;
2241
+ disclosed: boolean;
2242
+ satisfied: DelegationGrantRef[];
2243
+ missing: DelegationGrantRef[];
2244
+ }
2245
+ /** Response for the `whoami` operation: who the key resolves to, and where. */
2246
+ interface WhoamiResult {
2247
+ /** The DID the relayed api key resolves to. */
2248
+ did: string;
2249
+ /**
2250
+ * The org DIDs the agent itself belongs to (its own agent-keyed membership),
2251
+ * or `[]` when it belongs to none. Each is a valid `org_did` for
2252
+ * `contracts.list` scope `"org"`, so this is the seed for browsing the agent's
2253
+ * own orgs.
2254
+ */
2255
+ organisations: string[];
2256
+ /**
2257
+ * The agent's owning / managing DID — usually the org that created it. `null`
2258
+ * for a missing record (agents created without a hosted card or agent URI have
2259
+ * no registry record), a record with no owner link, or a malformed record
2260
+ * (decode failure is logged at `WARN`, never a silent authority downgrade); a
2261
+ * snapshot read failure is surfaced as an error, not reported as `null`. The
2262
+ * owner link is mutable and may have changed since creation, so treat this as
2263
+ * best-effort, not an authority.
2264
+ */
2265
+ owner: string | null;
2266
+ }
2267
+ /** Params for the `describe.contract` operation. */
2268
+ interface DescribeContractParams {
2269
+ /**
2270
+ * Registry name: `tee:<name>/contracts` (core) or `z:<tid>:<tail>` (tenant).
2271
+ * The bare core form `contracts.list` presents (`tee:<name>` / `y:<name>`) is
2272
+ * also accepted — the node maps it onto the `/contracts` registry key — so a
2273
+ * `ListedContract.name` feeds straight in.
2274
+ */
2275
+ contract: string;
2276
+ /** Explicit version; omitted resolves the current registered version. */
2277
+ version?: string;
2278
+ }
2279
+ /** Params for the `describe.function` operation. */
2280
+ interface DescribeFunctionParams {
2281
+ /**
2282
+ * Registry name: `tee:<name>/contracts` (core) or `z:<tid>:<tail>` (tenant).
2283
+ * The bare core form `contracts.list` presents (`tee:<name>` / `y:<name>`) is
2284
+ * also accepted — the node maps it onto the `/contracts` registry key.
2285
+ */
2286
+ contract: string;
2287
+ /** The single function to project from the contract's descriptor. */
2288
+ function: string;
2289
+ /** Explicit version; omitted resolves the current registered version. */
2290
+ version?: string;
2291
+ }
2292
+ /**
2293
+ * One function's descriptor entry — the `describe.function` result and the
2294
+ * element type of a {@link ContractDescriptorDocument}'s `functions` array.
2295
+ *
2296
+ * Left open-ended: the descriptor document's full schema (argument schema,
2297
+ * wire projection, auth requirements) is owned by the contract descriptor
2298
+ * registry and served verbatim by the node. The named fields are the ones the
2299
+ * node's descriptor path always presents.
2300
+ */
2301
+ interface FunctionDescriptorEntry {
2302
+ /** Contract function name (e.g. `compute-payroll`). */
2303
+ name: string;
2304
+ summary?: string;
2305
+ /** Whether the function mutates state. */
2306
+ mutates?: boolean;
2307
+ [key: string]: unknown;
2308
+ }
2309
+ /**
2310
+ * The node's descriptor document for a contract — the `descriptor` field of a
2311
+ * {@link DescribeContractResult}. Open-ended for the same reason as
2312
+ * {@link FunctionDescriptorEntry}: the node returns the registry's descriptor
2313
+ * document verbatim.
2314
+ */
2315
+ interface ContractDescriptorDocument {
2316
+ name?: string;
2317
+ version?: string;
2318
+ summary?: string;
2319
+ tags?: string[];
2320
+ functions?: FunctionDescriptorEntry[];
2321
+ [key: string]: unknown;
2322
+ }
2323
+ /**
2324
+ * Result of the `describe.contract` operation. The node wraps the descriptor
2325
+ * document with the resolved dispatch `version`, so an authorised describe hands
2326
+ * back the exact `scriptVersion` an {@link invoke} call needs alongside the
2327
+ * schema. Returned only on the authorised path; a gate miss or unknown contract
2328
+ * yields the uniform non-disclosive error, never this wrapper.
2329
+ */
2330
+ interface DescribeContractResult {
2331
+ /** The canonical registry name, echoed from the request. */
2332
+ contract: string;
2333
+ /** The resolved dispatch version — pass as `scriptVersion` to `invoke`. */
2334
+ version: string;
2335
+ /** The contract's full descriptor document. */
2336
+ descriptor: ContractDescriptorDocument;
2337
+ }
2338
+ /**
2339
+ * Result of the `describe.function` operation: the resolved dispatch `version`
2340
+ * paired with the single projected function entry. Same authorised-path-only
2341
+ * guarantee as {@link DescribeContractResult}.
2342
+ */
2343
+ interface DescribeFunctionResult {
2344
+ /** The canonical registry name, echoed from the request. */
2345
+ contract: string;
2346
+ /** The resolved dispatch version — pass as `scriptVersion` to `invoke`. */
2347
+ version: string;
2348
+ /** The single projected function's descriptor entry. */
2349
+ descriptor: FunctionDescriptorEntry;
2350
+ }
2351
+
2352
+ /**
2353
+ * T3n Client - Main SDK class
2354
+ *
2355
+ * Provides a simple interface for establishing secure sessions with T3n nodes.
2356
+ * All cryptographic complexity is handled in WASM components.
2357
+ */
2358
+
2359
+ /**
2360
+ * Main T3n SDK Client
2361
+ */
2362
+ declare class T3nClient {
2363
+ private readonly config;
2364
+ private readonly transport;
2365
+ /**
2366
+ * Resolved node base URL. Snapshotted in the constructor so the
2367
+ * typed contract wrappers (`kycStatus`, `getSelfEthAddress`, …)
2368
+ * can call `getContractVersion()` against the same host the
2369
+ * transport talks to. Used only by the `contract_version: "latest"`
2370
+ * resolution path in {@link executeUserContract}.
2371
+ */
2372
+ private readonly effectiveBaseUrl;
2373
+ /**
2374
+ * Server-minted session ID, set by {@link handshake} from the
2375
+ * `Session-Id` response header. `null`
2376
+ * until the handshake completes. Client code cannot set it — a
2377
+ * client-supplied session id is rejected, closing the
2378
+ * session-fixation vector.
2379
+ */
2380
+ private sessionId;
2381
+ /**
2382
+ * Set by {@link sendRpcRequest} when an `auth.handshake` RPC is
2383
+ * actually issued. Decouples the "flow completed without talking
2384
+ * to a server" case (unit-test mocks that only exercise handler
2385
+ * delegation) from the real "server must mint the id" invariant:
2386
+ * we only enforce the mint requirement when a round-trip happened.
2387
+ */
2388
+ private handshakeSentRpc;
2389
+ private readonly logger;
2390
+ private readonly encryption;
2391
+ private status;
2392
+ /**
2393
+ * In-flight WASM state-machine bytes. Holds the opaque state
2394
+ * returned by `flow[method].next()` between iterations of
2395
+ * `runFlow`. Always cleared at the top of `runFlow` and again
2396
+ * once `tryFinalize` has extracted the terminal payload — so
2397
+ * outside of an active loop these slots are always `null`.
2398
+ */
2399
+ private wasmState;
2400
+ /**
2401
+ * Terminal payloads produced by `flow[method].finish()`:
2402
+ * - `handshake` → serialized session blob, used by
2403
+ * `getSessionState()` for subsequent `session.encrypt` calls.
2404
+ * - `auth` → serialized DID; the public `authenticate()` decodes
2405
+ * it into `this.did` and the slot is otherwise unused.
2406
+ * - `execute` → unused (executes return immediately to the caller).
2407
+ *
2408
+ * Stored in a dedicated field instead of reusing `wasmState`
2409
+ * because the two meanings — "in-flight state machine" vs
2410
+ * "finalized payload" — are semantically different and merging
2411
+ * them re-introduces the bug-class this guard exists to prevent.
2412
+ */
2413
+ private finalizedPayload;
2414
+ private did;
2415
+ private handshakeResult;
2416
+ constructor(config: T3nClientConfig);
2417
+ /**
2418
+ * Start the handshake process with the T3n node
2419
+ */
2420
+ handshake(): Promise<HandshakeResult>;
2421
+ /**
2422
+ * Authenticate with the T3n node.
2423
+ *
2424
+ * For OIDC, this runs a two-step nonce-bound flow:
2425
+ * 1. Sends `InitOidcAuth` to server → receives session-binding nonce.
2426
+ * 2. Calls `getIdToken(nonce)` callback so the app can include the
2427
+ * nonce in the Google authorization URL.
2428
+ * 3. Sends `SubmitIdToken` with the nonce-bearing token → receives DID.
2429
+ */
2430
+ authenticate(authInput: AuthInput): Promise<Did>;
2431
+ /**
2432
+ * Add an Ethereum wallet as an additional authenticator on the
2433
+ * already-authenticated account.
2434
+ *
2435
+ * Proves control of the wallet via SIWE and links it to the session's
2436
+ * EXISTING DID (resolved server-side from the session) — it does NOT
2437
+ * mint a new DID and does NOT change the session: `this.did` and
2438
+ * `this.status` are left untouched, and no new cookie is issued.
2439
+ *
2440
+ * Requires a completed {@link authenticate} first (e.g. an OIDC
2441
+ * login). Only Ethereum is supported — OIDC/email identities are
2442
+ * established at login, not added afterwards.
2443
+ *
2444
+ * Reuses the same client-side eth state machine as login, but posts
2445
+ * to the authenticated `auth.add-authenticator` route. If the wallet
2446
+ * is already linked to a different account, the server rejects with a
2447
+ * typed `eth_auth_map_conflict` error (resolve via account merge).
2448
+ *
2449
+ * @returns the existing DID the wallet was linked to.
2450
+ */
2451
+ addAuthMethod(authInput: EthAuthInput): Promise<Did>;
2452
+ /**
2453
+ * OIDC two-step authentication with session-binding nonce.
2454
+ *
2455
+ * Bypasses the WASM client state machine and makes two encrypted
2456
+ * RPC calls directly:
2457
+ * 1. `InitOidcAuth { provider }` → server generates nonce → returns
2458
+ * `ProvideNonce { nonce }`.
2459
+ * 2. App calls `getIdToken(nonce)` to obtain a nonce-bound `id_token`.
2460
+ * 3. `SubmitIdToken { id_token }` → server verifies token + nonce →
2461
+ * returns `Finish { did }`.
2462
+ */
2463
+ private authenticateOidc;
2464
+ /**
2465
+ * Parse a `Finish { did }` reply shared by the manual (non-WASM) auth flows
2466
+ * that bypass the client state machine (interactive OIDC, keyless workload).
2467
+ *
2468
+ * Validates the `oidc_auth_action` tag before reading `did`: a decodable but
2469
+ * non-`Finish` reply is reported as such rather than silently misread as a
2470
+ * missing DID (which would discard whatever the server actually said). Returns
2471
+ * the session {@link Did}.
2472
+ */
2473
+ private parseFinishDid;
2474
+ /**
2475
+ * Workload (keyless hosted-agent) single-call authentication.
2476
+ *
2477
+ * A hosted agent authenticates with its OWN OIDC workload identity —
2478
+ * a machine `id_token` whose `(iss, sub)` the caller has already
2479
+ * fetched — forwarded through this transport by value. Distinct from
2480
+ * the interactive {@link authenticateOidc} flow: there is NO
2481
+ * session-binding nonce and NO `InitOidcAuth` round-trip. We make a
2482
+ * SINGLE encrypted RPC call:
2483
+ *
2484
+ * 1. `SubmitWorkloadToken { provider, id_token }` → the node verifies
2485
+ * the token and mints/resolves the DID `oidc:<iss>:<sub>` →
2486
+ * returns `Finish { did }`.
2487
+ *
2488
+ * Bypasses the WASM client state machine (mirrors `authenticateOidc` /
2489
+ * `authenticateEmailOtp`); the `SubmitWorkloadToken` action tag is
2490
+ * matched server-side.
2491
+ */
2492
+ private authenticateWorkload;
2493
+ /**
2494
+ * Email-OTP two-step authentication.
2495
+ *
2496
+ * Symmetric with {@link authenticateOidc}: bypasses the WASM client
2497
+ * state machine and makes two encrypted RPC calls directly:
2498
+ * 1. `InitEmailOtp { email }` → node sends a one-time code → returns
2499
+ * an `OtpSent` ack.
2500
+ * 2. App calls `getOtpCode()` to obtain the code the user received.
2501
+ * 3. `SubmitOtpCode { code }` → node verifies the code, resolves the
2502
+ * DID on the shared `email:<addr>` key → returns `Finish { did }`.
2503
+ *
2504
+ * Because the DID is keyed on the (server-lowercased) email, a user
2505
+ * who previously signed in with the same address via Google (OIDC)
2506
+ * authenticates to the SAME DID — one identity, no double account.
2507
+ */
2508
+ private authenticateEmailOtp;
2509
+ /**
2118
2510
  * Execute an action on the T3n node.
2119
2511
  *
2120
2512
  * Returns the JSON-stringified contract response. Most callers should
@@ -2173,7 +2565,7 @@ declare class T3nClient {
2173
2565
  * Generic capability check (`delegation.check`) — the
2174
2566
  * node-backed source for the MCP `checkDelegation` funnel tool.
2175
2567
  *
2176
- * Returns the `agent_auth ∩ UserGrant` verdict for `(agent, contract,
2568
+ * Returns the `member_delegation ∩ org_delegation` verdict for `(agent, contract,
2177
2569
  * pii_did)`: whether the acting agent (resolved from the session) holds the
2178
2570
  * standing grants that `contract`'s `functions` / `scopes` need for member
2179
2571
  * `pii_did`. The org half is vacuous for no-org (Individual-owned) targets,
@@ -2190,7 +2582,7 @@ declare class T3nClient {
2190
2582
  * the caller's own audit trail (every actor). With a `pii_did` set to
2191
2583
  * another user's DID, returns — as a delegated agent — the events the
2192
2584
  * caller performed for that user; admitted ONLY while that user's
2193
- * `agent-auth` grant to the caller is live (revocable). `cursor` is the
2585
+ * `delegation` grant to the caller is live (revocable). `cursor` is the
2194
2586
  * `next_cursor` from a prior page; `limit` clamps server-side.
2195
2587
  *
2196
2588
  * Unlike {@link getUsage}, this runs the SAME session-payload
@@ -2267,7 +2659,7 @@ declare class T3nClient {
2267
2659
  * credits.
2268
2660
  *
2269
2661
  * The returned DID is the org identifier the org-data and payroll
2270
- * surfaces expect (e.g. `OrgDataClient.setGrants({ orgDid, … })`).
2662
+ * surfaces expect (e.g. `OrgDataClient.setDelegation({ orgDid, … })`).
2271
2663
  *
2272
2664
  * @param name - human-readable organisation name (1..=128 bytes)
2273
2665
  * @returns the new organisation's DID (`did:t3n:<40-hex>`)
@@ -2411,14 +2803,14 @@ declare class T3nClient {
2411
2803
  * 1. `user-remove-organisation-attribution` — drop the membership edge
2412
2804
  * (org-admin gated; idempotent on an already-absent membership). The host
2413
2805
  * membership gate makes the detach effective immediately.
2414
- * 2. `org-remove-member-grants` — sweep the member from the org's
2415
- * per-contract `UserGrant` lists, so the capability does not silently
2806
+ * 2. `org-remove-member-delegation` — sweep the member from the org's
2807
+ * per-contract `BoundGrant` lists, so the capability does not silently
2416
2808
  * reactivate if the member later rejoins.
2417
2809
  *
2418
- * The member's `agent_auth` delegations are self-scoped (`AGENT_AUTH_MAP` is a
2419
- * per-user document an admin cannot reach), so this cannot sweep them; the host
2420
- * membership gate denies them regardless, and the member's own session can run
2421
- * {@link revokeAgentAuthForOrg} for full cleanup.
2810
+ * The member's delegations are self-scoped (the delegation edge in
2811
+ * `ROLE_ASSIGNMENTS_MAP` is a per-user document an admin cannot reach), so this
2812
+ * cannot sweep them; the host membership gate denies them regardless, and the
2813
+ * member's own session can run {@link revokeMemberDelegationForOrg} for full cleanup.
2422
2814
  *
2423
2815
  * @param orgDid - the organisation
2424
2816
  * @param userDid - the member to detach
@@ -2432,9 +2824,9 @@ declare class T3nClient {
2432
2824
  * target — the contract's self-leave branch (`caller == target`) admits it
2433
2825
  * without org-admin rights. The host membership gate makes the detach
2434
2826
  * effective immediately.
2435
- * 2. `org-remove-member-grants` — sweep the caller's own grants for the org
2827
+ * 2. `org-remove-member-delegation` — sweep the caller's own grants for the org
2436
2828
  * (the self-revocation branch, `caller == member`).
2437
- * 3. `agent-auth-revoke-org` — drop the caller's own org-scoped agent
2829
+ * 3. `member-delegation-revoke-org` — drop the caller's own org-scoped
2438
2830
  * delegations.
2439
2831
  *
2440
2832
  * Steps 2–3 leave no stale capability rows that would reactivate on a rejoin.
@@ -2443,40 +2835,42 @@ declare class T3nClient {
2443
2835
  */
2444
2836
  leaveOrganisation(orgDid: string): Promise<void>;
2445
2837
  /**
2446
- * Revoke the caller's own agent delegations scoped to one org
2447
- * (detach-cascade `agent_auth` half). Dispatches
2448
- * `agent-auth-revoke-org` on `tee:user/contracts` (**SelfOnly**): every
2449
- * `ScriptGrant` targeting a `z:<orgTid>:*` contract is removed from the
2450
- * caller's own agent-auth document.
2838
+ * Revoke the caller's own delegations scoped to one org (detach-cascade
2839
+ * `delegation` half). Dispatches `member-delegation-revoke-org` on
2840
+ * `tee:user/contracts` (**SelfOnly**): every delegation-edge grant targeting a
2841
+ * `z:<orgTid>:*` contract is removed from the caller's own delegation
2842
+ * document.
2451
2843
  *
2452
2844
  * @param orgTid - the org's z-space tenant id (`did:t3n:<hex>` or bare
2453
2845
  * 40-hex) — i.e. the `<tid>` in the org's `z:<tid>:…` contract names
2454
2846
  */
2455
- revokeAgentAuthForOrg(orgTid: string): Promise<void>;
2847
+ revokeMemberDelegationForOrg(orgTid: string): Promise<void>;
2456
2848
  /**
2457
- * Read the authenticated user's own agent-auth policy — the standing
2458
- * grants delegated to agents. Dispatches `agent-auth-get` on
2849
+ * Read the authenticated user's own delegation policy — the standing
2850
+ * grants delegated to agents. Dispatches `member-delegation-get` on
2459
2851
  * `tee:authorisations/contracts` (the policy's owning contract), which is
2460
2852
  * **SelfOnly**, so this always returns the caller's own
2461
- * `AGENT_AUTH_MAP[self]` document.
2853
+ * delegation edge in `ROLE_ASSIGNMENTS_MAP`.
2462
2854
  *
2463
- * @returns the full policy document (normalised to the camelCase write
2464
- * shape): the per-agent `agents` entries plus the document-level
2465
- * `discoverDids` discovery grants
2855
+ * @returns the full policy document as the flat snake_case wire shape: the
2856
+ * `grants` list (each row's `grantee` is the authorised delegatee DID) plus
2857
+ * the document-level `discover_dids` discovery grants
2466
2858
  * @throws if the session is not authenticated, or the contract refuses
2467
2859
  */
2468
- getAgentAuth(): Promise<AgentAuthPolicy>;
2860
+ getMemberDelegation(): Promise<MemberDelegationDoc>;
2469
2861
  /**
2470
- * Authorise an agent for one contract on the caller's own behalf
2862
+ * Authorise a delegatee for one contract on the caller's own behalf
2471
2863
  * (envelope-free authorisation). Read-merge-writes the
2472
- * caller's `AGENT_AUTH_MAP[self]` document via `agent-auth-update`
2473
- * (**SelfOnly**) with script-level union semantics, so other contracts'
2474
- * grants for this or any agent survive untouched.
2864
+ * caller's delegation edge in `ROLE_ASSIGNMENTS_MAP` via `member-delegation-update`
2865
+ * (**SelfOnly**) with `(grantee, contract_id)` union semantics, so other
2866
+ * contracts' grants for this or any delegatee survive untouched.
2475
2867
  *
2476
- * Carries the new `scopes` + validity fields: the delegated
2477
- * org-data scopes and an optional `[validFromSecs, validUntilSecs]`
2478
- * window. The ≤ cap *length* check is enforced contract-side at write
2479
- * time; the expiry gate is host-side at read time.
2868
+ * The grant is the flat wire {@link BoundGrant}: its `grantee` is the delegatee
2869
+ * DID being authorised, and it carries `functions`, the delegated org-data
2870
+ * `scopes`, direct-read `read_scopes`, egress `allowed_hosts`, an optional
2871
+ * semver `version_req`, and an optional validity `window`. The ≤ cap *length*
2872
+ * check is enforced contract-side at write time; the expiry gate is host-side
2873
+ * at read time.
2480
2874
  *
2481
2875
  * This is the write surface `getDelegationInstructions` produces the
2482
2876
  * parameters for. The caller MUST be the delegating user, authenticated as
@@ -2488,38 +2882,38 @@ declare class T3nClient {
2488
2882
  * standing discovery), and any `options.discoverDids` are unioned in
2489
2883
  * (order-preserving, deduplicated).
2490
2884
  *
2491
- * @param agentDid - the agent DID being authorised
2492
- * @param grant - the single script grant to set (contract, functions,
2493
- * scopes, validity, egress hosts)
2885
+ * @param grant - the single grant to set — a {@link BoundGrant} whose
2886
+ * `grantee` is the delegatee DID being authorised (contract_id, functions,
2887
+ * scopes, window, egress hosts)
2494
2888
  * @param options - optional `discoverDids` to union into the document's
2495
2889
  * discovery grants (org DIDs for org-mode `listContracts`, the caller's
2496
2890
  * own DID for self mode)
2497
- * @returns the script rows preserved from the existing policy (audit aid)
2891
+ * @returns the grant rows preserved from the existing policy (audit aid)
2498
2892
  * @throws if the session is not authenticated, or the contract refuses
2499
2893
  */
2500
- updateAgentAuth(agentDid: string, grant: AgentAuthScriptGrant, options?: {
2894
+ updateMemberDelegation(grant: BoundGrant, options?: {
2501
2895
  discoverDids?: string[];
2502
2896
  }): Promise<{
2503
2897
  preservedRows: string[];
2504
2898
  }>;
2505
2899
  /**
2506
2900
  * Build the canonical `ExecuteActionRequest` shape the server
2507
- * expects (`script_name`, `script_version`, `function_name`, `input`,
2901
+ * expects (`contract_id`, `contract_version`, `function_name`, `input`,
2508
2902
  * optional `pii_did`) and dispatch it through {@link execute}.
2509
2903
  *
2510
2904
  * Two pieces of glue live here that every typed user-contract
2511
2905
  * wrapper would otherwise duplicate:
2512
2906
  *
2513
2907
  * 1. **Field naming.** The server deserialises strictly into
2514
- * `script_name` / `script_version` / `function_name` —
2908
+ * `contract_id` / `contract_version` / `function_name` —
2515
2909
  * sending `contract` / `version` / `function` produces
2516
2910
  * `Invalid action request: missing field …` 400s. Centralising
2517
2911
  * the names here means every wrapper agrees with the server.
2518
- * 2. **`"latest"` resolution.** `script_version` is `SemVer` on
2912
+ * 2. **`"latest"` resolution.** `contract_version` is `SemVer` on
2519
2913
  * the server, so a literal `"latest"` cannot be parsed. We
2520
2914
  * fetch the registered current version via
2521
2915
  * `GET /api/contracts/current?name=…` (cached per script name
2522
- * in `getScriptVersion`) and forward the resolved
2916
+ * in `getContractVersion`) and forward the resolved
2523
2917
  * `MAJOR.MINOR.PATCH` string.
2524
2918
  *
2525
2919
  * Wrappers that need PII delegation can extend this helper
@@ -2529,8 +2923,8 @@ declare class T3nClient {
2529
2923
  private executeUserContract;
2530
2924
  /**
2531
2925
  * Same glue as {@link executeUserContract}, parameterised over the
2532
- * target system contract — the agent-auth wrappers dispatch on
2533
- * `tee:authorisations/contracts` (the authorisation policy's owning
2926
+ * target system contract — the delegation wrappers dispatch on
2927
+ * `tee:authorisations/contracts` (the delegation policy's owning
2534
2928
  * contract) while the rest of the user-contract surface stays on
2535
2929
  * `tee:user/contracts`.
2536
2930
  */
@@ -2784,25 +3178,24 @@ declare class T3nClient {
2784
3178
  */
2785
3179
  submitUserInput(input: SubmitUserInputArgs): Promise<SubmitUserInputResult>;
2786
3180
  /**
2787
- * Replace this user's agent-authorisation policy (`tee:user/contracts` →
2788
- * `agent-auth-update`). The supplied document IS the new state: an empty
2789
- * `agents` array revokes all agent access, and an omitted `discoverDids`
3181
+ * Replace this user's delegation policy (`tee:authorisations/contracts`
3182
+ * → `member-delegation-update`). The supplied document IS the new state: an empty
3183
+ * `grants` array revokes all delegated access, and an empty `discover_dids`
2790
3184
  * persists an empty discovery-grant list. This is the full-document
2791
- * write — use {@link T3nClient.updateAgentAuth} for the single-grant
3185
+ * write — use {@link T3nClient.updateMemberDelegation} for the single-grant
2792
3186
  * read-merge-write that preserves other contracts' grants and the
2793
3187
  * standing discovery grants.
2794
3188
  *
2795
- * Typed wrapper over the raw contract call: callers pass camelCase input;
2796
- * the SDK emits the canonical snake_case wire via
2797
- * {@link toAgentAuthUpdateWire} (carrying `scopes` / `read_scopes` /
2798
- * validity alongside `functions` / `allowed_hosts`, plus the
2799
- * document-level `discover_dids`), so it does not rely on the contract's
2800
- * compatibility aliases.
3189
+ * The {@link MemberDelegationDoc} IS the snake_case wire shape — grant rows are
3190
+ * {@link BoundGrant} verbatim — so the document passes straight through with
3191
+ * no casing transform. Absent per-grant qualifiers (`version_req` /
3192
+ * `read_scopes` / `allowed_hosts` / `window`) are simply unset on the object
3193
+ * and so omitted from the JSON.
2801
3194
  *
2802
3195
  * @throws {RpcError} if the contract rejects the policy (validation failure,
2803
- * too many agents/grants).
3196
+ * too many delegatees/grants).
2804
3197
  */
2805
- agentAuthUpdate(input: AgentAuthUpdateInput): Promise<void>;
3198
+ memberDelegationUpdate(input: MemberDelegationDoc): Promise<void>;
2806
3199
  /**
2807
3200
  * Convenience helper: run the explicit OTP roundtrip and submit
2808
3201
  * the slim user-upsert in one call.
@@ -2865,851 +3258,449 @@ declare class T3nClient {
2865
3258
  * `opts.onUpdate` fires once per snapshot, including
2866
3259
  * intermediate `pending` ones. Errors thrown from the callback
2867
3260
  * are swallowed so a misbehaving UI handler can't strand the
2868
- * poll loop.
2869
- *
2870
- * @throws [[KycStatusTimeoutError]] when the cadence's
2871
- * `timeoutMs` elapses without a terminal status.
2872
- * @throws the abort reason when `opts.signal` is aborted.
2873
- * @throws the underlying RPC error when the contract or
2874
- * transport raises (e.g. session expiry mid-poll).
2875
- */
2876
- kycStatusPoll(opts?: KycPollOptions): Promise<KycStatus>;
2877
- /**
2878
- * The server-minted session ID once handshake has completed, or
2879
- * `null` beforehand.
2880
- */
2881
- getSessionId(): SessionId | null;
2882
- getStatus(): SessionStatus;
2883
- getDid(): Did | null;
2884
- getLastSetCookie(): string | null;
2885
- getLastResponseHeaders(): Record<string, string>;
2886
- isAuthenticated(): boolean;
2887
- /**
2888
- * Run a WASM state machine flow to completion.
2889
- *
2890
- * Clears both `wasmState[method]` and `finalizedPayload[method]`
2891
- * at entry so a flow that previously threw partway (e.g. an RPC
2892
- * error) starts from a clean slate on retry. Without the reset,
2893
- * stale state from the failed attempt leaks into the new flow
2894
- * and `tryFinalize` may either spuriously succeed or run `next()`
2895
- * against a state that no longer matches the action we're sending.
2896
- *
2897
- * The `tryFinalize`-then-`next` order is load-bearing: the loop's
2898
- * exit condition fires *after* the previous iteration's
2899
- * `handleWasmRequest` has flushed the outbound peer reply, so
2900
- * every state-machine emission reaches the wire before we extract
2901
- * the final payload.
2902
- */
2903
- private runFlow;
2904
- /**
2905
- * Try to finalize the current flow. Returns the finish() payload
2906
- * (a serialized Session for handshake, a serialized DID for auth)
2907
- * or `null` if the state machine has not reached its terminal phase
2908
- * yet.
2909
- *
2910
- * The "not yet finalized" case is the loop's signal to keep
2911
- * iterating, not a real error. Any *other* failure must propagate
2912
- * so callers see real WASM errors instead of silent retries that
2913
- * spin forever.
2914
- *
2915
- * The terminal payload is stored in `finalizedPayload[method]`
2916
- * (a separate field from `wasmState[method]`) so the in-flight
2917
- * state-machine bytes and the finalized session/DID bytes never
2918
- * occupy the same slot. `getSessionState()` reads from
2919
- * `finalizedPayload.handshake`.
2920
- */
2921
- private tryFinalize;
2922
- /**
2923
- * Handle a WASM request based on its type
2924
- */
2925
- private handleWasmRequest;
2926
- /**
2927
- * Handle a send-remote request by calling the RPC endpoint
2928
- */
2929
- private handleSendRemote;
2930
- private captureHandshakeResult;
2931
- /**
2932
- * Handle a guest-to-host request using configured handlers
2933
- */
2934
- private handleGuestToHost;
2935
- /**
2936
- * Send an RPC request with automatic encryption/decryption
2937
- */
2938
- private sendRpcRequest;
2939
- /**
2940
- * Send a session-authenticated JSON-RPC request with plaintext
2941
- * params/result (no SessionEncryption layer). Used for tenant-facing
2942
- * read endpoints whose payloads carry only public / non-disclosive
2943
- * metadata (`contracts.list`, `delegation.check`) where the
2944
- * server-side handler reads the JSON envelope directly. (The token
2945
- * self-reads moved to the sealed path — see {@link getUsage}.)
2946
- *
2947
- * Auto-attaches the `Session-Id` header; surfaces JSON-RPC errors
2948
- * the same way as {@link sendRpcRequest} (typed
2949
- * `InsufficientCreditError` when applicable, `RpcError` otherwise).
2950
- * Returns the parsed `result` field — typically a JSON object the
2951
- * caller will narrow to the endpoint's response type.
2952
- */
2953
- private sendUnencryptedSessionRpc;
2954
- /**
2955
- * Send a session-authenticated JSON-RPC request whose params/result
2956
- * are sealed with the same {@link SessionEncryption} layer
2957
- * `action.execute` uses — for read endpoints that return PII
2958
- * (`audit.get-mine`) and therefore must not travel plaintext over
2959
- * TLS. Unlike {@link sendRpcRequest}, this is not tied to the WASM
2960
- * client `Method` state machine: it takes the raw RPC method string
2961
- * and only does encrypt → send → decrypt.
2962
- *
2963
- * Requires an established (>= Encrypted) session; returns the
2964
- * decrypted plaintext response string for the caller to `JSON.parse`.
2965
- */
2966
- private sendEncryptedSessionRpc;
2967
- /**
2968
- * Inspect a JSON-RPC response for an `error` field and throw the
2969
- * appropriate typed exception. No-op when `response.error` is
2970
- * absent. Shared by every RPC path so wire-shape changes in the
2971
- * server's error envelope (typed-error subclasses, request-id
2972
- * placement, detail formatting) only need to land in one place.
2973
- *
2974
- * JSON-RPC `error.message` is the generic category string
2975
- * ("Invalid params", "Internal error", …). The node attaches the
2976
- * actionable text and per-request correlation id in `error.data`.
2977
- * Extract both so callers (and toasts that only render `.message`)
2978
- * get the real reason plus an id an operator can grep in the logs.
2979
- *
2980
- * Chargepoint denials surface as a typed
2981
- * `InsufficientCreditError` so frontends can branch on
2982
- * `instanceof` to render an "out of credit" UI without
2983
- * prefix-matching the message themselves. The wire format is stable.
2984
- */
2985
- private throwIfRpcError;
2986
- private sendMultipartRpcRequest;
2987
- /**
2988
- * Capture the server-minted `Session-Id` from the last handshake
2989
- * response headers. Validates shape so a
2990
- * broken or MITM'd response fails loudly instead of leaving a
2991
- * garbage value in the client. Idempotent: only the first valid
2992
- * mint per session is honoured — subsequent handshake RPC legs
2993
- * (none exist today, but the state-machine loop can iterate) do
2994
- * not overwrite an already-set value.
3261
+ * poll loop.
3262
+ *
3263
+ * @throws [[KycStatusTimeoutError]] when the cadence's
3264
+ * `timeoutMs` elapses without a terminal status.
3265
+ * @throws the abort reason when `opts.signal` is aborted.
3266
+ * @throws the underlying RPC error when the contract or
3267
+ * transport raises (e.g. session expiry mid-poll).
2995
3268
  */
2996
- private captureMintedSessionId;
3269
+ kycStatusPoll(opts?: KycPollOptions): Promise<KycStatus>;
2997
3270
  /**
2998
- * Get the finalized session blob (for `session.encrypt` calls).
2999
- * Populated by `tryFinalize` once the handshake state machine
3000
- * reaches its terminal phase.
3271
+ * The server-minted session ID once handshake has completed, or
3272
+ * `null` beforehand.
3001
3273
  */
3002
- private getSessionState;
3003
- }
3004
-
3005
- /**
3006
- * Guest-to-Host Request Handlers
3007
- *
3008
- * These handle requests from WASM that need the host environment to perform side effects.
3009
- * Examples: signing challenges, providing public keys, generating random bytes.
3010
- */
3011
-
3012
- /**
3013
- * Account — MetaMask handler accepts either a plain address string or an
3014
- * object with an `address` field (for compatibility with various wallet
3015
- * libraries).
3016
- */
3017
- type EthAccount = string | {
3018
- address: string;
3019
- };
3020
- /**
3021
- * Create an EthSign handler using MetaMask (window.ethereum)
3022
- * @param account - MetaMask account (string address or object with address property)
3023
- * @param logger - Optional logger instance. Defaults to a logger using the global log level (LogLevel.ERROR).
3024
- * Pass a custom logger to override logging behavior for this handler.
3025
- * @param privateKey - Optional private key for signing (if provided, MetaMask is not used)
3026
- */
3027
- declare function metamask_sign(account: EthAccount, logger?: Logger, privateKey?: string | undefined): GuestToHostHandler;
3028
- /**
3029
- * Get the current MetaMask address
3030
- * @returns Ethereum address (lowercase, 0x prefixed)
3031
- */
3032
- declare function metamask_get_address(): Promise<string>;
3033
- /**
3034
- * Get the address for a given private key
3035
- * @param privateKey - Ethereum private key (0x prefixed hex string)
3036
- * @returns Ethereum address (lowercase, 0x prefixed)
3037
- */
3038
- declare function eth_get_address(privateKey: string): string;
3039
- /**
3040
- * Create an MlKemPublicKey handler that lazily fetches the root public key
3041
- * from `${baseUrl}/status` on first invocation, verifies it against the
3042
- * DKG attestation trust anchor (SP-003), and caches the encoded response
3043
- * for subsequent calls.
3044
- *
3045
- * @param baseUrl - **Required**. The node URL whose `/status` endpoint should
3046
- * serve the ML-KEM public key. Must be the same URL the
3047
- * T3nClient is constructed with — otherwise the handshake
3048
- * encrypts to one node and sends ciphertext to another.
3049
- *
3050
- * Was optional in 0.3.x, where omitting it caused the lazy
3051
- * fetch to silently fall back to `NODE_URLS[currentEnv]` and
3052
- * hit the wrong node. Three downstream consumers (demo.ts,
3053
- * t3-apps dev wallet hooks, t3n-mcp session manager) all
3054
- * hit this trap before we tightened the type.
3055
- * @param trustAnchor - **Required**. Client-pinned expected peer IDs +
3056
- * RTMR3 allowlist the DKG bundle is verified against, or
3057
- * `{ unsafe_trust_server: true }` to skip verification.
3058
- * The key is only cached/returned once verification passes.
3059
- */
3060
- declare function createMlKemPublicKeyHandler(baseUrl: string, trustAnchor: TrustAnchorOrUnsafe): GuestToHostHandler;
3061
- /**
3062
- * Create Random handler backed by crypto.getRandomValues
3063
- * Note: The Rust Vec<u8> type serializes as an array of bytes, not a base64 string
3064
- */
3065
- declare function createRandomHandler(): GuestToHostHandler;
3066
- /**
3067
- * Create the default handler set required by the T3n handshake.
3068
- *
3069
- * @param baseUrl - **Required**. Forwarded to `createMlKemPublicKeyHandler`
3070
- * so the lazy /status fetch hits the right node.
3071
- * @param trustAnchor - **Required**. Forwarded to the ML-KEM handler so the
3072
- * fetched key is verified against the DKG attestation
3073
- * (SP-003) before the handshake trusts it.
3074
- */
3075
- declare function createDefaultHandlers(baseUrl: string, trustAnchor: TrustAnchorOrUnsafe): GuestToHostHandlers;
3076
-
3077
- /**
3078
- * Stateless `api_key` agent auth.
3079
- *
3080
- * `invoke` posts once to `POST /api/invoke` — an HTTPS-only
3081
- * endpoint (see the HTTPS-guard note below) that authenticates an org agent
3082
- * by an opaque API key (`X-T3N-Api-Key: t3n_key_<...>`) and executes a
3083
- * `z:` contract as that agent in the SAME request. Unlike
3084
- * {@link T3nClient.execute}, there is **no** ML-KEM handshake, **no**
3085
- * `Session-Id`, and **no** session state: the node derives the acting agent
3086
- * DID from the relayed key per-call (`resolve_stateless_credential`
3087
- * driving the session contract's `api_key` action), then runs the same
3088
- * execute pipeline `action.execute` runs after `check_authentication`
3089
- * (`ActionService::execute_as_did`), and returns the contract's decoded
3090
- * result as a plain `Json(result)` body — NOT a JSON-RPC envelope.
3091
- *
3092
- * Because the response is the bare decoded value (no `{jsonrpc,result,id}`
3093
- * wrapper to unwrap), decoding reuses {@link parseContractResponse} — the
3094
- * exact same JSON.parse + optional-schema path {@link T3nClient.executeAndDecode}
3095
- * uses for the session `execute` RPC — so callers get identical typed /
3096
- * schema-validated decoding on either path.
3097
- *
3098
- * This module intentionally does NOT import {@link T3nClient}, the WASM
3099
- * component loader, or any handshake/session machinery — `invoke` is
3100
- * a single fetch, nothing else.
3101
- *
3102
- * ### Keyed discovery transports
3103
- * Alongside `invoke` (which acts), this module exports the keyed **discovery**
3104
- * reads — {@link discoverWhoami}, {@link discoverListContracts},
3105
- * {@link discoverCheckDelegation}, {@link discoverDescribeContract},
3106
- * {@link discoverDescribeFunction}. They are the api-key counterpart of the
3107
- * session `T3nClient.listContracts` / `checkDelegation` reads: each POSTs a
3108
- * `{ method, params }` envelope to the node's `POST /api/discover` with the
3109
- * same `X-T3N-Api-Key` header, HTTPS guard, timeout, and key-safe error
3110
- * hygiene as `invoke`, and returns the node's raw JSON result. The session
3111
- * `T3nClient` methods are untouched — these live beside `invoke`, off the
3112
- * session client, so the relay reads never open a session. Every transport
3113
- * shares the {@link postKeyed} core, so there is one implementation of the
3114
- * secure-transport + secret-hygiene rules below, not two.
3115
- *
3116
- * ### HTTPS guard
3117
- * The API key is a long-lived bearer credential relayed in a plain header,
3118
- * so `invoke` refuses to send it over an insecure transport: `baseUrl`
3119
- * must be `https:`, unless the host is a local-dev loopback
3120
- * (`localhost` / `127.0.0.1` / `[::1]`), in which case plain `http:` is
3121
- * allowed. The check runs before any network activity — an insecure
3122
- * `baseUrl` never gets as far as a `fetch` call.
3123
- *
3124
- * ### Error hygiene
3125
- * Every error `invoke` throws is a fixed, generic
3126
- * {@link InvokeError} message — the response body text, the
3127
- * underlying network error's message, and the api key are never
3128
- * interpolated into it. This is defense in depth against a server (or a
3129
- * malicious intermediary) that echoes the key or other secrets back in an
3130
- * error body: whatever comes back over the wire on a non-2xx response is
3131
- * discarded, not surfaced. The timeout timer also stays armed until the
3132
- * response body has been fully read (or has itself timed out) — see
3133
- * {@link invoke}'s implementation — so a connection that delivers
3134
- * headers and then stalls on the body still respects `timeoutMs`.
3135
- */
3136
-
3137
- /**
3138
- * Wire body for `POST /api/invoke` — mirrors the server's
3139
- * server-side `ExecuteActionRequest`, the same shape
3140
- * `T3nClient`'s `execute*` wrappers build for the session `action.execute`
3141
- * RPC. Field names are load-bearing: the server deserialises strictly into
3142
- * `script_name` / `script_version` / `function_name` (see
3143
- * `T3nClient.executeSystemContract`'s doc comment) — `contract` / `version`
3144
- * / `function` produce a 400.
3145
- */
3146
- interface InvokeRequest {
3147
- script_name: string;
3148
- script_version: string;
3149
- function_name: string;
3150
- /** Delegated-call target member; omitted for a self (non-delegated) call. */
3151
- pii_did?: string;
3152
- input?: unknown;
3153
- }
3154
- /** Options for {@link invoke}. */
3155
- interface InvokeOptions {
3274
+ getSessionId(): SessionId | null;
3275
+ getStatus(): SessionStatus;
3276
+ getDid(): Did | null;
3277
+ getLastSetCookie(): string | null;
3278
+ getLastResponseHeaders(): Record<string, string>;
3279
+ isAuthenticated(): boolean;
3156
3280
  /**
3157
- * RPC base URL of the T3n node, e.g. `https://node.example.com`. Must be
3158
- * `https:` unless the host is a local-dev loopback (`localhost` /
3159
- * `127.0.0.1` / `[::1]`) — see the module doc comment's HTTPS-guard note.
3281
+ * Run a WASM state machine flow to completion.
3282
+ *
3283
+ * Clears both `wasmState[method]` and `finalizedPayload[method]`
3284
+ * at entry so a flow that previously threw partway (e.g. an RPC
3285
+ * error) starts from a clean slate on retry. Without the reset,
3286
+ * stale state from the failed attempt leaks into the new flow
3287
+ * and `tryFinalize` may either spuriously succeed or run `next()`
3288
+ * against a state that no longer matches the action we're sending.
3289
+ *
3290
+ * The `tryFinalize`-then-`next` order is load-bearing: the loop's
3291
+ * exit condition fires *after* the previous iteration's
3292
+ * `handleWasmRequest` has flushed the outbound peer reply, so
3293
+ * every state-machine emission reaches the wire before we extract
3294
+ * the final payload.
3160
3295
  */
3161
- baseUrl: string;
3296
+ private runFlow;
3162
3297
  /**
3163
- * The agent's opaque API key (`t3n_key_<...>`), relayed verbatim in the
3164
- * `X-T3N-Api-Key` header. Never logged and never interpolated into any
3165
- * error this module throws — see the module doc comment and
3166
- * {@link InvokeError}.
3167
- */
3168
- apiKey: string;
3169
- /** The wire request to execute, built to the {@link InvokeRequest} shape. */
3170
- request: InvokeRequest;
3171
- /** Fetch timeout in ms. Defaults to 30s, matching {@link HttpTransport}. */
3172
- timeoutMs?: number;
3173
- }
3174
- /**
3175
- * Thrown when `POST /api/invoke` fails at the transport or HTTP
3176
- * layer (network failure, timeout, non-2xx status). Contract-level errors
3177
- * the node returns as a 2xx JSON error value are NOT wrapped here — they
3178
- * flow through {@link parseContractResponse}'s normal return, same as the
3179
- * session `execute` path.
3180
- *
3181
- * The message is always one of a small set of fixed, generic strings — it
3182
- * NEVER contains the raw api key, the response body text, or the
3183
- * underlying network error's message: a server (or a
3184
- * misbehaving intermediary) that echoes the key or other secrets back in
3185
- * an error body must not be able to leak them through this error's
3186
- * message.
3187
- */
3188
- declare class InvokeError extends T3nError {
3189
- readonly status?: number | undefined;
3190
- constructor(message: string, status?: number | undefined);
3191
- }
3192
- /**
3193
- * Execute a `z:` contract as an org agent, authenticating with an opaque
3194
- * API key — one request, no handshake, no session.
3195
- *
3196
- * @param opts - baseUrl, apiKey, and the wire request to execute
3197
- * @param schema - optional validator applied to the decoded result (e.g. a
3198
- * zod schema); anything exposing `.parse(value)` is accepted, same as
3199
- * {@link T3nClient.executeAndDecode}
3200
- * @returns the contract's decoded result, typed as `T`
3201
- * @throws {InvokeError} if `baseUrl` is insecure, on a network
3202
- * failure/timeout, or on a non-2xx response
3203
- * @throws {ContractResponseError} if the node returns a 2xx with a body
3204
- * that is not valid JSON
3205
- */
3206
- declare function invoke<T = unknown>(opts: InvokeOptions, schema?: ContractResponseSchema<T>): Promise<T>;
3207
- /**
3208
- * Transport options shared by the keyed discovery reads. Mirrors the transport
3209
- * half of {@link InvokeOptions} (no `request`; the operation params are the
3210
- * second argument of each read). Same HTTPS + secret-hygiene rules as `invoke`.
3211
- */
3212
- interface DiscoverOptions {
3298
+ * Try to finalize the current flow. Returns the finish() payload
3299
+ * (a serialized Session for handshake, a serialized DID for auth)
3300
+ * or `null` if the state machine has not reached its terminal phase
3301
+ * yet.
3302
+ *
3303
+ * The "not yet finalized" case is the loop's signal to keep
3304
+ * iterating, not a real error. Any *other* failure must propagate
3305
+ * so callers see real WASM errors instead of silent retries that
3306
+ * spin forever.
3307
+ *
3308
+ * The terminal payload is stored in `finalizedPayload[method]`
3309
+ * (a separate field from `wasmState[method]`) so the in-flight
3310
+ * state-machine bytes and the finalized session/DID bytes never
3311
+ * occupy the same slot. `getSessionState()` reads from
3312
+ * `finalizedPayload.handshake`.
3313
+ */
3314
+ private tryFinalize;
3213
3315
  /**
3214
- * RPC base URL of the T3n node, e.g. `https://node.example.com`. Must be
3215
- * `https:` unless the host is a local-dev loopback — see
3216
- * {@link InvokeOptions.baseUrl}.
3316
+ * Handle a WASM request based on its type
3217
3317
  */
3218
- baseUrl: string;
3318
+ private handleWasmRequest;
3219
3319
  /**
3220
- * The agent's opaque API key (`t3n_key_<...>`), relayed verbatim in the
3221
- * `X-T3N-Api-Key` header. Never logged and never interpolated into any
3222
- * error this module throws.
3320
+ * Handle a send-remote request by calling the RPC endpoint
3223
3321
  */
3224
- apiKey: string;
3225
- /** Fetch timeout in ms. Defaults to 30s, matching {@link invoke}. */
3226
- timeoutMs?: number;
3227
- }
3228
- /**
3229
- * `whoami` — resolve the DID the relayed key maps to. The node never
3230
- * trusts a caller-supplied DID; this is the relay's sole DID source.
3231
- *
3232
- * @throws {InvokeError} if `baseUrl` is insecure, on a network failure/timeout,
3233
- * or on a non-2xx response
3234
- */
3235
- declare function discoverWhoami(opts: DiscoverOptions): Promise<WhoamiResult>;
3236
- /**
3237
- * `contracts.list` — the keyed counterpart of {@link T3nClient.listContracts}.
3238
- * Absent `params` (`{}`) lists the curated `core` contracts; `org` / `self`
3239
- * scopes are discovery-grant gated server-side (R5 non-disclosive empty page).
3240
- *
3241
- * @throws {InvokeError} — see {@link discoverWhoami}
3242
- */
3243
- declare function discoverListContracts(opts: DiscoverOptions, params?: ListContractsParams): Promise<ListContractsResult>;
3244
- /**
3245
- * `delegation.check` — the keyed counterpart of
3246
- * {@link T3nClient.checkDelegation}. Returns the `agent_auth ∩ UserGrant`
3247
- * verdict for the acting agent (as itself, or for `params.pii_did`).
3248
- *
3249
- * @throws {InvokeError} — see {@link discoverWhoami}
3250
- */
3251
- declare function discoverCheckDelegation(opts: DiscoverOptions, params: GrantCheckParams): Promise<GrantCheckResult>;
3252
- /**
3253
- * `describe.contract` — the authority-gated keyed describe read. Returns
3254
- * `{ contract, version, descriptor }`: the resolved dispatch `version` (the
3255
- * `scriptVersion` an {@link invoke} call needs) alongside the contract's full
3256
- * descriptor document. Unlike the session/stdio public descriptor GET, the relay
3257
- * path is membership-gated on the contract's owning org and returns a uniform
3258
- * non-disclosive error for both "not found" and "not authorised"
3259
- * (anti-enumeration).
3260
- *
3261
- * @throws {InvokeError} — see {@link discoverWhoami}
3262
- */
3263
- declare function discoverDescribeContract(opts: DiscoverOptions, params: DescribeContractParams): Promise<DescribeContractResult>;
3264
- /**
3265
- * `describe.function` — the authority-gated keyed describe read for a single
3266
- * function. Returns `{ contract, version, descriptor }` with `descriptor` the
3267
- * projected function entry. Same gating as {@link discoverDescribeContract}.
3268
- *
3269
- * @throws {InvokeError} — see {@link discoverWhoami}
3270
- */
3271
- declare function discoverDescribeFunction(opts: DiscoverOptions, params: DescribeFunctionParams): Promise<DescribeFunctionResult>;
3272
-
3273
- /**
3274
- * Token fixed-point units (USDT-style 6 decimals).
3275
- *
3276
- * As of `tee:*` metering v2, every token amount on the wire —
3277
- * {@link BalanceRow}'s `available`/`reserved`, {@link UsageEntry.amount},
3278
- * and `total_supply` — is denominated in **base units**, where
3279
- * `1 T3N token = `{@link BASE_UNITS_PER_TOKEN}` base units`. The node
3280
- * meters the *actual* fractional cost of each operation (pro-rata by
3281
- * bytes / byte-seconds / fuel) down to `1e-6` token, so amounts are
3282
- * raw integers in base units, NOT whole tokens.
3283
- *
3284
- * The wire fields are left as raw base units (no silent rescaling — that
3285
- * would lose precision for large balances and surprise callers doing
3286
- * arithmetic). Use {@link formatTokens} to render a human "tokens"
3287
- * string and {@link toBaseUnits} to convert a token figure back.
3288
- *
3289
- * ⚠️ Breaking vs. the pre-decimals SDK: a balance that used to read `5`
3290
- * (whole tokens) now reads `5_000_000` (base units). Multiply existing
3291
- * display code through {@link formatTokens}.
3292
- */
3293
- /** Decimal places in a T3N token (fixed; mirrors the node constant). */
3294
- declare const TOKEN_DECIMALS = 6;
3295
- /** Base units per whole T3N token — `10 ** TOKEN_DECIMALS`. */
3296
- declare const BASE_UNITS_PER_TOKEN = 1000000;
3297
- /**
3298
- * Render a base-unit amount as a human-readable token string, e.g.
3299
- * `25_920_000 → "25.92"`, `1_000_000 → "1"`, `4768 → "0.004768"`.
3300
- *
3301
- * Trailing-zero fraction digits are trimmed; an integer amount renders
3302
- * with no decimal point. Accepts `number` or `bigint`; for balances
3303
- * above `Number.MAX_SAFE_INTEGER` prefer passing a `bigint`.
3304
- */
3305
- declare function formatTokens(baseUnits: number | bigint): string;
3306
- /**
3307
- * Convert a whole-or-fractional token figure to base units (rounded to
3308
- * the nearest base unit). E.g. `25.92 → 25_920_000`, `1 → 1_000_000`.
3309
- */
3310
- declare function toBaseUnits(tokens: number): number;
3311
-
3312
- /**
3313
- * Org-data wire types mirroring the org-data contract wire shapes.
3314
- *
3315
- * Plain TypeScript interfaces (no zod) — the SDK does not use a
3316
- * validation library for domain types; see the existing `types/` files.
3317
- *
3318
- * Each response type below is paired with a shallow runtime predicate
3319
- * (`isMutationResponse`, `isOrgPolicyMeta`, etc.) so the org-data client
3320
- * can `assertShape` the decoded payload before returning to callers.
3321
- * Predicates check the top-level structure only; nested elements
3322
- * (e.g. each `UserGrant` inside `OrgContractGrants.grants`) are not
3323
- * deeply validated — see `utils/shape.ts` for the rationale.
3324
- *
3325
- * Reference: the org-data wire contract.
3326
- */
3327
- /**
3328
- * Capability grant stored under `ORG_CONTRACT_GRANTS_MAP`.
3329
- *
3330
- * Mirrors the org-data `UserGrant` wire shape.
3331
- */
3332
- interface UserGrant {
3333
- /** The user this grant applies to (`did:t3n:<40-hex>`). */
3334
- user_did: string;
3335
- /** WIT function names the user may invoke (e.g. `"set-records"`). */
3336
- functions: string[];
3337
- /** Data scope paths the user may access (e.g. `"example/records"`). */
3338
- scopes: string[];
3339
- }
3340
- /**
3341
- * Policy record for an organisation's data tier.
3342
- *
3343
- * Mirrors the org-data policy-meta wire shape.
3344
- */
3345
- interface OrgPolicyMeta {
3346
- /** DIDs (`did:t3n:<40-hex>`) of users authorised to manage policy and read data. */
3347
- admins: string[];
3348
- /** Maximum number of admins allowed for this org. */
3349
- max_admins: number;
3350
- /** Unix timestamp (secs) when the policy was first created. */
3351
- created_at_secs: number;
3352
- /** Unix timestamp (secs) of the most recent policy update. */
3353
- updated_at_secs: number;
3322
+ private handleSendRemote;
3323
+ private captureHandshakeResult;
3354
3324
  /**
3355
- * Per-org ceiling on delegation-credential validity (seconds).
3325
+ * Handle a guest-to-host request using configured handlers
3326
+ */
3327
+ private handleGuestToHost;
3328
+ /**
3329
+ * Send an RPC request with automatic encryption/decryption
3330
+ */
3331
+ private sendRpcRequest;
3332
+ /**
3333
+ * Send a session-authenticated JSON-RPC request with plaintext
3334
+ * params/result (no SessionEncryption layer). Used for tenant-facing
3335
+ * read endpoints whose payloads carry only public / non-disclosive
3336
+ * metadata (`contracts.list`, `delegation.check`) where the
3337
+ * server-side handler reads the JSON envelope directly. (The token
3338
+ * self-reads moved to the sealed path — see {@link getUsage}.)
3356
3339
  *
3357
- * Absent when no org-level cap is set — the contract omits the field
3358
- * (never serialises null) and the cluster-wide
3359
- * `delegation.max_credential_validity_secs` governs instead. When set,
3360
- * the effective cap is `min(max_credential_validity_secs, cluster_ceiling)`.
3340
+ * Auto-attaches the `Session-Id` header; surfaces JSON-RPC errors
3341
+ * the same way as {@link sendRpcRequest} (typed
3342
+ * `InsufficientCreditError` when applicable, `RpcError` otherwise).
3343
+ * Returns the parsed `result` field — typically a JSON object the
3344
+ * caller will narrow to the endpoint's response type.
3361
3345
  */
3362
- max_credential_validity_secs?: number;
3363
- }
3364
- /** Shallow runtime guard for {@link OrgPolicyMeta}. */
3365
- declare function isOrgPolicyMeta(value: unknown): value is OrgPolicyMeta;
3366
- /**
3367
- * Effective org policy view returned by `org-policy-view`.
3368
- *
3369
- * Readable by any authenticated session (non-sensitive metadata).
3370
- * Returns the **effective** credential validity cap:
3371
- * `min(org.max_credential_validity_secs, cluster_ceiling)`, equal to the
3372
- * cluster ceiling when the org has not set a per-org cap. The contract
3373
- * always returns a value (or errors) — the field is never null.
3374
- */
3375
- interface OrgPolicyView {
3346
+ private sendUnencryptedSessionRpc;
3376
3347
  /**
3377
- * Effective delegation-credential validity cap in seconds:
3378
- * `min(org value, cluster ceiling)`, equal to the cluster ceiling when the
3379
- * org has not set a per-org cap. Always present — mirrors the contract's
3380
- * `PolicyViewResponse.effective_validity_secs` (org-data `org-policy-view`).
3348
+ * Send a session-authenticated JSON-RPC request whose params/result
3349
+ * are sealed with the same {@link SessionEncryption} layer
3350
+ * `action.execute` uses — for read endpoints that return PII
3351
+ * (`audit.get-mine`) and therefore must not travel plaintext over
3352
+ * TLS. Unlike {@link sendRpcRequest}, this is not tied to the WASM
3353
+ * client `Method` state machine: it takes the raw RPC method string
3354
+ * and only does encrypt → send → decrypt.
3355
+ *
3356
+ * Requires an established (>= Encrypted) session; returns the
3357
+ * decrypted plaintext response string for the caller to `JSON.parse`.
3381
3358
  */
3382
- effective_validity_secs: number;
3383
- }
3384
- /** Shallow runtime guard for {@link OrgPolicyView}. */
3385
- declare function isOrgPolicyView(value: unknown): value is OrgPolicyView;
3386
- /**
3387
- * Caller-scoped admin status returned by `org-am-i-admin`.
3388
- *
3389
- * Reports only whether the **calling** session's DID is in the org's admin
3390
- * list — never the roster itself (contrast {@link OrgPolicyMeta}, returned by
3391
- * the admin-gated `org-policy-get`). Readable by any authenticated session.
3392
- * Mirrors the org-data `AmIAdminResponse` wire shape.
3393
- */
3394
- interface OrgAdminStatus {
3395
- /** Whether the calling session is an admin of the queried org. */
3396
- is_admin: boolean;
3397
- }
3398
- /** Shallow runtime guard for {@link OrgAdminStatus}. */
3399
- declare function isOrgAdminStatus(value: unknown): value is OrgAdminStatus;
3400
- /**
3401
- * Standard response returned by all policy write and data mutation operations.
3402
- *
3403
- * Mirrors the org-data `MutationResponse` wire shape.
3404
- */
3405
- interface MutationResponse {
3359
+ private sendEncryptedSessionRpc;
3406
3360
  /**
3407
- * `"created"`, `"updated"`, `"deleted"`, or — for the agent-card mutations —
3408
- * `"published"` / `"unpublished"`.
3361
+ * Inspect a JSON-RPC response for an `error` field and throw the
3362
+ * appropriate typed exception. No-op when `response.error` is
3363
+ * absent. Shared by every RPC path so wire-shape changes in the
3364
+ * server's error envelope (typed-error subclasses, request-id
3365
+ * placement, detail formatting) only need to land in one place.
3366
+ *
3367
+ * JSON-RPC `error.message` is the generic category string
3368
+ * ("Invalid params", "Internal error", …). The node attaches the
3369
+ * actionable text and per-request correlation id in `error.data`.
3370
+ * Extract both so callers (and toasts that only render `.message`)
3371
+ * get the real reason plus an id an operator can grep in the logs.
3372
+ *
3373
+ * Chargepoint denials surface as a typed
3374
+ * `InsufficientCreditError` so frontends can branch on
3375
+ * `instanceof` to render an "out of credit" UI without
3376
+ * prefix-matching the message themselves. The wire format is stable.
3409
3377
  */
3410
- status: string;
3411
- /** Hex-encoded entry ID; present on data write/delete operations. */
3412
- entry_id?: string;
3413
- /** Whether the target key existed before deletion; present on single-entry deletes. */
3414
- deleted?: boolean;
3415
- /** Number of entries removed; present on `org-data-delete-scope`. */
3416
- deleted_entries?: number;
3417
- tx_hash: string | null;
3378
+ private throwIfRpcError;
3379
+ private sendMultipartRpcRequest;
3380
+ /**
3381
+ * Capture the server-minted `Session-Id` from the last handshake
3382
+ * response headers. Validates shape so a
3383
+ * broken or MITM'd response fails loudly instead of leaving a
3384
+ * garbage value in the client. Idempotent: only the first valid
3385
+ * mint per session is honoured — subsequent handshake RPC legs
3386
+ * (none exist today, but the state-machine loop can iterate) do
3387
+ * not overwrite an already-set value.
3388
+ */
3389
+ private captureMintedSessionId;
3390
+ /**
3391
+ * Get the finalized session blob (for `session.encrypt` calls).
3392
+ * Populated by `tryFinalize` once the handshake state machine
3393
+ * reaches its terminal phase.
3394
+ */
3395
+ private getSessionState;
3418
3396
  }
3397
+
3419
3398
  /**
3420
- * Shallow runtime guard for {@link MutationResponse}.
3399
+ * Guest-to-Host Request Handlers
3421
3400
  *
3422
- * Only the always-present fields are checked — `status` is mandatory on
3423
- * every mutation; `tx_hash` is non-optional but nullable. The optional
3424
- * fields (`entry_id`, `deleted`, `deleted_entries`) are not validated
3425
- * because their presence depends on which mutation ran.
3401
+ * These handle requests from WASM that need the host environment to perform side effects.
3402
+ * Examples: signing challenges, providing public keys, generating random bytes.
3426
3403
  */
3427
- declare function isMutationResponse(value: unknown): value is MutationResponse;
3404
+
3428
3405
  /**
3429
- * Response type alias for org-writers-get.
3430
- *
3431
- * The wire body is `{ writers: string[] }` where each entry is
3432
- * `did:t3n:<40-hex>`.
3406
+ * Account — MetaMask handler accepts either a plain address string or an
3407
+ * object with an `address` field (for compatibility with various wallet
3408
+ * libraries).
3433
3409
  */
3434
- interface OrgWriters {
3435
- writers: string[];
3436
- }
3437
- /** Shallow runtime guard for {@link OrgWriters}. */
3438
- declare function isOrgWriters(value: unknown): value is OrgWriters;
3410
+ type EthAccount = string | {
3411
+ address: string;
3412
+ };
3439
3413
  /**
3440
- * Response type alias for org-grants-get.
3441
- *
3442
- * The wire body echoes the `contract_id` alongside the grant list.
3414
+ * Create an EthSign handler using MetaMask (window.ethereum)
3415
+ * @param account - MetaMask account (string address or object with address property)
3416
+ * @param logger - Optional logger instance. Defaults to a logger using the global log level (LogLevel.ERROR).
3417
+ * Pass a custom logger to override logging behavior for this handler.
3418
+ * @param privateKey - Optional private key for signing (if provided, MetaMask is not used)
3443
3419
  */
3444
- interface OrgContractGrants {
3445
- contract_id: string;
3446
- grants: UserGrant[];
3447
- }
3420
+ declare function metamask_sign(account: EthAccount, logger?: Logger, privateKey?: string | undefined): GuestToHostHandler;
3448
3421
  /**
3449
- * Shallow runtime guard for {@link OrgContractGrants}.
3450
- *
3451
- * Validates the immediate envelope (`contract_id: string`, `grants:
3452
- * array`) without recursing into each `UserGrant`. The Rust contract
3453
- * is the source of truth for grant element shape; widening the predicate
3454
- * here would create maintenance churn against benign field additions.
3422
+ * Get the current MetaMask address
3423
+ * @returns Ethereum address (lowercase, 0x prefixed)
3455
3424
  */
3456
- declare function isOrgContractGrants(value: unknown): value is OrgContractGrants;
3425
+ declare function metamask_get_address(): Promise<string>;
3457
3426
  /**
3458
- * One grant inside a role: a {@link UserGrant} body (without the
3459
- * grantee, which is bound at assignment time) plus the target contract.
3460
- * Mirrors the org-data `RoleGrant` wire shape.
3427
+ * Get the address for a given private key
3428
+ * @param privateKey - Ethereum private key (0x prefixed hex string)
3429
+ * @returns Ethereum address (lowercase, 0x prefixed)
3461
3430
  */
3462
- interface RoleGrant {
3463
- /** Target contract (canonical name, e.g. `"tee:z-payroll/contracts"`). */
3464
- contract_id: string;
3465
- /** WIT function names this grant confers. */
3466
- functions: string[];
3467
- /** Data scope paths this grant confers (canonicalised lowercase). */
3468
- scopes: string[];
3469
- }
3431
+ declare function eth_get_address(privateKey: string): string;
3470
3432
  /**
3471
- * A role: a named bundle of grants and/or composed sub-roles.
3472
- * Mirrors the org-data `RoleDefinition` wire shape.
3433
+ * Create an MlKemPublicKey handler that lazily fetches the root public key
3434
+ * from `${baseUrl}/status` on first invocation, verifies it against the
3435
+ * DKG attestation trust anchor (SP-003), and caches the encoded response
3436
+ * for subsequent calls.
3437
+ *
3438
+ * @param baseUrl - **Required**. The node URL whose `/status` endpoint should
3439
+ * serve the ML-KEM public key. Must be the same URL the
3440
+ * T3nClient is constructed with — otherwise the handshake
3441
+ * encrypts to one node and sends ciphertext to another.
3442
+ *
3443
+ * Was optional in 0.3.x, where omitting it caused the lazy
3444
+ * fetch to silently fall back to `NODE_URLS[currentEnv]` and
3445
+ * hit the wrong node. Three downstream consumers (demo.ts,
3446
+ * t3-apps dev wallet hooks, t3n-mcp session manager) all
3447
+ * hit this trap before we tightened the type.
3448
+ * @param trustAnchor - **Required**. Client-pinned expected peer IDs +
3449
+ * RTMR3 allowlist the DKG bundle is verified against, or
3450
+ * `{ unsafe_trust_server: true }` to skip verification.
3451
+ * The key is only cached/returned once verification passes.
3473
3452
  */
3474
- interface RoleDefinition {
3475
- /** Org-unique role identifier (slug; function-name grammar). */
3476
- role_id: string;
3477
- /** Human-facing label. */
3478
- label: string;
3479
- /** Composite: other role ids in the same org whose grants this role confers. */
3480
- includes: string[];
3481
- /** Grants this role confers directly. */
3482
- grants: RoleGrant[];
3483
- }
3453
+ declare function createMlKemPublicKeyHandler(baseUrl: string, trustAnchor: TrustAnchorOrUnsafe): GuestToHostHandler;
3484
3454
  /**
3485
- * The roles assigned to one grantee within one org.
3486
- * Mirrors the org-data `RoleAssignments` wire shape.
3455
+ * Create Random handler backed by crypto.getRandomValues
3456
+ * Note: The Rust Vec<u8> type serializes as an array of bytes, not a base64 string
3487
3457
  */
3488
- interface RoleAssignments {
3489
- /** Assigned role ids. */
3490
- roles: string[];
3491
- }
3492
- /** Response for `org-role-get`; `role` is `null` when the id is unknown. */
3493
- interface RoleGetResponse {
3494
- role: RoleDefinition | null;
3495
- }
3496
- /** Shallow runtime guard for {@link RoleGetResponse}. */
3497
- declare function isRoleGetResponse(value: unknown): value is RoleGetResponse;
3458
+ declare function createRandomHandler(): GuestToHostHandler;
3498
3459
  /**
3499
- * One org-owned agent's outbound host allow-list for a single contract.
3460
+ * Create the default handler set required by the T3n handshake.
3500
3461
  *
3501
- * Egress only — it carries no data scopes by construction, so it can never be
3502
- * a second path to org data (that stays with `org-policy-set-grants`).
3462
+ * @param baseUrl - **Required**. Forwarded to `createMlKemPublicKeyHandler`
3463
+ * so the lazy /status fetch hits the right node.
3464
+ * @param trustAnchor - **Required**. Forwarded to the ML-KEM handler so the
3465
+ * fetched key is verified against the DKG attestation
3466
+ * (SP-003) before the handshake trusts it.
3503
3467
  */
3504
- interface AgentEgressEntry {
3468
+ declare function createDefaultHandlers(baseUrl: string, trustAnchor: TrustAnchorOrUnsafe): GuestToHostHandlers;
3469
+
3470
+ /**
3471
+ * Stateless `api_key` agent auth.
3472
+ *
3473
+ * `invoke` posts once to `POST /api/invoke` — an HTTPS-only
3474
+ * endpoint (see the HTTPS-guard note below) that authenticates an org agent
3475
+ * by an opaque API key (`X-T3N-Api-Key: t3n_key_<...>`) and executes a
3476
+ * `z:` contract as that agent in the SAME request. Unlike
3477
+ * {@link T3nClient.execute}, there is **no** ML-KEM handshake, **no**
3478
+ * `Session-Id`, and **no** session state: the node derives the acting agent
3479
+ * DID from the relayed key per-call (`resolve_stateless_credential`
3480
+ * driving the session contract's `api_key` action), then runs the same
3481
+ * execute pipeline `action.execute` runs after `check_authentication`
3482
+ * (`ActionService::execute_as_did`), and returns the contract's decoded
3483
+ * result as a plain `Json(result)` body — NOT a JSON-RPC envelope.
3484
+ *
3485
+ * Because the response is the bare decoded value (no `{jsonrpc,result,id}`
3486
+ * wrapper to unwrap), decoding reuses {@link parseContractResponse} — the
3487
+ * exact same JSON.parse + optional-schema path {@link T3nClient.executeAndDecode}
3488
+ * uses for the session `execute` RPC — so callers get identical typed /
3489
+ * schema-validated decoding on either path.
3490
+ *
3491
+ * This module intentionally does NOT import {@link T3nClient}, the WASM
3492
+ * component loader, or any handshake/session machinery — `invoke` is
3493
+ * a single fetch, nothing else.
3494
+ *
3495
+ * ### Keyed discovery transports
3496
+ * Alongside `invoke` (which acts), this module exports the keyed **discovery**
3497
+ * reads — {@link discoverWhoami}, {@link discoverListContracts},
3498
+ * {@link discoverCheckDelegation}, {@link discoverDescribeContract},
3499
+ * {@link discoverDescribeFunction}. They are the api-key counterpart of the
3500
+ * session `T3nClient.listContracts` / `checkDelegation` reads: each POSTs a
3501
+ * `{ method, params }` envelope to the node's `POST /api/discover` with the
3502
+ * same `X-T3N-Api-Key` header, HTTPS guard, timeout, and key-safe error
3503
+ * hygiene as `invoke`, and returns the node's raw JSON result. The session
3504
+ * `T3nClient` methods are untouched — these live beside `invoke`, off the
3505
+ * session client, so the relay reads never open a session. Every transport
3506
+ * shares the {@link postKeyed} core, so there is one implementation of the
3507
+ * secure-transport + secret-hygiene rules below, not two.
3508
+ *
3509
+ * ### HTTPS guard
3510
+ * The API key is a long-lived bearer credential relayed in a plain header,
3511
+ * so `invoke` refuses to send it over an insecure transport: `baseUrl`
3512
+ * must be `https:`, unless the host is a local-dev loopback
3513
+ * (`localhost` / `127.0.0.1` / `[::1]`), in which case plain `http:` is
3514
+ * allowed. The check runs before any network activity — an insecure
3515
+ * `baseUrl` never gets as far as a `fetch` call.
3516
+ *
3517
+ * ### Error hygiene
3518
+ * Every error `invoke` throws is a fixed, generic
3519
+ * {@link InvokeError} message — the response body text, the
3520
+ * underlying network error's message, and the api key are never
3521
+ * interpolated into it. This is defense in depth against a server (or a
3522
+ * malicious intermediary) that echoes the key or other secrets back in an
3523
+ * error body: whatever comes back over the wire on a non-2xx response is
3524
+ * discarded, not surfaced. The timeout timer also stays armed until the
3525
+ * response body has been fully read (or has itself timed out) — see
3526
+ * {@link invoke}'s implementation — so a connection that delivers
3527
+ * headers and then stalls on the body still respects `timeoutMs`.
3528
+ */
3529
+
3530
+ /**
3531
+ * Wire body for `POST /api/invoke` — mirrors the server's
3532
+ * server-side `ExecuteActionRequest`, the same shape
3533
+ * `T3nClient`'s `execute*` wrappers build for the session `action.execute`
3534
+ * RPC. Field names are load-bearing: the server deserialises strictly into
3535
+ * `contract_id` / `contract_version` / `function_name` (see
3536
+ * `T3nClient.executeSystemContract`'s doc comment) — `contract` / `version`
3537
+ * / `function` produce a 400.
3538
+ */
3539
+ interface InvokeRequest {
3505
3540
  contract_id: string;
3506
- /** Bare lowercase hostnames, matched exactly by the node. */
3507
- allowed_hosts: string[];
3508
- /** WIT functions covered; `["*"]` means all of them. */
3509
- functions: string[];
3510
- /** Present only when the allow-list is pinned to a version range. */
3511
- version_req?: string;
3541
+ contract_version: string;
3542
+ function_name: string;
3543
+ /** Delegated-call target member; omitted for a self (non-delegated) call. */
3544
+ pii_did?: string;
3545
+ input?: unknown;
3546
+ }
3547
+ /** Options for {@link invoke}. */
3548
+ interface InvokeOptions {
3549
+ /**
3550
+ * RPC base URL of the T3n node, e.g. `https://node.example.com`. Must be
3551
+ * `https:` unless the host is a local-dev loopback (`localhost` /
3552
+ * `127.0.0.1` / `[::1]`) — see the module doc comment's HTTPS-guard note.
3553
+ */
3554
+ baseUrl: string;
3555
+ /**
3556
+ * The agent's opaque API key (`t3n_key_<...>`), relayed verbatim in the
3557
+ * `X-T3N-Api-Key` header. Never logged and never interpolated into any
3558
+ * error this module throws — see the module doc comment and
3559
+ * {@link InvokeError}.
3560
+ */
3561
+ apiKey: string;
3562
+ /** The wire request to execute, built to the {@link InvokeRequest} shape. */
3563
+ request: InvokeRequest;
3564
+ /** Fetch timeout in ms. Defaults to 30s, matching {@link HttpTransport}. */
3565
+ timeoutMs?: number;
3512
3566
  }
3513
3567
  /**
3514
- * Response for `org-agent-egress-get`; `egress` is `null` when the agent holds
3515
- * no egress entry for the requested contract.
3568
+ * Thrown when `POST /api/invoke` fails at the transport or HTTP
3569
+ * layer (network failure, timeout, non-2xx status). Contract-level errors
3570
+ * the node returns as a 2xx JSON error value are NOT wrapped here — they
3571
+ * flow through {@link parseContractResponse}'s normal return, same as the
3572
+ * session `execute` path.
3573
+ *
3574
+ * The message is always one of a small set of fixed, generic strings — it
3575
+ * NEVER contains the raw api key, the response body text, or the
3576
+ * underlying network error's message: a server (or a
3577
+ * misbehaving intermediary) that echoes the key or other secrets back in
3578
+ * an error body must not be able to leak them through this error's
3579
+ * message.
3516
3580
  */
3517
- interface AgentEgressGetResponse {
3518
- egress: AgentEgressEntry | null;
3519
- }
3520
- /** Runtime guard for {@link AgentEgressGetResponse}. */
3521
- declare function isAgentEgressGetResponse(value: unknown): value is AgentEgressGetResponse;
3522
- /** Response for `org-role-assignments-get`. */
3523
- interface RoleAssignmentsResponse {
3524
- /** Echoed back so callers don't need to track which request this answers. */
3525
- grantee_did: string;
3526
- /** The grantee's assigned role ids (empty when none). */
3527
- roles: string[];
3581
+ declare class InvokeError extends T3nError {
3582
+ readonly status?: number | undefined;
3583
+ constructor(message: string, status?: number | undefined);
3528
3584
  }
3529
- /** Shallow runtime guard for {@link RoleAssignmentsResponse}. */
3530
- declare function isRoleAssignmentsResponse(value: unknown): value is RoleAssignmentsResponse;
3531
3585
  /**
3532
- * Input for `listAgents` — the org plus optional pagination. Omit both `cursor`
3533
- * and `limit` for the first page at the default limit; pass a previous
3534
- * response's `next_cursor` back as `cursor` to fetch the following page.
3586
+ * Execute a `z:` contract as an org agent, authenticating with an opaque
3587
+ * API key — one request, no handshake, no session.
3588
+ *
3589
+ * @param opts - baseUrl, apiKey, and the wire request to execute
3590
+ * @param schema - optional validator applied to the decoded result (e.g. a
3591
+ * zod schema); anything exposing `.parse(value)` is accepted, same as
3592
+ * {@link T3nClient.executeAndDecode}
3593
+ * @returns the contract's decoded result, typed as `T`
3594
+ * @throws {InvokeError} if `baseUrl` is insecure, on a network
3595
+ * failure/timeout, or on a non-2xx response
3596
+ * @throws {ContractResponseError} if the node returns a 2xx with a body
3597
+ * that is not valid JSON
3598
+ */
3599
+ declare function invoke<T = unknown>(opts: InvokeOptions, schema?: ContractResponseSchema<T>): Promise<T>;
3600
+ /**
3601
+ * Transport options shared by the keyed discovery reads. Mirrors the transport
3602
+ * half of {@link InvokeOptions} (no `request`; the operation params are the
3603
+ * second argument of each read). Same HTTPS + secret-hygiene rules as `invoke`.
3535
3604
  */
3536
- interface ListAgentsInput {
3537
- orgDid: string;
3538
- /** Opaque cursor from a previous response's `next_cursor`. */
3539
- cursor?: string;
3540
- /** Maximum agents to return in this page. */
3541
- limit?: number;
3605
+ interface DiscoverOptions {
3606
+ /**
3607
+ * RPC base URL of the T3n node, e.g. `https://node.example.com`. Must be
3608
+ * `https:` unless the host is a local-dev loopback — see
3609
+ * {@link InvokeOptions.baseUrl}.
3610
+ */
3611
+ baseUrl: string;
3612
+ /**
3613
+ * The agent's opaque API key (`t3n_key_<...>`), relayed verbatim in the
3614
+ * `X-T3N-Api-Key` header. Never logged and never interpolated into any
3615
+ * error this module throws.
3616
+ */
3617
+ apiKey: string;
3618
+ /** Fetch timeout in ms. Defaults to 30s, matching {@link invoke}. */
3619
+ timeoutMs?: number;
3542
3620
  }
3543
3621
  /**
3544
- * One org-owned agent in a {@link ListAgentsResponse}: the agent's DID, its
3545
- * display name, and the number of distinct contracts it can access via a direct
3546
- * grant. Mirrors the org-data `AgentSummary` wire shape. The name comes from the
3547
- * agent's private card (falling back to the DID), so the FE no longer needs to
3548
- * fetch each `public:agent_cards` entry to render the roster.
3622
+ * `whoami` — resolve the DID the relayed key maps to. The node never
3623
+ * trusts a caller-supplied DID; this is the relay's sole DID source.
3624
+ *
3625
+ * @throws {InvokeError} if `baseUrl` is insecure, on a network failure/timeout,
3626
+ * or on a non-2xx response
3549
3627
  */
3550
- interface AgentSummary {
3551
- /** The agent's DID (`did:t3n:<40-hex>`). */
3552
- did: string;
3553
- /** The agent's display name, from its private card (DID when unavailable). */
3554
- name: string;
3555
- /** Count of distinct contracts the agent holds a direct grant on. */
3556
- contract_count: number;
3557
- }
3558
- /** Response for `org-data-list-agents`. */
3559
- interface ListAgentsResponse {
3560
- /** One PAGE of the org's org-owned agents, sorted by DID. */
3561
- agents: AgentSummary[];
3562
- /** Opaque cursor for the next page; absent on the last page. */
3563
- next_cursor?: string;
3564
- }
3565
- /** A human member's org role. The closed wire domain of {@link HumanMember}. */
3566
- type MemberRole = "admin" | "member";
3628
+ declare function discoverWhoami(opts: DiscoverOptions): Promise<WhoamiResult>;
3567
3629
  /**
3568
- * Input for `listHumanMembers` — the org plus optional pagination. Omit both
3569
- * `cursor` and `limit` for the first page at the default limit; pass a previous
3570
- * response's `next_cursor` back as `cursor` to fetch the following page.
3630
+ * `contracts.list` — the keyed counterpart of {@link T3nClient.listContracts}.
3631
+ * Absent `params` (`{}`) lists the curated `core` contracts; `org` / `self`
3632
+ * scopes are discovery-grant gated server-side (R5 non-disclosive empty page).
3633
+ *
3634
+ * @throws {InvokeError} — see {@link discoverWhoami}
3571
3635
  */
3572
- interface ListHumanMembersInput {
3573
- orgDid: string;
3574
- /** Opaque cursor from a previous response's `next_cursor`. */
3575
- cursor?: string;
3576
- /** Maximum members to return in this page. */
3577
- limit?: number;
3578
- }
3636
+ declare function discoverListContracts(opts: DiscoverOptions, params?: ListContractsParams): Promise<ListContractsResult>;
3579
3637
  /**
3580
- * One direct human member: DID plus org role. No profile PII (name/email are
3581
- * out of scope and owned by `tee:user`). Mirrors the org-data `HumanMember`
3582
- * wire shape.
3638
+ * `delegation.check` — the keyed counterpart of
3639
+ * {@link T3nClient.checkDelegation}. Returns the `member_delegation ∩ org_delegation`
3640
+ * verdict for the acting agent (as itself, or for `params.pii_did`).
3641
+ *
3642
+ * @throws {InvokeError} — see {@link discoverWhoami}
3583
3643
  */
3584
- interface HumanMember {
3585
- /** The member's DID (`did:t3n:<40-hex>`). */
3586
- did: string;
3587
- /** The member's org role. */
3588
- role: MemberRole;
3589
- }
3590
- /** Response for `org-data-list-human-members`. */
3591
- interface ListHumanMembersResponse {
3592
- /** One PAGE of the org's direct human members, sorted by DID. */
3593
- members: HumanMember[];
3594
- /** Opaque cursor for the next page; absent on the last page. */
3595
- next_cursor?: string;
3596
- }
3597
- /** Shallow runtime guard for {@link ListHumanMembersResponse}. */
3598
- declare function isListHumanMembersResponse(value: unknown): value is ListHumanMembersResponse;
3599
- /** Shallow runtime guard for {@link ListAgentsResponse}. */
3600
- declare function isListAgentsResponse(value: unknown): value is ListAgentsResponse;
3601
- /** Response for `org-data-list`. */
3602
- interface DataListResponse {
3603
- /** Hex-encoded entry IDs for this page. */
3604
- entry_ids: string[];
3605
- /** Offset to pass for the next page. `null` when this is the last page. */
3606
- next_offset: number | null;
3607
- /** Total number of entries in the scope (across all pages). */
3608
- total: number;
3609
- }
3610
- /** Shallow runtime guard for {@link DataListResponse}. */
3611
- declare function isDataListResponse(value: unknown): value is DataListResponse;
3612
- /** Secret shape discriminator (mirrors the contract `SecretKind`). */
3613
- type SecretKind = "single_value" | "json";
3614
- /** Metadata common to every {@link SecretView} entry. */
3615
- interface SecretViewBase {
3616
- /** Secret name (the `(org, name)` key tail). */
3617
- name: string;
3618
- /** Monotonic version, bumped on each value rotation and ACL edit. */
3619
- version: number;
3620
- /** Unix seconds of the most recent write. */
3621
- updated_at_secs: number;
3622
- }
3644
+ declare function discoverCheckDelegation(opts: DiscoverOptions, params: GrantCheckParams): Promise<GrantCheckResult>;
3623
3645
  /**
3624
- * The redacted per-secret summary `org-secret-list` returns — a discriminated
3625
- * union on `kind`. The value is NEVER present: a single-value exposes only its
3626
- * last four characters and a json secret only its sorted top-level field names.
3646
+ * `describe.contract` — the authority-gated keyed describe read. Returns
3647
+ * `{ contract, version, descriptor }`: the resolved dispatch `version` (the
3648
+ * `scriptVersion` an {@link invoke} call needs) alongside the contract's full
3649
+ * descriptor document. Unlike the session/stdio public descriptor GET, the relay
3650
+ * path is membership-gated on the contract's owning org and returns a uniform
3651
+ * non-disclosive error for both "not found" and "not authorised"
3652
+ * (anti-enumeration).
3653
+ *
3654
+ * @throws {InvokeError} — see {@link discoverWhoami}
3627
3655
  */
3628
- type SecretView = (SecretViewBase & {
3629
- kind: "single_value";
3630
- /** Last four characters of the value (whole value when ≤ 4 chars). */
3631
- last4: string;
3632
- }) | (SecretViewBase & {
3633
- kind: "json";
3634
- /** Sorted top-level object field names (keys only, no values). */
3635
- field_names: string[];
3636
- });
3637
- /** Shallow runtime guard for {@link SecretView}. */
3638
- declare function isSecretView(value: unknown): value is SecretView;
3656
+ declare function discoverDescribeContract(opts: DiscoverOptions, params: DescribeContractParams): Promise<DescribeContractResult>;
3639
3657
  /**
3640
- * Full secret record returned by `org-secret-get` — the value IS included
3641
- * (the deliberate read-back path the READ axis exists for), along with all
3642
- * three ACLs.
3658
+ * `describe.function` — the authority-gated keyed describe read for a single
3659
+ * function. Returns `{ contract, version, descriptor }` with `descriptor` the
3660
+ * projected function entry. Same gating as {@link discoverDescribeContract}.
3661
+ *
3662
+ * @throws {InvokeError} — see {@link discoverWhoami}
3643
3663
  */
3644
- interface SecretRecord {
3645
- name: string;
3646
- kind: SecretKind;
3647
- /** The value as text: the scalar for a single-value, canonical JSON object for a json secret. */
3648
- value: string;
3649
- version: number;
3650
- /** READ axis — DIDs allowed to read the value back. */
3651
- reader_dids: string[];
3652
- /** READ axis — role ids allowed to read the value back. */
3653
- reader_roles: string[];
3654
- /** MANAGE axis — DIDs allowed to rotate the value. */
3655
- manager_dids: string[];
3656
- /** MANAGE axis — role ids allowed to rotate the value. */
3657
- manager_roles: string[];
3658
- /** USE axis — canonical contract ids allowed to have the value injected. */
3659
- contract_allowlist: string[];
3660
- created_at_secs: number;
3661
- updated_at_secs: number;
3662
- /** DID of the caller who last wrote the record. */
3663
- updated_by: string;
3664
- }
3665
- /** Shallow runtime guard for {@link SecretRecord}. */
3666
- declare function isSecretRecord(value: unknown): value is SecretRecord;
3667
- /** Response for `org-secret-list`: redacted per-kind views, no values. */
3668
- interface SecretListResponse {
3669
- secrets: SecretView[];
3670
- }
3671
- /** Shallow runtime guard for {@link SecretListResponse}. */
3672
- declare function isSecretListResponse(value: unknown): value is SecretListResponse;
3673
- /** Response for `org-data-get`. */
3674
- interface DataGetResponse {
3675
- entry_id: string;
3676
- /** Hex-encoded raw payload bytes. */
3677
- payload_hex: string;
3678
- }
3679
- /** Shallow runtime guard for {@link DataGetResponse}. */
3680
- declare function isDataGetResponse(value: unknown): value is DataGetResponse;
3664
+ declare function discoverDescribeFunction(opts: DiscoverOptions, params: DescribeFunctionParams): Promise<DescribeFunctionResult>;
3665
+
3681
3666
  /**
3682
- * Return shape of `agentCardGet` — composed client-side from the generic
3683
- * `org-data-get` read of the card's entry (there is no card-specific read
3684
- * operation on the contract). To check whether a public copy exists, probe
3685
- * the anonymous `GET /api/agent-card/{did}` endpoint.
3667
+ * Token fixed-point units (USDT-style 6 decimals).
3668
+ *
3669
+ * As of `tee:*` metering v2, every token amount on the wire —
3670
+ * {@link BalanceRow}'s `available`/`reserved`, {@link UsageEntry.amount},
3671
+ * and `total_supply` — is denominated in **base units**, where
3672
+ * `1 T3N token = `{@link BASE_UNITS_PER_TOKEN}` base units`. The node
3673
+ * meters the *actual* fractional cost of each operation (pro-rata by
3674
+ * bytes / byte-seconds / fuel) down to `1e-6` token, so amounts are
3675
+ * raw integers in base units, NOT whole tokens.
3676
+ *
3677
+ * The wire fields are left as raw base units (no silent rescaling — that
3678
+ * would lose precision for large balances and surprise callers doing
3679
+ * arithmetic). Use {@link formatTokens} to render a human "tokens"
3680
+ * string and {@link toBaseUnits} to convert a token figure back.
3681
+ *
3682
+ * ⚠️ Breaking vs. the pre-decimals SDK: a balance that used to read `5`
3683
+ * (whole tokens) now reads `5_000_000` (base units). Multiply existing
3684
+ * display code through {@link formatTokens}.
3686
3685
  */
3687
- interface AgentCardResponse {
3688
- /** The agent whose card this is (`did:t3n:<40-hex>`). */
3689
- agent_did: string;
3690
- /** The stored card JSON body, verbatim. */
3691
- card: string;
3692
- }
3693
- /** Shallow runtime guard for {@link AgentCardResponse}. */
3694
- declare function isAgentCardResponse(value: unknown): value is AgentCardResponse;
3686
+ /** Decimal places in a T3N token (fixed; mirrors the node constant). */
3687
+ declare const TOKEN_DECIMALS = 6;
3688
+ /** Base units per whole T3N token — `10 ** TOKEN_DECIMALS`. */
3689
+ declare const BASE_UNITS_PER_TOKEN = 1000000;
3695
3690
  /**
3696
- * Legacy direct-route org-data envelope shape retained for compatibility.
3691
+ * Render a base-unit amount as a human-readable token string, e.g.
3692
+ * `25_920_000 → "25.92"`, `1_000_000 → "1"`, `4768 → "0.004768"`.
3697
3693
  *
3698
- * This mirrors the removed `/api/user-contract/execute` body format from
3699
- * the transitional transport. New callers should use `OrgDataClient`,
3700
- * which now dispatches through authenticated `/api/rpc` +
3701
- * `action.execute` instead.
3694
+ * Trailing-zero fraction digits are trimmed; an integer amount renders
3695
+ * with no decimal point. Accepts `number` or `bigint`; for balances
3696
+ * above `Number.MAX_SAFE_INTEGER` prefer passing a `bigint`.
3702
3697
  */
3703
- interface OrgDataActionWire {
3704
- nonce: string;
3705
- user_did: string;
3706
- authenticator_id: string;
3707
- contract_id: string;
3708
- function: string;
3709
- args_hash: string;
3710
- expires_at_secs: number;
3711
- signature: string;
3712
- }
3698
+ declare function formatTokens(baseUnits: number | bigint): string;
3699
+ /**
3700
+ * Convert a whole-or-fractional token figure to base units (rounded to
3701
+ * the nearest base unit). E.g. `25.92 → 25_920_000`, `1 → 1_000_000`.
3702
+ */
3703
+ declare function toBaseUnits(tokens: number): number;
3713
3704
 
3714
3705
  /**
3715
3706
  * OrgDataClient — typed wrapper over the existing authenticated
@@ -3782,12 +3773,19 @@ interface SetWritersInput {
3782
3773
  scope: string;
3783
3774
  writers: string[];
3784
3775
  }
3785
- interface SetGrantsInput {
3776
+ /**
3777
+ * A grant to set via {@link OrgDataClient.setDelegation}. The per-grant
3778
+ * `contract_id` is injected by the SDK from the request `contractId` (the
3779
+ * contract sets it server-side regardless), so callers omit it — a read-back
3780
+ * {@link BoundGrant}, which carries `contract_id`, is still assignable.
3781
+ */
3782
+ type SetGrantInput = Omit<BoundGrant, "contract_id">;
3783
+ interface OrgDelegationSetInput {
3786
3784
  orgDid: string;
3787
3785
  contractId: string;
3788
- grants: UserGrant[];
3786
+ grants: SetGrantInput[];
3789
3787
  }
3790
- interface DeleteGrantsInput {
3788
+ interface OrgDelegationDeleteInput {
3791
3789
  orgDid: string;
3792
3790
  contractId: string;
3793
3791
  }
@@ -3796,9 +3794,9 @@ interface DeleteGrantsInput {
3796
3794
  * while executing one of the org's contracts (org-admin only).
3797
3795
  *
3798
3796
  * Egress ONLY — this confers no data authority. An agent needs BOTH this and a
3799
- * {@link OrgDataClient.setGrants} entry naming its own DID to do useful work:
3800
- * `setGrants` authorises the org data it may read, this authorises the hosts it
3801
- * may dial. No human `agent_auth` row is involved in either.
3797
+ * {@link OrgDataClient.setDelegation} entry naming its own DID to do useful work:
3798
+ * `setDelegation` authorises the org data it may read, this authorises the hosts it
3799
+ * may dial. No human delegation row is involved in either.
3802
3800
  *
3803
3801
  * Hosts are matched EXACTLY (lowercased). A scheme, port, path, or `*` wildcard
3804
3802
  * is rejected rather than stored as an entry that could never match.
@@ -3930,7 +3928,7 @@ interface DeleteScopeInput {
3930
3928
  interface PurgeOrgInput {
3931
3929
  orgDid: string;
3932
3930
  }
3933
- interface RemoveMemberGrantsInput {
3931
+ interface OrgRemoveMemberDelegationInput {
3934
3932
  orgDid: string;
3935
3933
  /** DID (`did:t3n:<40-hex>` or bare hex) to drop from every grant list. */
3936
3934
  memberDid: string;
@@ -3942,7 +3940,7 @@ interface WritersGetInput {
3942
3940
  orgDid: string;
3943
3941
  scope: string;
3944
3942
  }
3945
- interface GrantsGetInput {
3943
+ interface OrgDelegationGetInput {
3946
3944
  orgDid: string;
3947
3945
  contractId: string;
3948
3946
  }
@@ -4079,22 +4077,22 @@ declare class OrgDataClient {
4079
4077
  /** Delete a secret entirely (org-admin only). */
4080
4078
  secretDelete(input: SecretNameInput): Promise<MutationResponse>;
4081
4079
  /**
4082
- * Full replacement of the user-grant list for a contract.
4080
+ * Full replacement of the org's grant list for a contract.
4083
4081
  *
4084
4082
  * Passing an empty list removes the entry.
4085
4083
  */
4086
- setGrants(input: SetGrantsInput): Promise<MutationResponse>;
4084
+ setDelegation(input: OrgDelegationSetInput): Promise<MutationResponse>;
4087
4085
  /**
4088
4086
  * Delete the grant entry for a contract entirely.
4089
4087
  */
4090
- deleteGrants(input: DeleteGrantsInput): Promise<MutationResponse>;
4088
+ deleteDelegation(input: OrgDelegationDeleteInput): Promise<MutationResponse>;
4091
4089
  /**
4092
4090
  * Grant or replace the outbound host allow-list an org-owned agent may use
4093
4091
  * while executing one of the org's contracts (org-admin only).
4094
4092
  *
4095
4093
  * Full replacement for the `(agent, contract)` pair. Other contracts' egress
4096
4094
  * entries are untouched. See {@link SetAgentEgressInput} on why this is
4097
- * needed alongside {@link setGrants}.
4095
+ * needed alongside {@link setDelegation}.
4098
4096
  */
4099
4097
  setAgentEgress(input: SetAgentEgressInput): Promise<MutationResponse>;
4100
4098
  /**
@@ -4179,11 +4177,11 @@ declare class OrgDataClient {
4179
4177
  purgeOrg(input: PurgeOrgInput): Promise<MutationResponse>;
4180
4178
  /**
4181
4179
  * Detach-cascade grant sweep: drop `memberDid` from every
4182
- * one of the org's per-contract `UserGrant` lists. Authorised for an
4180
+ * one of the org's per-contract `BoundGrant` lists. Authorised for an
4183
4181
  * org-admin of the subject, or the member removing their own grants.
4184
4182
  * `deleted_entries` reports how many contract grant lists were rewritten.
4185
4183
  */
4186
- removeMemberGrants(input: RemoveMemberGrantsInput): Promise<MutationResponse>;
4184
+ removeMemberDelegation(input: OrgRemoveMemberDelegationInput): Promise<MutationResponse>;
4187
4185
  /** Read the policy metadata for an org (admin-only). */
4188
4186
  policyGet(input: PolicyGetInput): Promise<OrgPolicyMeta>;
4189
4187
  /**
@@ -4210,7 +4208,7 @@ declare class OrgDataClient {
4210
4208
  /** Read the writer list for a scope (admin-only). */
4211
4209
  writersGet(input: WritersGetInput): Promise<OrgWriters>;
4212
4210
  /** Read the grant list for a contract (admin-only). */
4213
- grantsGet(input: GrantsGetInput): Promise<OrgContractGrants>;
4211
+ getDelegation(input: OrgDelegationGetInput): Promise<OrgContractDelegation>;
4214
4212
  /**
4215
4213
  * List entry IDs for a scope (admin-only), paginated.
4216
4214
  *
@@ -4305,17 +4303,17 @@ declare class SessionOrgDataClient {
4305
4303
  secretList(input: SecretListInput): Promise<SecretView[]>;
4306
4304
  /** Mirrors {@link OrgDataClient.secretDelete}. */
4307
4305
  secretDelete(input: SecretNameInput): Promise<MutationResponse>;
4308
- /** Mirrors {@link OrgDataClient.setGrants}. */
4309
- setGrants(input: SetGrantsInput): Promise<MutationResponse>;
4310
- /** Mirrors {@link OrgDataClient.deleteGrants}. */
4311
- deleteGrants(input: DeleteGrantsInput): Promise<MutationResponse>;
4306
+ /** Mirrors {@link OrgDataClient.setDelegation}. */
4307
+ setDelegation(input: OrgDelegationSetInput): Promise<MutationResponse>;
4308
+ /** Mirrors {@link OrgDataClient.deleteDelegation}. */
4309
+ deleteDelegation(input: OrgDelegationDeleteInput): Promise<MutationResponse>;
4312
4310
  /**
4313
4311
  * Grant or replace the outbound host allow-list an org-owned agent may use
4314
4312
  * while executing one of the org's contracts (org-admin only).
4315
4313
  *
4316
4314
  * Full replacement for the `(agent, contract)` pair. Other contracts' egress
4317
4315
  * entries are untouched. See {@link SetAgentEgressInput} on why this is
4318
- * needed alongside {@link setGrants}.
4316
+ * needed alongside {@link setDelegation}.
4319
4317
  */
4320
4318
  setAgentEgress(input: SetAgentEgressInput): Promise<MutationResponse>;
4321
4319
  /**
@@ -4357,8 +4355,8 @@ declare class SessionOrgDataClient {
4357
4355
  deleteScope(input: DeleteScopeInput): Promise<MutationResponse>;
4358
4356
  /** Mirrors {@link OrgDataClient.purgeOrg}. */
4359
4357
  purgeOrg(input: PurgeOrgInput): Promise<MutationResponse>;
4360
- /** Mirrors {@link OrgDataClient.removeMemberGrants}. */
4361
- removeMemberGrants(input: RemoveMemberGrantsInput): Promise<MutationResponse>;
4358
+ /** Mirrors {@link OrgDataClient.removeMemberDelegation}. */
4359
+ removeMemberDelegation(input: OrgRemoveMemberDelegationInput): Promise<MutationResponse>;
4362
4360
  /** Mirrors {@link OrgDataClient.policyGet}. */
4363
4361
  policyGet(input: PolicyGetInput): Promise<OrgPolicyMeta>;
4364
4362
  /** Mirrors {@link OrgDataClient.policyView}. */
@@ -4367,8 +4365,8 @@ declare class SessionOrgDataClient {
4367
4365
  amIAdmin(input: PolicyGetInput): Promise<boolean>;
4368
4366
  /** Mirrors {@link OrgDataClient.writersGet}. */
4369
4367
  writersGet(input: WritersGetInput): Promise<OrgWriters>;
4370
- /** Mirrors {@link OrgDataClient.grantsGet}. */
4371
- grantsGet(input: GrantsGetInput): Promise<OrgContractGrants>;
4368
+ /** Mirrors {@link OrgDataClient.getDelegation}. */
4369
+ getDelegation(input: OrgDelegationGetInput): Promise<OrgContractDelegation>;
4372
4370
  /** Mirrors {@link OrgDataClient.dataList}. */
4373
4371
  dataList(input: DataListInput): Promise<DataListResponse>;
4374
4372
  /** Mirrors {@link OrgDataClient.dataGet}. */
@@ -4398,7 +4396,7 @@ declare function createOrgDataClientFromSession(t3n: T3nClient, baseUrl: string)
4398
4396
  *
4399
4397
  * Envelope-free authorisation removed the per-call delegation
4400
4398
  * credential and envelope entirely: authority is now the standing on-chain
4401
- * `agent_auth` ∩ `UserGrant` intersection the host re-reads every call, and
4399
+ * `member_delegation` ∩ `org_delegation` intersection the host re-reads every call, and
4402
4400
  * every payroll call emits the plain Direct wire variant (`{ request }`).
4403
4401
  * What remains here is the request body shape, its canonical defaults, and
4404
4402
  * the base64url / DID helpers callers still need.
@@ -4412,7 +4410,7 @@ declare function createOrgDataClientFromSession(t3n: T3nClient, baseUrl: string)
4412
4410
  /**
4413
4411
  * Canonical sorted run-pipeline function surface for the z-payroll contract
4414
4412
  * (`z:<org-tid>:payroll`). Sorted ascending. Mirrors `Z_PAYROLL_RUN_FUNCTIONS`
4415
- * in the Trinity harness; used as the `functions` set for agent-auth grants
4413
+ * in the Trinity harness; used as the `functions` set for delegation grants
4416
4414
  * and `check-delegation` queries.
4417
4415
  */
4418
4416
  declare const Z_PAYROLL_RUN_FUNCTIONS: readonly ["compute-payroll", "execute-disbursement", "finalize-audit", "submit-escalations", "validate-credentials"];
@@ -4617,7 +4615,7 @@ declare function stringToBytes(str: string): Uint8Array;
4617
4615
  */
4618
4616
  declare function bytesToString(bytes: Uint8Array): string;
4619
4617
 
4620
- declare function getScriptVersion(rpcUrl: string, scriptName: string): Promise<string>;
4618
+ declare function getContractVersion(rpcUrl: string, contractId: string): Promise<string>;
4621
4619
 
4622
4620
  /**
4623
4621
  * Secret redaction utilities for T3n SDK
@@ -4659,8 +4657,8 @@ declare function redactSecretsFromJson(jsonString: string): string;
4659
4657
  *
4660
4658
  * Predicates are intentionally shallow — they validate the immediate
4661
4659
  * top-level structure (object kind, presence/type of leading fields)
4662
- * but do not deeply validate nested elements (e.g. each `UserGrant`
4663
- * inside `OrgContractGrants.grants`). Deep validation would be brittle
4660
+ * but do not deeply validate nested elements (e.g. each `BoundGrant`
4661
+ * inside `OrgContractDelegation.grants`). Deep validation would be brittle
4664
4662
  * against benign contract additions; shallow guards catch the failure
4665
4663
  * modes that actually surface as runtime crashes (null/string/missing
4666
4664
  * top-level field).
@@ -4946,7 +4944,7 @@ interface TenantBaseClient {
4946
4944
  }
4947
4945
  interface TenantClientConfig {
4948
4946
  environment?: TenantSdkEnvironment;
4949
- /** Node URL for `getScriptVersion` during business contract execution. Falls back to `baseUrl`. */
4947
+ /** Node URL for `getContractVersion` during business contract execution. Falls back to `baseUrl`. */
4950
4948
  endpoint?: string;
4951
4949
  /**
4952
4950
  * Authenticated base client the TenantClient dispatches RPCs through.
@@ -4963,7 +4961,7 @@ interface TenantClientConfig {
4963
4961
  t3n?: TenantBaseClient;
4964
4962
  baseUrl?: string;
4965
4963
  tenantDid?: string;
4966
- tenantScriptName?: string;
4964
+ tenantContractId?: string;
4967
4965
  }
4968
4966
  type TenantStatus = "pending" | "active" | "suspended";
4969
4967
  interface TenantMeResponse {
@@ -5413,5 +5411,5 @@ declare function tenantDidHex(tenantDid: string): string;
5413
5411
  declare function validateTail(tail: string): string;
5414
5412
  declare function canonicalTenantName(tenantDid: string, tail: string): string;
5415
5413
 
5416
- export { AGENT_CARDS_SCOPE, AuthMethod, AuthenticationError, BASE_UNITS_PER_TOKEN, ContractResponseError, DEFAULT_ENVIRONMENT, DEFAULT_INDIVIDUAL_THRESHOLD_CENTS, DEFAULT_KYC_POLL_CADENCE, HandshakeError, HttpTransport, InvokeError, KycStatusTimeoutError, LogLevel, MockTransport, NODE_URLS, OrgDataClient, OtpRateLimitedError, RpcError, SessionExpiredError, SessionOrgDataClient, SessionStateError, SessionStatus, SessionUsageReportClient, T3nClient, T3nConfigError, T3nError, TERMINAL_KYC_STATUSES, TOKEN_DECIMALS, TenantClient, TenantContractsNamespace, TenantMapsNamespace, TenantNamespace, TenantSdkValidationError, TenantTokenNamespace, UnsupportedTenantSdkOperationError, UserUpsertError, WasmError, WireEncodingError, Z_PAYROLL_AUDIT_READ_FUNCTIONS, Z_PAYROLL_RUN_FUNCTIONS, _b64uEncode, assertShape, b64uDecodeStrict, b64uEncodeBytes, buildSecretWriteArgs, bytesToString, canonicalTenantName, clearKeyCache, clearManifestVersionFloor, compactDidFromBytes, createDefaultHandlers, createEmailOtpAuthInput, createEthAuthInput, createLogger, createMlKemPublicKeyHandler, createOidcAuthInput, createOrgDataClientFromSession, createRandomHandler, createUsageReportClientFromSession, createWorkloadAuthInput, decodeWasmErrorMessage, deriveAgentCardEntryId, discoverCheckDelegation, discoverDescribeContract, discoverDescribeFunction, discoverListContracts, discoverWhoami, eth_get_address, extractWasmError, fetchDkgAttestation, fetchMlKemPublicKey, fetchTrustedManifest, formatTokens, generateRandomString, generateUUID, getEnvironment, getEnvironmentName, getGlobalLogLevel, getLogger, getNodeUrl, getScriptVersion, invoke, isAgentCardResponse, isAgentEgressGetResponse, isDataGetResponse, isDataListResponse, isListAgentsResponse, isListHumanMembersResponse, isMutationResponse, isObject, isOrgAdminStatus, isOrgContractGrants, isOrgPolicyMeta, isOrgPolicyView, isOrgUsageReport, isOrgWriters, isRoleAssignmentsResponse, isRoleGetResponse, isSecretListResponse, isSecretRecord, isSecretView, isUnsafeTrustServer, loadConfig, loadWasmComponent, manifestToTrustAnchor, maskKeyMaterial, mergeAgentAuthEntries, mergeDiscoverDids, metamask_get_address, metamask_sign, parseAgentAuthGet, parseAgentAuthPolicy, parseContractResponse, redactSecrets, redactSecretsFromJson, requestToWire, setEnvironment, setGlobalLogLevel, setNodeUrl, stringToBytes, tenantDidHex, toAgentAuthUpdateWire, toBaseUnits, validateConfig, validateTail, verifyDkgAttestation, verifyManifestSignature, verifyTdxQuote };
5417
- export type { ActivityCallerType, ActivityEntry, ActivityOutcome, ActivityReport, AdmitForOrgOptions, AgentAuthEntry, AgentAuthMergeResult, AgentAuthPolicy, AgentAuthScriptGrant, AgentAuthUpdateInput, AgentCardRefInput, AgentCardResponse, AgentCardSetInput, AgentEgressEntry, AgentEgressGetResponse, AgentEgressRefInput, AgentSummary, AssignRolesInput, AuthInput, BalanceRow, ChargeReason, ClientAuth, ClientHandshake, ConfigValidationResult, ContractDescriptorDocument, ContractDescriptorFacets, ContractExecuteInput, ContractKind, ContractLifecycleStatus, ContractListDetailedOptions, ContractListDetailedPage, ContractPublishInput, ContractRegisterResult, ContractResponseSchema, ContractSetDescriptorInput, CreatePolicyInput, DataGetInput, DataGetResponse, DataListInput, DataListResponse, DelegationGrantKind, DelegationGrantRef, DeleteDataInput, DeleteGrantsInput, DeleteScopeInput, DescribeContractParams, DescribeContractResult, DescribeFunctionParams, DescribeFunctionResult, DetailedContract, Did, Direction, DiscoverOptions, DkgAttestation, DkgVerifyResult, EmailOtpAuthInput, EmailOtpCredentials, Environment, EthAuthInput, ExecuteBusinessContractOptions, ExecuteOrgDataActionOptions, FetchTrustedManifestOptions, FunctionDescriptorEntry, GetActivityLogOptions, GetUsageOptions, GrantCheckParams, GrantCheckResult, GranteeInput, GrantsGetInput, GuestToHostHandler, GuestToHostHandlers, HandshakeResult, HumanMember, InvokeOptions, InvokeRequest, JsonRpcRequest, JsonRpcResponse, KycPollCadence, KycPollOptions, KycStatus, KycStatusKind, ListAgentsInput, ListAgentsResponse, ListContractsParams, ListContractsResult, ListContractsScope, ListHumanMembersInput, ListHumanMembersResponse, ListedContract, Logger, MapCreateInput, MapLifecycleStatus, MapResponse, MapUpdateInput, MapVisibility, MemberRole, MutationResponse, OidcAuthInput, OidcCredentials, OrgAdminStatus, OrgContractGrants, OrgDataActionWire, OrgDataClientOptions, OrgPolicyMeta, OrgPolicyView, OrgUsageReport, OrgUsageReportInput, OrgWriters, OtpChannel, OtpMergeSuggestion, OtpRequestInput, OtpRequestResult, OtpVerifyInput, OtpVerifyResult, PayrollRunRequest, PeerQuoteResult, PolicyGetInput, PurgeOrgInput, QuoteVerifyResult, ReaderSet, RemoveMemberGrantsInput, RoleAssignments, RoleAssignmentsResponse, RoleDefinition, RoleGetResponse, RoleGrant, RoleIdInput, SdkConfig, SecretKind, SecretListInput, SecretListResponse, SecretNameInput, SecretRecord, SecretSetValueInput, SecretView, SecretWriteInput, SessionCrypto, SessionId, SetAgentEgressInput, SetGrantsInput, SetRoleInput, SetWritersInput, SignedTrustManifest, StringEncoding, SubmitUserInputArgs, SubmitUserInputResult, T3nClientConfig, TenantAdmitProjection, TenantAdmitStatus, TenantBaseClient, TenantClientConfig, TenantContractExecuteInput, TenantContractPublishInput, TenantContractSetDescriptorInput, TenantExecutionSession, TenantMapCreateInput, TenantMapUpdatePatch, TenantMeResponse, TenantSdkEnvironment, TenantSelfAdmitResult, TenantStatus, TenantTargetOptions, TokenTxKind, Transport, TrustAnchor, TrustAnchorOrUnsafe, TrustAnchorSource, TrustManifestPayload, UnassignRolesInput, UnsafeTrustServer, UpdateMetaInput, UsageEntry, UsagePage, UsageReportSignature, UserGrant, UserInputProfile, UserUpsertErrorKind, WasmComponent, WasmNextResult, WhoamiResult, WireBlock, WorkloadAuthInput, WriteDataInput, WriterSet, WritersGetInput };
5414
+ export { AGENT_CARDS_SCOPE, AuthMethod, AuthenticationError, BASE_UNITS_PER_TOKEN, ContractResponseError, DEFAULT_ENVIRONMENT, DEFAULT_INDIVIDUAL_THRESHOLD_CENTS, DEFAULT_KYC_POLL_CADENCE, HandshakeError, HttpTransport, InvokeError, KycStatusTimeoutError, LogLevel, MockTransport, NODE_URLS, OrgDataClient, OtpRateLimitedError, RpcError, SessionExpiredError, SessionOrgDataClient, SessionStateError, SessionStatus, SessionUsageReportClient, T3nClient, T3nConfigError, T3nError, TERMINAL_KYC_STATUSES, TOKEN_DECIMALS, TenantClient, TenantContractsNamespace, TenantMapsNamespace, TenantNamespace, TenantSdkValidationError, TenantTokenNamespace, UnsupportedTenantSdkOperationError, UserUpsertError, WasmError, WireEncodingError, Z_PAYROLL_AUDIT_READ_FUNCTIONS, Z_PAYROLL_RUN_FUNCTIONS, _b64uEncode, assertShape, b64uDecodeStrict, b64uEncodeBytes, buildSecretWriteArgs, bytesToString, canonicalTenantName, clearKeyCache, clearManifestVersionFloor, compactDidFromBytes, createDefaultHandlers, createEmailOtpAuthInput, createEthAuthInput, createLogger, createMlKemPublicKeyHandler, createOidcAuthInput, createOrgDataClientFromSession, createRandomHandler, createUsageReportClientFromSession, createWorkloadAuthInput, decodeWasmErrorMessage, deriveAgentCardEntryId, discoverCheckDelegation, discoverDescribeContract, discoverDescribeFunction, discoverListContracts, discoverWhoami, eth_get_address, extractWasmError, fetchDkgAttestation, fetchMlKemPublicKey, fetchTrustedManifest, formatTokens, generateRandomString, generateUUID, getContractVersion, getEnvironment, getEnvironmentName, getGlobalLogLevel, getLogger, getNodeUrl, invoke, isAgentCardResponse, isAgentEgressGetResponse, isDataGetResponse, isDataListResponse, isListAgentsResponse, isListHumanMembersResponse, isMutationResponse, isObject, isOrgAdminStatus, isOrgContractDelegation, isOrgPolicyMeta, isOrgPolicyView, isOrgUsageReport, isOrgWriters, isRoleAssignmentsResponse, isRoleGetResponse, isSecretListResponse, isSecretRecord, isSecretView, isUnsafeTrustServer, loadConfig, loadWasmComponent, manifestToTrustAnchor, maskKeyMaterial, mergeDiscoverDids, mergeGrants, metamask_get_address, metamask_sign, parseContractResponse, parseMemberDelegationDoc, redactSecrets, redactSecretsFromJson, requestToWire, setEnvironment, setGlobalLogLevel, setNodeUrl, stringToBytes, tenantDidHex, toBaseUnits, validateConfig, validateTail, verifyDkgAttestation, verifyManifestSignature, verifyTdxQuote };
5415
+ export type { ActivityCallerType, ActivityEntry, ActivityOutcome, ActivityReport, AdmitForOrgOptions, AgentCardRefInput, AgentCardResponse, AgentCardSetInput, AgentEgressEntry, AgentEgressGetResponse, AgentEgressRefInput, AgentSummary, AssignRolesInput, AuthInput, BalanceRow, BoundGrant, ChargeReason, ClientAuth, ClientHandshake, ConfigValidationResult, ContractDescriptorDocument, ContractDescriptorFacets, ContractExecuteInput, ContractKind, ContractLifecycleStatus, ContractListDetailedOptions, ContractListDetailedPage, ContractPublishInput, ContractRegisterResult, ContractResponseSchema, ContractSetDescriptorInput, CreatePolicyInput, DataGetInput, DataGetResponse, DataListInput, DataListResponse, DelegationGrantKind, DelegationGrantRef, DeleteDataInput, DeleteScopeInput, DescribeContractParams, DescribeContractResult, DescribeFunctionParams, DescribeFunctionResult, DetailedContract, Did, Direction, DiscoverOptions, DkgAttestation, DkgVerifyResult, EmailOtpAuthInput, EmailOtpCredentials, Environment, EthAuthInput, ExecuteBusinessContractOptions, ExecuteOrgDataActionOptions, FetchTrustedManifestOptions, FunctionDescriptorEntry, GetActivityLogOptions, GetUsageOptions, GrantCheckParams, GrantCheckResult, GranteeInput, GrantsMergeResult, GuestToHostHandler, GuestToHostHandlers, HandshakeResult, HumanMember, InvokeOptions, InvokeRequest, JsonRpcRequest, JsonRpcResponse, KycPollCadence, KycPollOptions, KycStatus, KycStatusKind, ListAgentsInput, ListAgentsResponse, ListContractsParams, ListContractsResult, ListContractsScope, ListHumanMembersInput, ListHumanMembersResponse, ListedContract, Logger, MapCreateInput, MapLifecycleStatus, MapResponse, MapUpdateInput, MapVisibility, MemberDelegationDoc, MemberRole, MutationResponse, OidcAuthInput, OidcCredentials, OrgAdminStatus, OrgContractDelegation, OrgDataActionWire, OrgDataClientOptions, OrgDelegationDeleteInput, OrgDelegationGetInput, OrgDelegationSetInput, OrgPolicyMeta, OrgPolicyView, OrgRemoveMemberDelegationInput, OrgUsageReport, OrgUsageReportInput, OrgWriters, OtpChannel, OtpMergeSuggestion, OtpRequestInput, OtpRequestResult, OtpVerifyInput, OtpVerifyResult, PayrollRunRequest, PeerQuoteResult, PolicyGetInput, PurgeOrgInput, QuoteVerifyResult, ReaderSet, RoleAssignments, RoleAssignmentsResponse, RoleDefinition, RoleGetResponse, RoleGrant, RoleIdInput, SdkConfig, SecretKind, SecretListInput, SecretListResponse, SecretNameInput, SecretRecord, SecretSetValueInput, SecretView, SecretWriteInput, SessionCrypto, SessionId, SetAgentEgressInput, SetRoleInput, SetWritersInput, SignedTrustManifest, StringEncoding, SubmitUserInputArgs, SubmitUserInputResult, T3nClientConfig, TenantAdmitProjection, TenantAdmitStatus, TenantBaseClient, TenantClientConfig, TenantContractExecuteInput, TenantContractPublishInput, TenantContractSetDescriptorInput, TenantExecutionSession, TenantMapCreateInput, TenantMapUpdatePatch, TenantMeResponse, TenantSdkEnvironment, TenantSelfAdmitResult, TenantStatus, TenantTargetOptions, TokenTxKind, Transport, TrustAnchor, TrustAnchorOrUnsafe, TrustAnchorSource, TrustManifestPayload, UnassignRolesInput, UnsafeTrustServer, UpdateMetaInput, UsageEntry, UsagePage, UsageReportSignature, UserInputProfile, UserUpsertErrorKind, Validity, WasmComponent, WasmNextResult, WhoamiResult, WireBlock, WorkloadAuthInput, WriteDataInput, WriterSet, WritersGetInput };