@vorim/sdk 3.2.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +143 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +185 -2
- package/dist/index.d.ts +185 -2
- package/dist/index.js +143 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -75,6 +75,76 @@ interface AuditEventInput {
|
|
|
75
75
|
* is `"v1"`; you can also pass it on a per-event basis.
|
|
76
76
|
*/
|
|
77
77
|
canonical_form?: 'v0' | 'v1';
|
|
78
|
+
/**
|
|
79
|
+
* Per-event delegation context (VAIP -02 § 6). Populated by the
|
|
80
|
+
* server when the emitting agent is acting via a delegation chain;
|
|
81
|
+
* callers may also set these manually for events recorded outside
|
|
82
|
+
* the standard delegation flow. v1 signatures cover these fields.
|
|
83
|
+
*/
|
|
84
|
+
on_behalf_of?: string;
|
|
85
|
+
delegator_agent_id?: string;
|
|
86
|
+
delegation_chain_id?: string;
|
|
87
|
+
delegation_depth?: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Claims structure for one VAIP -02 § 5 delegation link.
|
|
91
|
+
*
|
|
92
|
+
* Each delegation step in a chain is one of these objects, RFC 8785 JCS
|
|
93
|
+
* canonicalised and Ed25519-signed by the delegator. Mirrors the same
|
|
94
|
+
* type in `@vorim/shared-types`; duplicated here so the SDK ships zero
|
|
95
|
+
* runtime dependencies. Byte-equivalence with the shared definition is
|
|
96
|
+
* enforced by the cross-language parity script.
|
|
97
|
+
*/
|
|
98
|
+
interface DelegationLinkClaims {
|
|
99
|
+
v: 0;
|
|
100
|
+
type: 'vaip-delegation-link';
|
|
101
|
+
chain_id: string;
|
|
102
|
+
depth: number;
|
|
103
|
+
delegator: string;
|
|
104
|
+
delegate: string;
|
|
105
|
+
scopes: string[];
|
|
106
|
+
max_chain_depth: number;
|
|
107
|
+
valid_from: string;
|
|
108
|
+
valid_until: string | null;
|
|
109
|
+
parent_link_hash: string | null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* One step in an agent-to-agent identity delegation chain (VAIP -02 § 5).
|
|
113
|
+
*
|
|
114
|
+
* Returned by {@link VorimSDK.delegateToAgent} and the listing endpoints.
|
|
115
|
+
*/
|
|
116
|
+
interface AgentDelegationRecord {
|
|
117
|
+
/** Internal row id. */
|
|
118
|
+
id: string;
|
|
119
|
+
/** Public chain identifier (format `chain_<32hex>`). Stamped on
|
|
120
|
+
* every audit event in this chain. */
|
|
121
|
+
publicChainId: string;
|
|
122
|
+
/** Organisation id. */
|
|
123
|
+
orgId: string;
|
|
124
|
+
/** Internal DB id of the delegator agent. */
|
|
125
|
+
delegatorAgentId: string;
|
|
126
|
+
/** Internal DB id of the delegate agent. */
|
|
127
|
+
delegateAgentId: string;
|
|
128
|
+
/** Public agent_id of the delegator (e.g. agid_acme_abc). */
|
|
129
|
+
delegatorAgentPublicId: string;
|
|
130
|
+
/** Public agent_id of the delegate. */
|
|
131
|
+
delegateAgentPublicId: string;
|
|
132
|
+
/** Scopes the delegate may exercise. */
|
|
133
|
+
scopesDelegated: string[];
|
|
134
|
+
/** How many further hops the delegate is permitted. */
|
|
135
|
+
maxChainDepth: number;
|
|
136
|
+
/** This step's depth from the root (root delegator step = 1). */
|
|
137
|
+
currentDepth: number;
|
|
138
|
+
/** Active / suspended / revoked / expired. */
|
|
139
|
+
status: 'active' | 'suspended' | 'revoked' | 'expired';
|
|
140
|
+
/** Parent delegation row (null for the root of an identity chain). */
|
|
141
|
+
parentDelegationId: string | null;
|
|
142
|
+
/** Public agent_id of the root principal of this chain. */
|
|
143
|
+
onBehalfOf: string;
|
|
144
|
+
/** ISO8601 creation timestamp. */
|
|
145
|
+
createdAt: string;
|
|
146
|
+
/** Optional ISO8601 expiry. */
|
|
147
|
+
validUntil: string | null;
|
|
78
148
|
}
|
|
79
149
|
interface TrustRecord {
|
|
80
150
|
agent_id: string;
|
|
@@ -302,6 +372,14 @@ declare class VorimSDK {
|
|
|
302
372
|
* link to the old chain.
|
|
303
373
|
*/
|
|
304
374
|
private lastEventHash;
|
|
375
|
+
/**
|
|
376
|
+
* Per-agent monotonic counter incremented by `forgetAgentKey`. An
|
|
377
|
+
* emit that started before `forgetAgentKey` ran will read a stale
|
|
378
|
+
* epoch and refuse to repopulate the chain tail, preventing the
|
|
379
|
+
* revoked agent from inheriting a new lastEventHash from the
|
|
380
|
+
* in-flight emit that the lock was holding.
|
|
381
|
+
*/
|
|
382
|
+
private agentForgetEpoch;
|
|
305
383
|
/**
|
|
306
384
|
* Per-agent emit promise. Each new emit awaits the previous one so
|
|
307
385
|
* the chain is constructed in order. Concurrent emits to the same
|
|
@@ -392,6 +470,97 @@ declare class VorimSDK {
|
|
|
392
470
|
* Revoke a specific permission scope from an agent.
|
|
393
471
|
*/
|
|
394
472
|
revokePermission(agentId: string, scope: PermissionScope): Promise<any>;
|
|
473
|
+
/**
|
|
474
|
+
* Delegate the right to act on this agent's behalf to another agent
|
|
475
|
+
* in the same org, with a strict subset of this agent's scopes.
|
|
476
|
+
*
|
|
477
|
+
* Multi-hop chains are supported up to depth 32. Scope subset is
|
|
478
|
+
* enforced at every hop. Audit events emitted by the delegate carry
|
|
479
|
+
* the chain context (`on_behalf_of`, `delegator_agent_id`,
|
|
480
|
+
* `delegation_chain_id`, `delegation_depth`) so a verifier walking
|
|
481
|
+
* the bundle can reconstruct the full chain.
|
|
482
|
+
*
|
|
483
|
+
* @example
|
|
484
|
+
* ```ts
|
|
485
|
+
* const chain = await vorim.delegateToAgent('agid_parent_abc', {
|
|
486
|
+
* delegate_agent_id: 'agid_child_xyz',
|
|
487
|
+
* scopes_delegated: ['agent:read', 'agent:execute'],
|
|
488
|
+
* max_chain_depth: 1, // delegate may make ONE further hop
|
|
489
|
+
* valid_until: '2026-12-31T00:00:00Z',
|
|
490
|
+
* });
|
|
491
|
+
* console.log(chain.public_chain_id); // chain_<hex>
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
delegateToAgent(delegatorAgentId: string, input: {
|
|
495
|
+
delegate_agent_id: string;
|
|
496
|
+
scopes_delegated: PermissionScope[];
|
|
497
|
+
max_chain_depth?: number;
|
|
498
|
+
valid_until?: string;
|
|
499
|
+
/**
|
|
500
|
+
* Optional Ed25519-signed delegation link (VAIP -02 § 5). When
|
|
501
|
+
* provided, the server verifies the signature against the
|
|
502
|
+
* delegator's stored public key, persists alongside the chain
|
|
503
|
+
* row, and exports it in bundle delegation_tokens so the chain
|
|
504
|
+
* is offline-verifiable by `@vorim/verify`. Compute via
|
|
505
|
+
* {@link signDelegationLink} or set manually if signing
|
|
506
|
+
* elsewhere.
|
|
507
|
+
*/
|
|
508
|
+
signed_link?: {
|
|
509
|
+
claims: DelegationLinkClaims;
|
|
510
|
+
signature: string;
|
|
511
|
+
};
|
|
512
|
+
}): Promise<AgentDelegationRecord>;
|
|
513
|
+
/**
|
|
514
|
+
* Sign a delegation link with the delegator's private key. Returns
|
|
515
|
+
* the signed link in the shape accepted by `delegateToAgent`'s
|
|
516
|
+
* `signed_link` field.
|
|
517
|
+
*
|
|
518
|
+
* The signature is Ed25519 over the RFC 8785 JCS-canonical bytes of
|
|
519
|
+
* the claims object. Same algorithm the server and `@vorim/verify`
|
|
520
|
+
* use for verification.
|
|
521
|
+
*
|
|
522
|
+
* Use this when the delegator's private key is in this SDK's
|
|
523
|
+
* keyring (i.e. set via `register()` or `useAgentKey()`).
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```ts
|
|
527
|
+
* const signed = await vorim.signDelegationLink({
|
|
528
|
+
* v: 0,
|
|
529
|
+
* type: 'vaip-delegation-link',
|
|
530
|
+
* chain_id: 'chain_abc', // server returns this on first delegation
|
|
531
|
+
* depth: 1,
|
|
532
|
+
* delegator: 'agid_parent',
|
|
533
|
+
* delegate: 'agid_child',
|
|
534
|
+
* scopes: ['agent:read', 'agent:execute'],
|
|
535
|
+
* max_chain_depth: 1,
|
|
536
|
+
* valid_from: new Date().toISOString(),
|
|
537
|
+
* valid_until: null,
|
|
538
|
+
* parent_link_hash: null,
|
|
539
|
+
* });
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
signDelegationLink(claims: DelegationLinkClaims): Promise<{
|
|
543
|
+
claims: DelegationLinkClaims;
|
|
544
|
+
signature: string;
|
|
545
|
+
}>;
|
|
546
|
+
/**
|
|
547
|
+
* List active identity-chain entries this agent participates in
|
|
548
|
+
* (either as delegator or delegate). Useful for showing the current
|
|
549
|
+
* delegation graph in an admin UI.
|
|
550
|
+
*/
|
|
551
|
+
listAgentDelegations(agentId: string): Promise<AgentDelegationRecord[]>;
|
|
552
|
+
/**
|
|
553
|
+
* Walk a delegation chain by its public id. Returns the full chain
|
|
554
|
+
* in depth order.
|
|
555
|
+
*/
|
|
556
|
+
getDelegationChain(agentId: string, chainId: string): Promise<AgentDelegationRecord[]>;
|
|
557
|
+
/**
|
|
558
|
+
* Revoke this agent's delegation in a given chain. Cascades to all
|
|
559
|
+
* descendants beneath this agent's depth in the chain.
|
|
560
|
+
*/
|
|
561
|
+
revokeAgentDelegation(agentId: string, chainId: string): Promise<{
|
|
562
|
+
revoked: number;
|
|
563
|
+
}>;
|
|
395
564
|
/**
|
|
396
565
|
* Emit an audit event for an agent action.
|
|
397
566
|
*
|
|
@@ -412,12 +581,18 @@ declare class VorimSDK {
|
|
|
412
581
|
* Emit a batch of audit events (up to 1,000). Each event is signed
|
|
413
582
|
* independently using its agent_id to look up the signing key. See
|
|
414
583
|
* {@link VorimSDK.emit} for signing behaviour and opt-out.
|
|
584
|
+
*
|
|
585
|
+
* When the server returns `ingested < events.length` (e.g. one event
|
|
586
|
+
* referenced an unknown agent_id), a `console.warn` is emitted so
|
|
587
|
+
* operators don't silently lose audit rows. The result is returned
|
|
588
|
+
* unchanged so callers can inspect / act on it.
|
|
415
589
|
*/
|
|
416
590
|
emitBatch(events: AuditEventInput[], options?: {
|
|
417
591
|
sign?: boolean;
|
|
418
592
|
}): Promise<{
|
|
419
593
|
ingested: number;
|
|
420
594
|
}>;
|
|
595
|
+
private warnOnPartialIngest;
|
|
421
596
|
/**
|
|
422
597
|
* Internal: prepare an event for transmission. Auto-signs if the SDK has a
|
|
423
598
|
* key for this agent and signing isn't explicitly opted out. Pre-existing
|
|
@@ -444,7 +619,15 @@ declare class VorimSDK {
|
|
|
444
619
|
private prepareEvent;
|
|
445
620
|
/** Serialise per-agent and apply chain hash + sign. */
|
|
446
621
|
private prepareEventChained;
|
|
447
|
-
/** Sign an event right now, no chain handling.
|
|
622
|
+
/** Sign an event right now, no chain handling.
|
|
623
|
+
*
|
|
624
|
+
* On signing failure (malformed key, Web Crypto unavailable, etc.)
|
|
625
|
+
* the event ships with its requested `canonical_form` preserved and
|
|
626
|
+
* a one-line warning is logged via `console.warn`. The previous
|
|
627
|
+
* behaviour silently dropped both the signature AND the
|
|
628
|
+
* canonical_form marker, which caused the event to be classified
|
|
629
|
+
* server-side as a v0 `signature_missing` instead of a v1 attempt
|
|
630
|
+
* that failed — making the breakage invisible to operators. */
|
|
448
631
|
private signEventNow;
|
|
449
632
|
/**
|
|
450
633
|
* Export a signed audit bundle for a date range.
|
|
@@ -568,4 +751,4 @@ declare class VorimError extends Error {
|
|
|
568
751
|
}
|
|
569
752
|
declare function createVorim(config: VorimConfig): VorimSDK;
|
|
570
753
|
|
|
571
|
-
export { type Agent, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, CANONICAL_TOOL_CATALOGUE_VERSION, type CatalogueTool, type PermissionCheckResult, type PermissionScope, type ReplayContext, type ReplayInputs, type TrustRecord, type VorimConfig, VorimError, VorimSDK, canonicalPayloadV0, canonicalPayloadV1, createVorim as default, hashPreviousEvent, hashSystemPrompt, hashTool, hashToolCatalogue, jcsCanonicalise, prepareReplayContext };
|
|
754
|
+
export { type Agent, type AgentDelegationRecord, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, CANONICAL_TOOL_CATALOGUE_VERSION, type CatalogueTool, type DelegationLinkClaims, type PermissionCheckResult, type PermissionScope, type ReplayContext, type ReplayInputs, type TrustRecord, type VorimConfig, VorimError, VorimSDK, canonicalPayloadV0, canonicalPayloadV1, createVorim as default, hashPreviousEvent, hashSystemPrompt, hashTool, hashToolCatalogue, jcsCanonicalise, prepareReplayContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,76 @@ interface AuditEventInput {
|
|
|
75
75
|
* is `"v1"`; you can also pass it on a per-event basis.
|
|
76
76
|
*/
|
|
77
77
|
canonical_form?: 'v0' | 'v1';
|
|
78
|
+
/**
|
|
79
|
+
* Per-event delegation context (VAIP -02 § 6). Populated by the
|
|
80
|
+
* server when the emitting agent is acting via a delegation chain;
|
|
81
|
+
* callers may also set these manually for events recorded outside
|
|
82
|
+
* the standard delegation flow. v1 signatures cover these fields.
|
|
83
|
+
*/
|
|
84
|
+
on_behalf_of?: string;
|
|
85
|
+
delegator_agent_id?: string;
|
|
86
|
+
delegation_chain_id?: string;
|
|
87
|
+
delegation_depth?: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Claims structure for one VAIP -02 § 5 delegation link.
|
|
91
|
+
*
|
|
92
|
+
* Each delegation step in a chain is one of these objects, RFC 8785 JCS
|
|
93
|
+
* canonicalised and Ed25519-signed by the delegator. Mirrors the same
|
|
94
|
+
* type in `@vorim/shared-types`; duplicated here so the SDK ships zero
|
|
95
|
+
* runtime dependencies. Byte-equivalence with the shared definition is
|
|
96
|
+
* enforced by the cross-language parity script.
|
|
97
|
+
*/
|
|
98
|
+
interface DelegationLinkClaims {
|
|
99
|
+
v: 0;
|
|
100
|
+
type: 'vaip-delegation-link';
|
|
101
|
+
chain_id: string;
|
|
102
|
+
depth: number;
|
|
103
|
+
delegator: string;
|
|
104
|
+
delegate: string;
|
|
105
|
+
scopes: string[];
|
|
106
|
+
max_chain_depth: number;
|
|
107
|
+
valid_from: string;
|
|
108
|
+
valid_until: string | null;
|
|
109
|
+
parent_link_hash: string | null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* One step in an agent-to-agent identity delegation chain (VAIP -02 § 5).
|
|
113
|
+
*
|
|
114
|
+
* Returned by {@link VorimSDK.delegateToAgent} and the listing endpoints.
|
|
115
|
+
*/
|
|
116
|
+
interface AgentDelegationRecord {
|
|
117
|
+
/** Internal row id. */
|
|
118
|
+
id: string;
|
|
119
|
+
/** Public chain identifier (format `chain_<32hex>`). Stamped on
|
|
120
|
+
* every audit event in this chain. */
|
|
121
|
+
publicChainId: string;
|
|
122
|
+
/** Organisation id. */
|
|
123
|
+
orgId: string;
|
|
124
|
+
/** Internal DB id of the delegator agent. */
|
|
125
|
+
delegatorAgentId: string;
|
|
126
|
+
/** Internal DB id of the delegate agent. */
|
|
127
|
+
delegateAgentId: string;
|
|
128
|
+
/** Public agent_id of the delegator (e.g. agid_acme_abc). */
|
|
129
|
+
delegatorAgentPublicId: string;
|
|
130
|
+
/** Public agent_id of the delegate. */
|
|
131
|
+
delegateAgentPublicId: string;
|
|
132
|
+
/** Scopes the delegate may exercise. */
|
|
133
|
+
scopesDelegated: string[];
|
|
134
|
+
/** How many further hops the delegate is permitted. */
|
|
135
|
+
maxChainDepth: number;
|
|
136
|
+
/** This step's depth from the root (root delegator step = 1). */
|
|
137
|
+
currentDepth: number;
|
|
138
|
+
/** Active / suspended / revoked / expired. */
|
|
139
|
+
status: 'active' | 'suspended' | 'revoked' | 'expired';
|
|
140
|
+
/** Parent delegation row (null for the root of an identity chain). */
|
|
141
|
+
parentDelegationId: string | null;
|
|
142
|
+
/** Public agent_id of the root principal of this chain. */
|
|
143
|
+
onBehalfOf: string;
|
|
144
|
+
/** ISO8601 creation timestamp. */
|
|
145
|
+
createdAt: string;
|
|
146
|
+
/** Optional ISO8601 expiry. */
|
|
147
|
+
validUntil: string | null;
|
|
78
148
|
}
|
|
79
149
|
interface TrustRecord {
|
|
80
150
|
agent_id: string;
|
|
@@ -302,6 +372,14 @@ declare class VorimSDK {
|
|
|
302
372
|
* link to the old chain.
|
|
303
373
|
*/
|
|
304
374
|
private lastEventHash;
|
|
375
|
+
/**
|
|
376
|
+
* Per-agent monotonic counter incremented by `forgetAgentKey`. An
|
|
377
|
+
* emit that started before `forgetAgentKey` ran will read a stale
|
|
378
|
+
* epoch and refuse to repopulate the chain tail, preventing the
|
|
379
|
+
* revoked agent from inheriting a new lastEventHash from the
|
|
380
|
+
* in-flight emit that the lock was holding.
|
|
381
|
+
*/
|
|
382
|
+
private agentForgetEpoch;
|
|
305
383
|
/**
|
|
306
384
|
* Per-agent emit promise. Each new emit awaits the previous one so
|
|
307
385
|
* the chain is constructed in order. Concurrent emits to the same
|
|
@@ -392,6 +470,97 @@ declare class VorimSDK {
|
|
|
392
470
|
* Revoke a specific permission scope from an agent.
|
|
393
471
|
*/
|
|
394
472
|
revokePermission(agentId: string, scope: PermissionScope): Promise<any>;
|
|
473
|
+
/**
|
|
474
|
+
* Delegate the right to act on this agent's behalf to another agent
|
|
475
|
+
* in the same org, with a strict subset of this agent's scopes.
|
|
476
|
+
*
|
|
477
|
+
* Multi-hop chains are supported up to depth 32. Scope subset is
|
|
478
|
+
* enforced at every hop. Audit events emitted by the delegate carry
|
|
479
|
+
* the chain context (`on_behalf_of`, `delegator_agent_id`,
|
|
480
|
+
* `delegation_chain_id`, `delegation_depth`) so a verifier walking
|
|
481
|
+
* the bundle can reconstruct the full chain.
|
|
482
|
+
*
|
|
483
|
+
* @example
|
|
484
|
+
* ```ts
|
|
485
|
+
* const chain = await vorim.delegateToAgent('agid_parent_abc', {
|
|
486
|
+
* delegate_agent_id: 'agid_child_xyz',
|
|
487
|
+
* scopes_delegated: ['agent:read', 'agent:execute'],
|
|
488
|
+
* max_chain_depth: 1, // delegate may make ONE further hop
|
|
489
|
+
* valid_until: '2026-12-31T00:00:00Z',
|
|
490
|
+
* });
|
|
491
|
+
* console.log(chain.public_chain_id); // chain_<hex>
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
delegateToAgent(delegatorAgentId: string, input: {
|
|
495
|
+
delegate_agent_id: string;
|
|
496
|
+
scopes_delegated: PermissionScope[];
|
|
497
|
+
max_chain_depth?: number;
|
|
498
|
+
valid_until?: string;
|
|
499
|
+
/**
|
|
500
|
+
* Optional Ed25519-signed delegation link (VAIP -02 § 5). When
|
|
501
|
+
* provided, the server verifies the signature against the
|
|
502
|
+
* delegator's stored public key, persists alongside the chain
|
|
503
|
+
* row, and exports it in bundle delegation_tokens so the chain
|
|
504
|
+
* is offline-verifiable by `@vorim/verify`. Compute via
|
|
505
|
+
* {@link signDelegationLink} or set manually if signing
|
|
506
|
+
* elsewhere.
|
|
507
|
+
*/
|
|
508
|
+
signed_link?: {
|
|
509
|
+
claims: DelegationLinkClaims;
|
|
510
|
+
signature: string;
|
|
511
|
+
};
|
|
512
|
+
}): Promise<AgentDelegationRecord>;
|
|
513
|
+
/**
|
|
514
|
+
* Sign a delegation link with the delegator's private key. Returns
|
|
515
|
+
* the signed link in the shape accepted by `delegateToAgent`'s
|
|
516
|
+
* `signed_link` field.
|
|
517
|
+
*
|
|
518
|
+
* The signature is Ed25519 over the RFC 8785 JCS-canonical bytes of
|
|
519
|
+
* the claims object. Same algorithm the server and `@vorim/verify`
|
|
520
|
+
* use for verification.
|
|
521
|
+
*
|
|
522
|
+
* Use this when the delegator's private key is in this SDK's
|
|
523
|
+
* keyring (i.e. set via `register()` or `useAgentKey()`).
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```ts
|
|
527
|
+
* const signed = await vorim.signDelegationLink({
|
|
528
|
+
* v: 0,
|
|
529
|
+
* type: 'vaip-delegation-link',
|
|
530
|
+
* chain_id: 'chain_abc', // server returns this on first delegation
|
|
531
|
+
* depth: 1,
|
|
532
|
+
* delegator: 'agid_parent',
|
|
533
|
+
* delegate: 'agid_child',
|
|
534
|
+
* scopes: ['agent:read', 'agent:execute'],
|
|
535
|
+
* max_chain_depth: 1,
|
|
536
|
+
* valid_from: new Date().toISOString(),
|
|
537
|
+
* valid_until: null,
|
|
538
|
+
* parent_link_hash: null,
|
|
539
|
+
* });
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
signDelegationLink(claims: DelegationLinkClaims): Promise<{
|
|
543
|
+
claims: DelegationLinkClaims;
|
|
544
|
+
signature: string;
|
|
545
|
+
}>;
|
|
546
|
+
/**
|
|
547
|
+
* List active identity-chain entries this agent participates in
|
|
548
|
+
* (either as delegator or delegate). Useful for showing the current
|
|
549
|
+
* delegation graph in an admin UI.
|
|
550
|
+
*/
|
|
551
|
+
listAgentDelegations(agentId: string): Promise<AgentDelegationRecord[]>;
|
|
552
|
+
/**
|
|
553
|
+
* Walk a delegation chain by its public id. Returns the full chain
|
|
554
|
+
* in depth order.
|
|
555
|
+
*/
|
|
556
|
+
getDelegationChain(agentId: string, chainId: string): Promise<AgentDelegationRecord[]>;
|
|
557
|
+
/**
|
|
558
|
+
* Revoke this agent's delegation in a given chain. Cascades to all
|
|
559
|
+
* descendants beneath this agent's depth in the chain.
|
|
560
|
+
*/
|
|
561
|
+
revokeAgentDelegation(agentId: string, chainId: string): Promise<{
|
|
562
|
+
revoked: number;
|
|
563
|
+
}>;
|
|
395
564
|
/**
|
|
396
565
|
* Emit an audit event for an agent action.
|
|
397
566
|
*
|
|
@@ -412,12 +581,18 @@ declare class VorimSDK {
|
|
|
412
581
|
* Emit a batch of audit events (up to 1,000). Each event is signed
|
|
413
582
|
* independently using its agent_id to look up the signing key. See
|
|
414
583
|
* {@link VorimSDK.emit} for signing behaviour and opt-out.
|
|
584
|
+
*
|
|
585
|
+
* When the server returns `ingested < events.length` (e.g. one event
|
|
586
|
+
* referenced an unknown agent_id), a `console.warn` is emitted so
|
|
587
|
+
* operators don't silently lose audit rows. The result is returned
|
|
588
|
+
* unchanged so callers can inspect / act on it.
|
|
415
589
|
*/
|
|
416
590
|
emitBatch(events: AuditEventInput[], options?: {
|
|
417
591
|
sign?: boolean;
|
|
418
592
|
}): Promise<{
|
|
419
593
|
ingested: number;
|
|
420
594
|
}>;
|
|
595
|
+
private warnOnPartialIngest;
|
|
421
596
|
/**
|
|
422
597
|
* Internal: prepare an event for transmission. Auto-signs if the SDK has a
|
|
423
598
|
* key for this agent and signing isn't explicitly opted out. Pre-existing
|
|
@@ -444,7 +619,15 @@ declare class VorimSDK {
|
|
|
444
619
|
private prepareEvent;
|
|
445
620
|
/** Serialise per-agent and apply chain hash + sign. */
|
|
446
621
|
private prepareEventChained;
|
|
447
|
-
/** Sign an event right now, no chain handling.
|
|
622
|
+
/** Sign an event right now, no chain handling.
|
|
623
|
+
*
|
|
624
|
+
* On signing failure (malformed key, Web Crypto unavailable, etc.)
|
|
625
|
+
* the event ships with its requested `canonical_form` preserved and
|
|
626
|
+
* a one-line warning is logged via `console.warn`. The previous
|
|
627
|
+
* behaviour silently dropped both the signature AND the
|
|
628
|
+
* canonical_form marker, which caused the event to be classified
|
|
629
|
+
* server-side as a v0 `signature_missing` instead of a v1 attempt
|
|
630
|
+
* that failed — making the breakage invisible to operators. */
|
|
448
631
|
private signEventNow;
|
|
449
632
|
/**
|
|
450
633
|
* Export a signed audit bundle for a date range.
|
|
@@ -568,4 +751,4 @@ declare class VorimError extends Error {
|
|
|
568
751
|
}
|
|
569
752
|
declare function createVorim(config: VorimConfig): VorimSDK;
|
|
570
753
|
|
|
571
|
-
export { type Agent, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, CANONICAL_TOOL_CATALOGUE_VERSION, type CatalogueTool, type PermissionCheckResult, type PermissionScope, type ReplayContext, type ReplayInputs, type TrustRecord, type VorimConfig, VorimError, VorimSDK, canonicalPayloadV0, canonicalPayloadV1, createVorim as default, hashPreviousEvent, hashSystemPrompt, hashTool, hashToolCatalogue, jcsCanonicalise, prepareReplayContext };
|
|
754
|
+
export { type Agent, type AgentDelegationRecord, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, CANONICAL_TOOL_CATALOGUE_VERSION, type CatalogueTool, type DelegationLinkClaims, type PermissionCheckResult, type PermissionScope, type ReplayContext, type ReplayInputs, type TrustRecord, type VorimConfig, VorimError, VorimSDK, canonicalPayloadV0, canonicalPayloadV1, createVorim as default, hashPreviousEvent, hashSystemPrompt, hashTool, hashToolCatalogue, jcsCanonicalise, prepareReplayContext };
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ async function prepareReplayContext(inputs) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// src/index.ts
|
|
73
|
-
var SDK_VERSION = true ? "3.
|
|
73
|
+
var SDK_VERSION = true ? "3.3.1" : "0.0.0";
|
|
74
74
|
var USER_AGENT = `vorim-sdk/${SDK_VERSION}`;
|
|
75
75
|
function canonicalPayloadV0(event) {
|
|
76
76
|
return [
|
|
@@ -108,6 +108,14 @@ var VorimSDK = class {
|
|
|
108
108
|
* link to the old chain.
|
|
109
109
|
*/
|
|
110
110
|
lastEventHash = /* @__PURE__ */ new Map();
|
|
111
|
+
/**
|
|
112
|
+
* Per-agent monotonic counter incremented by `forgetAgentKey`. An
|
|
113
|
+
* emit that started before `forgetAgentKey` ran will read a stale
|
|
114
|
+
* epoch and refuse to repopulate the chain tail, preventing the
|
|
115
|
+
* revoked agent from inheriting a new lastEventHash from the
|
|
116
|
+
* in-flight emit that the lock was holding.
|
|
117
|
+
*/
|
|
118
|
+
agentForgetEpoch = /* @__PURE__ */ new Map();
|
|
111
119
|
/**
|
|
112
120
|
* Per-agent emit promise. Each new emit awaits the previous one so
|
|
113
121
|
* the chain is constructed in order. Concurrent emits to the same
|
|
@@ -142,6 +150,7 @@ var VorimSDK = class {
|
|
|
142
150
|
this.agentKeys.delete(agentId);
|
|
143
151
|
this.lastEventHash.delete(agentId);
|
|
144
152
|
this.chainLocks.delete(agentId);
|
|
153
|
+
this.agentForgetEpoch.set(agentId, (this.agentForgetEpoch.get(agentId) ?? 0) + 1);
|
|
145
154
|
}
|
|
146
155
|
// ─── Health Check ────────────────────────────────────────────────
|
|
147
156
|
/**
|
|
@@ -230,6 +239,95 @@ var VorimSDK = class {
|
|
|
230
239
|
async revokePermission(agentId, scope) {
|
|
231
240
|
return this.delete(`/agents/${agentId}/permissions/${scope}`);
|
|
232
241
|
}
|
|
242
|
+
// ─── Agent-to-Agent Identity Delegation (VAIP -02 § 5) ──────────────
|
|
243
|
+
/**
|
|
244
|
+
* Delegate the right to act on this agent's behalf to another agent
|
|
245
|
+
* in the same org, with a strict subset of this agent's scopes.
|
|
246
|
+
*
|
|
247
|
+
* Multi-hop chains are supported up to depth 32. Scope subset is
|
|
248
|
+
* enforced at every hop. Audit events emitted by the delegate carry
|
|
249
|
+
* the chain context (`on_behalf_of`, `delegator_agent_id`,
|
|
250
|
+
* `delegation_chain_id`, `delegation_depth`) so a verifier walking
|
|
251
|
+
* the bundle can reconstruct the full chain.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* const chain = await vorim.delegateToAgent('agid_parent_abc', {
|
|
256
|
+
* delegate_agent_id: 'agid_child_xyz',
|
|
257
|
+
* scopes_delegated: ['agent:read', 'agent:execute'],
|
|
258
|
+
* max_chain_depth: 1, // delegate may make ONE further hop
|
|
259
|
+
* valid_until: '2026-12-31T00:00:00Z',
|
|
260
|
+
* });
|
|
261
|
+
* console.log(chain.public_chain_id); // chain_<hex>
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
async delegateToAgent(delegatorAgentId, input) {
|
|
265
|
+
return this.post(`/agents/${delegatorAgentId}/delegations`, input);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Sign a delegation link with the delegator's private key. Returns
|
|
269
|
+
* the signed link in the shape accepted by `delegateToAgent`'s
|
|
270
|
+
* `signed_link` field.
|
|
271
|
+
*
|
|
272
|
+
* The signature is Ed25519 over the RFC 8785 JCS-canonical bytes of
|
|
273
|
+
* the claims object. Same algorithm the server and `@vorim/verify`
|
|
274
|
+
* use for verification.
|
|
275
|
+
*
|
|
276
|
+
* Use this when the delegator's private key is in this SDK's
|
|
277
|
+
* keyring (i.e. set via `register()` or `useAgentKey()`).
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```ts
|
|
281
|
+
* const signed = await vorim.signDelegationLink({
|
|
282
|
+
* v: 0,
|
|
283
|
+
* type: 'vaip-delegation-link',
|
|
284
|
+
* chain_id: 'chain_abc', // server returns this on first delegation
|
|
285
|
+
* depth: 1,
|
|
286
|
+
* delegator: 'agid_parent',
|
|
287
|
+
* delegate: 'agid_child',
|
|
288
|
+
* scopes: ['agent:read', 'agent:execute'],
|
|
289
|
+
* max_chain_depth: 1,
|
|
290
|
+
* valid_from: new Date().toISOString(),
|
|
291
|
+
* valid_until: null,
|
|
292
|
+
* parent_link_hash: null,
|
|
293
|
+
* });
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
async signDelegationLink(claims) {
|
|
297
|
+
const key = this.agentKeys.get(claims.delegator);
|
|
298
|
+
if (!key) {
|
|
299
|
+
throw new VorimError(
|
|
300
|
+
400,
|
|
301
|
+
"NO_AGENT_KEY",
|
|
302
|
+
`SDK has no private key for delegator ${claims.delegator}`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
const bytes = jcsCanonicalise(claims);
|
|
306
|
+
const signature = await this.sign(bytes, key);
|
|
307
|
+
return { claims, signature };
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* List active identity-chain entries this agent participates in
|
|
311
|
+
* (either as delegator or delegate). Useful for showing the current
|
|
312
|
+
* delegation graph in an admin UI.
|
|
313
|
+
*/
|
|
314
|
+
async listAgentDelegations(agentId) {
|
|
315
|
+
return this.get(`/agents/${agentId}/delegations`);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Walk a delegation chain by its public id. Returns the full chain
|
|
319
|
+
* in depth order.
|
|
320
|
+
*/
|
|
321
|
+
async getDelegationChain(agentId, chainId) {
|
|
322
|
+
return this.get(`/agents/${agentId}/delegation-chain/${chainId}`);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Revoke this agent's delegation in a given chain. Cascades to all
|
|
326
|
+
* descendants beneath this agent's depth in the chain.
|
|
327
|
+
*/
|
|
328
|
+
async revokeAgentDelegation(agentId, chainId) {
|
|
329
|
+
return this.delete(`/agents/${agentId}/delegations/${chainId}`);
|
|
330
|
+
}
|
|
233
331
|
// ─── Audit ────────────────────────────────────────────────────────
|
|
234
332
|
/**
|
|
235
333
|
* Emit an audit event for an agent action.
|
|
@@ -244,16 +342,35 @@ var VorimSDK = class {
|
|
|
244
342
|
*/
|
|
245
343
|
async emit(event, options) {
|
|
246
344
|
const prepared = await this.prepareEvent(event, options?.sign);
|
|
247
|
-
|
|
345
|
+
const result = await this.post("/audit/events", { events: [prepared] });
|
|
346
|
+
this.warnOnPartialIngest(1, result?.ingested ?? 0);
|
|
347
|
+
return result;
|
|
248
348
|
}
|
|
249
349
|
/**
|
|
250
350
|
* Emit a batch of audit events (up to 1,000). Each event is signed
|
|
251
351
|
* independently using its agent_id to look up the signing key. See
|
|
252
352
|
* {@link VorimSDK.emit} for signing behaviour and opt-out.
|
|
353
|
+
*
|
|
354
|
+
* When the server returns `ingested < events.length` (e.g. one event
|
|
355
|
+
* referenced an unknown agent_id), a `console.warn` is emitted so
|
|
356
|
+
* operators don't silently lose audit rows. The result is returned
|
|
357
|
+
* unchanged so callers can inspect / act on it.
|
|
253
358
|
*/
|
|
254
359
|
async emitBatch(events, options) {
|
|
255
360
|
const prepared = await Promise.all(events.map((e) => this.prepareEvent(e, options?.sign)));
|
|
256
|
-
|
|
361
|
+
const result = await this.post("/audit/events", { events: prepared });
|
|
362
|
+
this.warnOnPartialIngest(events.length, result?.ingested ?? 0);
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
warnOnPartialIngest(submitted, ingested) {
|
|
366
|
+
if (ingested < submitted) {
|
|
367
|
+
try {
|
|
368
|
+
console.warn(
|
|
369
|
+
`[@vorim/sdk] partial ingest: server stored ${ingested}/${submitted} events. Common causes: unknown agent_id (cross-org or typo), invalid signature when strict verification is enabled.`
|
|
370
|
+
);
|
|
371
|
+
} catch {
|
|
372
|
+
}
|
|
373
|
+
}
|
|
257
374
|
}
|
|
258
375
|
/**
|
|
259
376
|
* Internal: prepare an event for transmission. Auto-signs if the SDK has a
|
|
@@ -298,6 +415,7 @@ var VorimSDK = class {
|
|
|
298
415
|
});
|
|
299
416
|
this.chainLocks.set(agentId, prior.then(() => next));
|
|
300
417
|
await prior;
|
|
418
|
+
const startEpoch = this.agentForgetEpoch.get(agentId) ?? 0;
|
|
301
419
|
try {
|
|
302
420
|
const prev = this.lastEventHash.get(agentId);
|
|
303
421
|
const eventWithPrev = prev ? { ...event, prev_event_hash: prev } : event;
|
|
@@ -305,7 +423,10 @@ var VorimSDK = class {
|
|
|
305
423
|
const wireForm = prepared.canonical_form ?? "v0";
|
|
306
424
|
const bytes = wireForm === "v1" ? canonicalPayloadV1(prepared) : canonicalPayloadV0(prepared);
|
|
307
425
|
try {
|
|
308
|
-
|
|
426
|
+
const tail = await hashPreviousEvent(bytes);
|
|
427
|
+
if ((this.agentForgetEpoch.get(agentId) ?? 0) === startEpoch) {
|
|
428
|
+
this.lastEventHash.set(agentId, tail);
|
|
429
|
+
}
|
|
309
430
|
} catch {
|
|
310
431
|
this.lastEventHash.delete(agentId);
|
|
311
432
|
}
|
|
@@ -314,18 +435,32 @@ var VorimSDK = class {
|
|
|
314
435
|
release();
|
|
315
436
|
}
|
|
316
437
|
}
|
|
317
|
-
/** Sign an event right now, no chain handling.
|
|
438
|
+
/** Sign an event right now, no chain handling.
|
|
439
|
+
*
|
|
440
|
+
* On signing failure (malformed key, Web Crypto unavailable, etc.)
|
|
441
|
+
* the event ships with its requested `canonical_form` preserved and
|
|
442
|
+
* a one-line warning is logged via `console.warn`. The previous
|
|
443
|
+
* behaviour silently dropped both the signature AND the
|
|
444
|
+
* canonical_form marker, which caused the event to be classified
|
|
445
|
+
* server-side as a v0 `signature_missing` instead of a v1 attempt
|
|
446
|
+
* that failed — making the breakage invisible to operators. */
|
|
318
447
|
async signEventNow(event, _shouldSign) {
|
|
319
448
|
const key = this.agentKeys.get(event.agent_id);
|
|
320
449
|
if (!key) return event;
|
|
321
450
|
const form = event.canonical_form ?? this.canonicalForm;
|
|
451
|
+
const withForm = form === "v0" ? event : { ...event, canonical_form: "v1" };
|
|
322
452
|
try {
|
|
323
|
-
const withForm = form === "v0" ? event : { ...event, canonical_form: "v1" };
|
|
324
453
|
const payload = form === "v1" ? canonicalPayloadV1(withForm) : canonicalPayloadV0(withForm);
|
|
325
454
|
const signature = await this.sign(payload, key);
|
|
326
455
|
return { ...withForm, signature };
|
|
327
|
-
} catch {
|
|
328
|
-
|
|
456
|
+
} catch (err) {
|
|
457
|
+
try {
|
|
458
|
+
console.warn(
|
|
459
|
+
`[@vorim/sdk] signing failed for agent_id=${event.agent_id} form=${form}: ${err?.message ?? err}. Event will be emitted unsigned with canonical_form retained.`
|
|
460
|
+
);
|
|
461
|
+
} catch {
|
|
462
|
+
}
|
|
463
|
+
return withForm;
|
|
329
464
|
}
|
|
330
465
|
}
|
|
331
466
|
/**
|