@aroha-sdk/core 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crypto/encryption.d.ts +39 -0
- package/dist/crypto/encryption.d.ts.map +1 -0
- package/dist/crypto/encryption.js +88 -0
- package/dist/crypto/encryption.js.map +1 -0
- package/dist/crypto/index.d.ts +3 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +3 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/signing.d.ts +43 -0
- package/dist/crypto/signing.d.ts.map +1 -0
- package/dist/crypto/signing.js +80 -0
- package/dist/crypto/signing.js.map +1 -0
- package/dist/identity/credentials.d.ts +81 -0
- package/dist/identity/credentials.d.ts.map +1 -0
- package/dist/identity/credentials.js +82 -0
- package/dist/identity/credentials.js.map +1 -0
- package/dist/identity/did-cache.d.ts +46 -0
- package/dist/identity/did-cache.d.ts.map +1 -0
- package/dist/identity/did-cache.js +90 -0
- package/dist/identity/did-cache.js.map +1 -0
- package/dist/identity/did.d.ts +139 -0
- package/dist/identity/did.d.ts.map +1 -0
- package/dist/identity/did.js +291 -0
- package/dist/identity/did.js.map +1 -0
- package/dist/identity/index.d.ts +5 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +5 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/web-did.d.ts +131 -0
- package/dist/identity/web-did.d.ts.map +1 -0
- package/dist/identity/web-did.js +338 -0
- package/dist/identity/web-did.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/messages/envelope.d.ts +102 -0
- package/dist/messages/envelope.d.ts.map +1 -0
- package/dist/messages/envelope.js +106 -0
- package/dist/messages/envelope.js.map +1 -0
- package/dist/messages/idempotency.d.ts +61 -0
- package/dist/messages/idempotency.d.ts.map +1 -0
- package/dist/messages/idempotency.js +93 -0
- package/dist/messages/idempotency.js.map +1 -0
- package/dist/messages/index.d.ts +5 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +5 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/nonce.d.ts +60 -0
- package/dist/messages/nonce.d.ts.map +1 -0
- package/dist/messages/nonce.js +94 -0
- package/dist/messages/nonce.js.map +1 -0
- package/dist/messages/types.d.ts +302 -0
- package/dist/messages/types.d.ts.map +1 -0
- package/dist/messages/types.js +38 -0
- package/dist/messages/types.js.map +1 -0
- package/dist/transport/client.d.ts +79 -0
- package/dist/transport/client.d.ts.map +1 -0
- package/dist/transport/client.js +182 -0
- package/dist/transport/client.js.map +1 -0
- package/dist/transport/http-utils.d.ts +3 -0
- package/dist/transport/http-utils.d.ts.map +1 -0
- package/dist/transport/http-utils.js +27 -0
- package/dist/transport/http-utils.js.map +1 -0
- package/dist/transport/index.d.ts +4 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +4 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/server.d.ts +123 -0
- package/dist/transport/server.d.ts.map +1 -0
- package/dist/transport/server.js +251 -0
- package/dist/transport/server.js.map +1 -0
- package/package.json +5 -1
- package/tsconfig.json +0 -10
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotency Store — server-side deduplication for ArohaRequest.
|
|
3
|
+
*
|
|
4
|
+
* ArohaCommit is already spec-idempotent. But ArohaRequest (capability
|
|
5
|
+
* invocations) are not — a retried "book-flight" request could create a
|
|
6
|
+
* duplicate booking. The idempotency store fixes this.
|
|
7
|
+
*
|
|
8
|
+
* Protocol contract:
|
|
9
|
+
* Sender includes idempotencyKey: string in ArohaRequestBody.
|
|
10
|
+
* Receiver checks the store before processing. If the key exists and
|
|
11
|
+
* the cached response is still valid, the cached response is returned
|
|
12
|
+
* immediately — no work is done twice.
|
|
13
|
+
*
|
|
14
|
+
* Key design: senderDID:idempotencyKey — scoped per sender so different
|
|
15
|
+
* orchestrators cannot accidentally share idempotency keys.
|
|
16
|
+
*
|
|
17
|
+
* Reference: Stripe API idempotency (https://stripe.com/docs/idempotency)
|
|
18
|
+
*/
|
|
19
|
+
import { type ArohaEnvelope } from "./envelope.js";
|
|
20
|
+
export interface IIdempotencyStore {
|
|
21
|
+
/**
|
|
22
|
+
* Retrieve a cached response for this key.
|
|
23
|
+
* Returns null if not found or expired.
|
|
24
|
+
*/
|
|
25
|
+
get(senderDID: string, idempotencyKey: string): Promise<ArohaEnvelope | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Store a response for this key with a TTL.
|
|
28
|
+
* TTL default: 86_400_000 ms (24 hours) — matches typical saga window.
|
|
29
|
+
*/
|
|
30
|
+
set(senderDID: string, idempotencyKey: string, response: ArohaEnvelope, ttlMs?: number): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export declare class InMemoryIdempotencyStore implements IIdempotencyStore {
|
|
33
|
+
private readonly defaultTtlMs;
|
|
34
|
+
private readonly store;
|
|
35
|
+
private readonly cleanupIntervalMs;
|
|
36
|
+
private readonly cleanupTimer;
|
|
37
|
+
constructor(config?: {
|
|
38
|
+
defaultTtlMs?: number;
|
|
39
|
+
cleanupIntervalMs?: number;
|
|
40
|
+
});
|
|
41
|
+
get(senderDID: string, idempotencyKey: string): Promise<ArohaEnvelope | null>;
|
|
42
|
+
set(senderDID: string, idempotencyKey: string, response: ArohaEnvelope, ttlMs?: number): Promise<void>;
|
|
43
|
+
destroy(): void;
|
|
44
|
+
get size(): number;
|
|
45
|
+
private evictExpired;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check the idempotency store and return a cached response if one exists.
|
|
49
|
+
* Returns null if the request should proceed normally.
|
|
50
|
+
*
|
|
51
|
+
* Usage in an agent's message handler:
|
|
52
|
+
* const cached = await checkIdempotency(store, envelope);
|
|
53
|
+
* if (cached) { respond(cached); return; }
|
|
54
|
+
* // ... process normally ...
|
|
55
|
+
* const response = buildResponse(...);
|
|
56
|
+
* await storeIdempotency(store, envelope, response);
|
|
57
|
+
* respond(response);
|
|
58
|
+
*/
|
|
59
|
+
export declare function checkIdempotency(store: IIdempotencyStore, envelope: ArohaEnvelope): Promise<ArohaEnvelope | null>;
|
|
60
|
+
export declare function storeIdempotency(store: IIdempotencyStore, requestEnvelope: ArohaEnvelope, responseEnvelope: ArohaEnvelope, ttlMs?: number): Promise<void>;
|
|
61
|
+
//# sourceMappingURL=idempotency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/messages/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAInD,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAE9E;;;OAGG;IACH,GAAG,CACD,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,aAAa,EACvB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AASD,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;gBAElD,MAAM,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAO;IAUxE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAW7E,GAAG,CACP,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,aAAa,EACvB,KAAK,SAAoB,GACxB,OAAO,CAAC,IAAI,CAAC;IAOhB,OAAO,IAAI,IAAI;IAKf,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,YAAY;CAMrB;AAQD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAI/B;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,iBAAiB,EACxB,eAAe,EAAE,aAAa,EAC9B,gBAAgB,EAAE,aAAa,EAC/B,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotency Store — server-side deduplication for ArohaRequest.
|
|
3
|
+
*
|
|
4
|
+
* ArohaCommit is already spec-idempotent. But ArohaRequest (capability
|
|
5
|
+
* invocations) are not — a retried "book-flight" request could create a
|
|
6
|
+
* duplicate booking. The idempotency store fixes this.
|
|
7
|
+
*
|
|
8
|
+
* Protocol contract:
|
|
9
|
+
* Sender includes idempotencyKey: string in ArohaRequestBody.
|
|
10
|
+
* Receiver checks the store before processing. If the key exists and
|
|
11
|
+
* the cached response is still valid, the cached response is returned
|
|
12
|
+
* immediately — no work is done twice.
|
|
13
|
+
*
|
|
14
|
+
* Key design: senderDID:idempotencyKey — scoped per sender so different
|
|
15
|
+
* orchestrators cannot accidentally share idempotency keys.
|
|
16
|
+
*
|
|
17
|
+
* Reference: Stripe API idempotency (https://stripe.com/docs/idempotency)
|
|
18
|
+
*/
|
|
19
|
+
export class InMemoryIdempotencyStore {
|
|
20
|
+
defaultTtlMs;
|
|
21
|
+
store = new Map();
|
|
22
|
+
cleanupIntervalMs;
|
|
23
|
+
cleanupTimer;
|
|
24
|
+
constructor(config = {}) {
|
|
25
|
+
this.defaultTtlMs = config.defaultTtlMs ?? 86_400_000; // 24h
|
|
26
|
+
this.cleanupIntervalMs = config.cleanupIntervalMs ?? 300_000; // 5m
|
|
27
|
+
// Periodically evict expired entries to prevent unbounded memory growth
|
|
28
|
+
this.cleanupTimer = setInterval(() => this.evictExpired(), this.cleanupIntervalMs);
|
|
29
|
+
// Don't prevent process exit if only cleanup timer is pending
|
|
30
|
+
if (this.cleanupTimer.unref)
|
|
31
|
+
this.cleanupTimer.unref();
|
|
32
|
+
}
|
|
33
|
+
async get(senderDID, idempotencyKey) {
|
|
34
|
+
const key = storeKey(senderDID, idempotencyKey);
|
|
35
|
+
const entry = this.store.get(key);
|
|
36
|
+
if (!entry)
|
|
37
|
+
return null;
|
|
38
|
+
if (Date.now() > entry.expiresAt) {
|
|
39
|
+
this.store.delete(key);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return entry.response;
|
|
43
|
+
}
|
|
44
|
+
async set(senderDID, idempotencyKey, response, ttlMs = this.defaultTtlMs) {
|
|
45
|
+
this.store.set(storeKey(senderDID, idempotencyKey), {
|
|
46
|
+
response,
|
|
47
|
+
expiresAt: Date.now() + ttlMs,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
destroy() {
|
|
51
|
+
clearInterval(this.cleanupTimer);
|
|
52
|
+
this.store.clear();
|
|
53
|
+
}
|
|
54
|
+
get size() {
|
|
55
|
+
return this.store.size;
|
|
56
|
+
}
|
|
57
|
+
evictExpired() {
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
for (const [key, entry] of this.store) {
|
|
60
|
+
if (now > entry.expiresAt)
|
|
61
|
+
this.store.delete(key);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ─── Utility ──────────────────────────────────────────────────────────────────
|
|
66
|
+
function storeKey(senderDID, idempotencyKey) {
|
|
67
|
+
return `${senderDID}:${idempotencyKey}`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check the idempotency store and return a cached response if one exists.
|
|
71
|
+
* Returns null if the request should proceed normally.
|
|
72
|
+
*
|
|
73
|
+
* Usage in an agent's message handler:
|
|
74
|
+
* const cached = await checkIdempotency(store, envelope);
|
|
75
|
+
* if (cached) { respond(cached); return; }
|
|
76
|
+
* // ... process normally ...
|
|
77
|
+
* const response = buildResponse(...);
|
|
78
|
+
* await storeIdempotency(store, envelope, response);
|
|
79
|
+
* respond(response);
|
|
80
|
+
*/
|
|
81
|
+
export async function checkIdempotency(store, envelope) {
|
|
82
|
+
const body = envelope.body;
|
|
83
|
+
if (!body.idempotencyKey)
|
|
84
|
+
return null;
|
|
85
|
+
return store.get(envelope.from, body.idempotencyKey);
|
|
86
|
+
}
|
|
87
|
+
export async function storeIdempotency(store, requestEnvelope, responseEnvelope, ttlMs) {
|
|
88
|
+
const body = requestEnvelope.body;
|
|
89
|
+
if (!body.idempotencyKey)
|
|
90
|
+
return;
|
|
91
|
+
await store.set(requestEnvelope.from, body.idempotencyKey, responseEnvelope, ttlMs);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=idempotency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/messages/idempotency.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aroha Protocol — Nonce Registry
|
|
3
|
+
*
|
|
4
|
+
* Implements the spec rule:
|
|
5
|
+
* "A receiving agent MUST reject any message where nonce has been seen before
|
|
6
|
+
* (replay attack)"
|
|
7
|
+
*
|
|
8
|
+
* Nonces are stored with a TTL equal to the message's expires window.
|
|
9
|
+
* After a nonce expires it is automatically evicted to bound memory usage.
|
|
10
|
+
*
|
|
11
|
+
* This is protocol infrastructure. It has no knowledge of message contents.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Pluggable nonce deduplication backend.
|
|
15
|
+
* Default: MapNonceStore (in-process). Production: inject a Redis adapter.
|
|
16
|
+
*/
|
|
17
|
+
export interface NonceStore {
|
|
18
|
+
/**
|
|
19
|
+
* Record a nonce and return true if it is fresh (first seen).
|
|
20
|
+
* Returns false if the nonce was already recorded (replay).
|
|
21
|
+
* expiryMs is the absolute expiry timestamp in milliseconds.
|
|
22
|
+
*/
|
|
23
|
+
setIfAbsent(nonce: string, expiryMs: number): Promise<boolean>;
|
|
24
|
+
evictExpired(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare class MapNonceStore implements NonceStore {
|
|
27
|
+
private readonly seen;
|
|
28
|
+
setIfAbsent(nonce: string, expiryMs: number): Promise<boolean>;
|
|
29
|
+
evictExpired(): Promise<void>;
|
|
30
|
+
get size(): number;
|
|
31
|
+
}
|
|
32
|
+
export declare class NonceRegistry {
|
|
33
|
+
private readonly store;
|
|
34
|
+
private readonly cleanupTimer;
|
|
35
|
+
private readonly syncSeen;
|
|
36
|
+
constructor(cleanupIntervalMs?: number, store?: NonceStore);
|
|
37
|
+
/**
|
|
38
|
+
* Synchronous check — uses a dedicated in-process map.
|
|
39
|
+
* Use checkAsync when injecting a custom store.
|
|
40
|
+
*
|
|
41
|
+
* @param nonce The nonce string from the message envelope
|
|
42
|
+
* @param expiresAt ISO8601 expiry time from the message's "expires" field
|
|
43
|
+
* @returns true if the nonce is fresh (first time seen), false if replay
|
|
44
|
+
*/
|
|
45
|
+
check(nonce: string, expiresAt: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Async check — works with any NonceStore, including custom backends.
|
|
48
|
+
*
|
|
49
|
+
* @param nonce The nonce string from the message envelope
|
|
50
|
+
* @param expiresAt ISO8601 expiry time from the message's "expires" field
|
|
51
|
+
* @returns true if the nonce is fresh (first time seen), false if replay
|
|
52
|
+
*/
|
|
53
|
+
checkAsync(nonce: string, expiresAt: string): Promise<boolean>;
|
|
54
|
+
/** Number of nonces currently tracked (sync store). */
|
|
55
|
+
get size(): number;
|
|
56
|
+
/** Stop the background cleanup timer. Call when the owning server shuts down. */
|
|
57
|
+
destroy(): void;
|
|
58
|
+
private evictSyncSeen;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=nonce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce.d.ts","sourceRoot":"","sources":["../../src/messages/nonce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAID,qBAAa,aAAc,YAAW,UAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAE5C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM9D,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,IAAI,IAAI,IAAI,MAAM,CAA2B;CAC9C;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAE9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;gBAE1C,iBAAiB,SAAS,EAAE,KAAK,CAAC,EAAE,UAAU;IAU1D;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAWhD;;;;;;OAMG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpE,uDAAuD;IACvD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,iFAAiF;IACjF,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aroha Protocol — Nonce Registry
|
|
3
|
+
*
|
|
4
|
+
* Implements the spec rule:
|
|
5
|
+
* "A receiving agent MUST reject any message where nonce has been seen before
|
|
6
|
+
* (replay attack)"
|
|
7
|
+
*
|
|
8
|
+
* Nonces are stored with a TTL equal to the message's expires window.
|
|
9
|
+
* After a nonce expires it is automatically evicted to bound memory usage.
|
|
10
|
+
*
|
|
11
|
+
* This is protocol infrastructure. It has no knowledge of message contents.
|
|
12
|
+
*/
|
|
13
|
+
// ─── Default in-process store ─────────────────────────────────────────────────
|
|
14
|
+
export class MapNonceStore {
|
|
15
|
+
seen = new Map();
|
|
16
|
+
async setIfAbsent(nonce, expiryMs) {
|
|
17
|
+
if (this.seen.has(nonce))
|
|
18
|
+
return false;
|
|
19
|
+
this.seen.set(nonce, expiryMs);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
async evictExpired() {
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
for (const [nonce, expiryMs] of this.seen) {
|
|
25
|
+
if (expiryMs < now)
|
|
26
|
+
this.seen.delete(nonce);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
get size() { return this.seen.size; }
|
|
30
|
+
}
|
|
31
|
+
// ─── Registry ─────────────────────────────────────────────────────────────────
|
|
32
|
+
export class NonceRegistry {
|
|
33
|
+
store;
|
|
34
|
+
cleanupTimer;
|
|
35
|
+
// Synchronous seen map for backward-compat check()
|
|
36
|
+
syncSeen = new Map();
|
|
37
|
+
constructor(cleanupIntervalMs = 60_000, store) {
|
|
38
|
+
this.store = store ?? new MapNonceStore();
|
|
39
|
+
this.cleanupTimer = setInterval(() => {
|
|
40
|
+
this.store.evictExpired().catch(() => { });
|
|
41
|
+
this.evictSyncSeen();
|
|
42
|
+
}, cleanupIntervalMs);
|
|
43
|
+
// Allow the process to exit even if this registry is still alive.
|
|
44
|
+
if (typeof this.cleanupTimer.unref === "function")
|
|
45
|
+
this.cleanupTimer.unref();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Synchronous check — uses a dedicated in-process map.
|
|
49
|
+
* Use checkAsync when injecting a custom store.
|
|
50
|
+
*
|
|
51
|
+
* @param nonce The nonce string from the message envelope
|
|
52
|
+
* @param expiresAt ISO8601 expiry time from the message's "expires" field
|
|
53
|
+
* @returns true if the nonce is fresh (first time seen), false if replay
|
|
54
|
+
*/
|
|
55
|
+
check(nonce, expiresAt) {
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
// Evict expired entries
|
|
58
|
+
for (const [n, exp] of this.syncSeen) {
|
|
59
|
+
if (exp < now)
|
|
60
|
+
this.syncSeen.delete(n);
|
|
61
|
+
}
|
|
62
|
+
if (this.syncSeen.has(nonce))
|
|
63
|
+
return false;
|
|
64
|
+
this.syncSeen.set(nonce, new Date(expiresAt).getTime());
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Async check — works with any NonceStore, including custom backends.
|
|
69
|
+
*
|
|
70
|
+
* @param nonce The nonce string from the message envelope
|
|
71
|
+
* @param expiresAt ISO8601 expiry time from the message's "expires" field
|
|
72
|
+
* @returns true if the nonce is fresh (first time seen), false if replay
|
|
73
|
+
*/
|
|
74
|
+
async checkAsync(nonce, expiresAt) {
|
|
75
|
+
const expiryMs = new Date(expiresAt).getTime();
|
|
76
|
+
return this.store.setIfAbsent(nonce, expiryMs);
|
|
77
|
+
}
|
|
78
|
+
/** Number of nonces currently tracked (sync store). */
|
|
79
|
+
get size() {
|
|
80
|
+
return this.syncSeen.size;
|
|
81
|
+
}
|
|
82
|
+
/** Stop the background cleanup timer. Call when the owning server shuts down. */
|
|
83
|
+
destroy() {
|
|
84
|
+
clearInterval(this.cleanupTimer);
|
|
85
|
+
}
|
|
86
|
+
evictSyncSeen() {
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
for (const [n, exp] of this.syncSeen) {
|
|
89
|
+
if (exp < now)
|
|
90
|
+
this.syncSeen.delete(n);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=nonce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce.js","sourceRoot":"","sources":["../../src/messages/nonce.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aroha Protocol — Layer 3 Message Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* All message types defined by the Aroha spec (aroha/1.0).
|
|
5
|
+
* These are the ONLY valid values for the "type" field in a Aroha envelope.
|
|
6
|
+
*
|
|
7
|
+
* Applications may not invent new top-level message types — they extend
|
|
8
|
+
* behavior through the "body" field only.
|
|
9
|
+
*/
|
|
10
|
+
export interface WithCredential {
|
|
11
|
+
/**
|
|
12
|
+
* Registry-based auth: the credential ID returned on registration.
|
|
13
|
+
* The receiving agent resolves the full credential from the registry.
|
|
14
|
+
* Preferred over credentialToken for repeated calls — shorter and revocable.
|
|
15
|
+
*/
|
|
16
|
+
credentialId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Inline auth: base64url-encoded signed HumanCredential.
|
|
19
|
+
* Used when no shared registry is available (e.g. first call or direct peer).
|
|
20
|
+
* If credentialId is also present, credentialId takes precedence.
|
|
21
|
+
*/
|
|
22
|
+
credentialToken?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface PreferenceContext {
|
|
25
|
+
budget?: {
|
|
26
|
+
max: number;
|
|
27
|
+
currency: string;
|
|
28
|
+
};
|
|
29
|
+
quality?: {
|
|
30
|
+
minRating?: number;
|
|
31
|
+
};
|
|
32
|
+
accessibility?: Record<string, boolean | string>;
|
|
33
|
+
constraints?: string[];
|
|
34
|
+
/** Signed VC granting the recipient access to read this context */
|
|
35
|
+
consentToken?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ArohaRequestBody extends WithCredential {
|
|
38
|
+
capability: string;
|
|
39
|
+
params: Record<string, unknown>;
|
|
40
|
+
preferenceContext?: PreferenceContext;
|
|
41
|
+
/**
|
|
42
|
+
* Idempotency key — if set, the receiving agent deduplicates requests with
|
|
43
|
+
* the same key from the same sender within a 24-hour window.
|
|
44
|
+
* Prevents duplicate side effects on retried requests (e.g. double-booking).
|
|
45
|
+
* Use a UUID generated once per logical operation, not per retry attempt.
|
|
46
|
+
*/
|
|
47
|
+
idempotencyKey?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ArohaResponseBody {
|
|
50
|
+
capability: string;
|
|
51
|
+
result: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
export interface ArohaStreamBody {
|
|
54
|
+
capability: string;
|
|
55
|
+
progressPct: number;
|
|
56
|
+
event: string;
|
|
57
|
+
data?: Record<string, unknown>;
|
|
58
|
+
}
|
|
59
|
+
export interface CapabilitySchemaShape {
|
|
60
|
+
/** JSON Schema for the capability's input body (params field). */
|
|
61
|
+
input: Record<string, unknown>;
|
|
62
|
+
/** JSON Schema for the capability's expected output (result field). */
|
|
63
|
+
output?: Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
export interface CSNNegotiateExtension {
|
|
66
|
+
/**
|
|
67
|
+
* Natural-language description of what the requestor needs.
|
|
68
|
+
* The provider uses this as a hint when structural schema matching is
|
|
69
|
+
* ambiguous. Absent means "use schema-only matching".
|
|
70
|
+
*/
|
|
71
|
+
capabilityIntent?: string;
|
|
72
|
+
/**
|
|
73
|
+
* JSON Schema of the requestor's expected interface.
|
|
74
|
+
* The provider runs structural compatibility matching against its registry.
|
|
75
|
+
* If a high-confidence match is found, no LLM call is needed.
|
|
76
|
+
*/
|
|
77
|
+
desiredSchema?: CapabilitySchemaShape;
|
|
78
|
+
/**
|
|
79
|
+
* SHA-256 hex of the canonical desiredSchema JSON.
|
|
80
|
+
* The provider checks its cache first — if a mapping exists for this hash
|
|
81
|
+
* and this sender DID, the negotiation resolves in < 1ms without LLM.
|
|
82
|
+
*/
|
|
83
|
+
schemaHash?: string;
|
|
84
|
+
/**
|
|
85
|
+
* If true, the provider returns its full signed capability manifest
|
|
86
|
+
* in the ArohaAccept body. The requestor caches it for future calls.
|
|
87
|
+
*/
|
|
88
|
+
requestCapabilityManifest?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* When true, the provider MUST NOT use LLM-based fuzzy matching.
|
|
91
|
+
* If structural/cache match fails, return ArohaError with code CSN_NO_STRUCTURAL_MATCH.
|
|
92
|
+
*/
|
|
93
|
+
disallowLLMFallback?: boolean;
|
|
94
|
+
}
|
|
95
|
+
export interface CapabilityManifestEntry {
|
|
96
|
+
name: string;
|
|
97
|
+
description: string;
|
|
98
|
+
inputSchema: Record<string, unknown>;
|
|
99
|
+
outputSchema?: Record<string, unknown>;
|
|
100
|
+
supportsSaga: boolean;
|
|
101
|
+
defaultPricing?: {
|
|
102
|
+
model: "per-call" | "subscription" | "negotiated";
|
|
103
|
+
amount?: number;
|
|
104
|
+
currency?: string;
|
|
105
|
+
};
|
|
106
|
+
defaultSLA?: {
|
|
107
|
+
maxResponseMs: number;
|
|
108
|
+
p99Ms?: number;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export interface SignedCapabilityManifest {
|
|
112
|
+
agentDID: string;
|
|
113
|
+
capabilities: CapabilityManifestEntry[];
|
|
114
|
+
generatedAt: string;
|
|
115
|
+
/** Ed25519 signature over the canonical manifest JSON. */
|
|
116
|
+
signature: string;
|
|
117
|
+
}
|
|
118
|
+
export interface ArohaNegotiateBody {
|
|
119
|
+
capability: string;
|
|
120
|
+
proposedTerms: {
|
|
121
|
+
price?: {
|
|
122
|
+
amount: number;
|
|
123
|
+
currency: string;
|
|
124
|
+
};
|
|
125
|
+
sla?: {
|
|
126
|
+
maxResponseMs: number;
|
|
127
|
+
uptime: number;
|
|
128
|
+
};
|
|
129
|
+
validForMs?: number;
|
|
130
|
+
[key: string]: unknown;
|
|
131
|
+
};
|
|
132
|
+
/** CSN extension — omit for traditional price/SLA-only negotiation. */
|
|
133
|
+
csn?: CSNNegotiateExtension;
|
|
134
|
+
}
|
|
135
|
+
export interface CSNAcceptExtension {
|
|
136
|
+
/**
|
|
137
|
+
* The actual registered capability name that matched the intent/schema.
|
|
138
|
+
* May differ from the `capability` field when CSN resolves an alias.
|
|
139
|
+
*/
|
|
140
|
+
resolvedCapability?: string;
|
|
141
|
+
/** The schema the provider agreed to serve. Stored by requestor for caching. */
|
|
142
|
+
agreedSchema?: CapabilitySchemaShape;
|
|
143
|
+
/** Echo of the requestor's schemaHash — allows cache population. */
|
|
144
|
+
schemaHash?: string;
|
|
145
|
+
/** Returned when requestCapabilityManifest was true. */
|
|
146
|
+
capabilityManifest?: SignedCapabilityManifest;
|
|
147
|
+
/**
|
|
148
|
+
* How the capability was matched:
|
|
149
|
+
* "schema" — deterministic structural match (preferred, no LLM)
|
|
150
|
+
* "intent" — LLM-assisted match (less certain, human approval recommended)
|
|
151
|
+
* "cache" — recovered from SHA-256 negotiation cache (zero-latency)
|
|
152
|
+
*/
|
|
153
|
+
matchMethod?: "schema" | "intent" | "cache";
|
|
154
|
+
/** Structural compatibility score (0–1) when matchMethod is "schema". */
|
|
155
|
+
compatibilityScore?: number;
|
|
156
|
+
/**
|
|
157
|
+
* Audit trail of how the match was resolved.
|
|
158
|
+
* Consumers can use this to tune caching or flag unexpected LLM usage.
|
|
159
|
+
*/
|
|
160
|
+
matchAudit?: {
|
|
161
|
+
structuralScore?: number;
|
|
162
|
+
cacheHit?: boolean;
|
|
163
|
+
llmUsed: boolean;
|
|
164
|
+
llmModel?: string;
|
|
165
|
+
fallbackReason?: string;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
export interface ArohaCounterOfferBody {
|
|
169
|
+
capability: string;
|
|
170
|
+
revisedTerms: ArohaNegotiateBody["proposedTerms"];
|
|
171
|
+
csn?: Pick<CSNAcceptExtension, "resolvedCapability" | "agreedSchema" | "capabilityManifest">;
|
|
172
|
+
}
|
|
173
|
+
export interface ArohaAcceptBody {
|
|
174
|
+
capability: string;
|
|
175
|
+
acceptedTerms: ArohaNegotiateBody["proposedTerms"];
|
|
176
|
+
/** CSN extension — present when the accept resolves a capability schema match. */
|
|
177
|
+
csn?: CSNAcceptExtension;
|
|
178
|
+
}
|
|
179
|
+
export interface ArohaReserveBody extends WithCredential {
|
|
180
|
+
capability: string;
|
|
181
|
+
params: Record<string, unknown>;
|
|
182
|
+
holdDurationMs: number;
|
|
183
|
+
preferenceContext?: PreferenceContext;
|
|
184
|
+
}
|
|
185
|
+
export interface ArohaReserveAckBody {
|
|
186
|
+
reservationToken: string;
|
|
187
|
+
expiresAt: string;
|
|
188
|
+
}
|
|
189
|
+
export interface ArohaCommitBody {
|
|
190
|
+
reservationToken: string;
|
|
191
|
+
}
|
|
192
|
+
export interface ArohaCommitAckBody {
|
|
193
|
+
reservationToken: string;
|
|
194
|
+
result: Record<string, unknown>;
|
|
195
|
+
}
|
|
196
|
+
export interface ArohaCancelBody {
|
|
197
|
+
reservationToken: string;
|
|
198
|
+
reason: string;
|
|
199
|
+
}
|
|
200
|
+
export interface ArohaCancelAckBody {
|
|
201
|
+
reservationToken: string;
|
|
202
|
+
}
|
|
203
|
+
export interface ArohaDelegateBody extends WithCredential {
|
|
204
|
+
targetDID: string;
|
|
205
|
+
capability: string;
|
|
206
|
+
params: Record<string, unknown>;
|
|
207
|
+
preferenceContext?: PreferenceContext;
|
|
208
|
+
}
|
|
209
|
+
export interface ArohaErrorBody {
|
|
210
|
+
code: ArohaErrorCode;
|
|
211
|
+
message: string;
|
|
212
|
+
retryable: boolean;
|
|
213
|
+
details?: Record<string, unknown>;
|
|
214
|
+
}
|
|
215
|
+
export interface ArohaSatisfactionSignalBody {
|
|
216
|
+
sagaId: string;
|
|
217
|
+
agentDID: string;
|
|
218
|
+
/** The capability this signal applies to (e.g. "search-flights"). */
|
|
219
|
+
capability: string;
|
|
220
|
+
outcome: "satisfied" | "neutral" | "dissatisfied";
|
|
221
|
+
dimensions: {
|
|
222
|
+
price: "satisfied" | "neutral" | "dissatisfied";
|
|
223
|
+
quality: "satisfied" | "neutral" | "dissatisfied";
|
|
224
|
+
speed: "satisfied" | "neutral" | "dissatisfied";
|
|
225
|
+
};
|
|
226
|
+
/** Whether the saga completed within the provider's stated SLA. */
|
|
227
|
+
withinSLA: boolean;
|
|
228
|
+
/** Whether a compensation (ArohaCancel) was required to recover. */
|
|
229
|
+
requiredCompensation: boolean;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* ArohaSpendingMandate — Layer 1 authorization token for agent payments.
|
|
233
|
+
*
|
|
234
|
+
* Enables agents to spend funds on behalf of a user without ever seeing
|
|
235
|
+
* raw payment credentials. Each hop in the delegation chain can only
|
|
236
|
+
* narrow constraints — never widen them.
|
|
237
|
+
*
|
|
238
|
+
* Mandate chain: User (intent) → Personal Agent (cart) → Provider (payment).
|
|
239
|
+
*
|
|
240
|
+
* References:
|
|
241
|
+
* AP2 Protocol (Google) — Intent/Cart/Payment Mandate pattern.
|
|
242
|
+
* IETF draft-niyikiza-oauth-attenuating-agent-tokens — monotonic scope narrowing.
|
|
243
|
+
*/
|
|
244
|
+
export interface ArohaSpendingMandateBody {
|
|
245
|
+
mandateTier: "intent" | "cart" | "payment";
|
|
246
|
+
constraints: SpendingConstraints;
|
|
247
|
+
grantee: string;
|
|
248
|
+
grantor: string;
|
|
249
|
+
expiresAt: string;
|
|
250
|
+
parentMandateId: string | null;
|
|
251
|
+
mandateId: string;
|
|
252
|
+
}
|
|
253
|
+
export interface SpendingConstraints {
|
|
254
|
+
spendLimitUsd: number;
|
|
255
|
+
sessionLimitUsd?: number;
|
|
256
|
+
currency?: string;
|
|
257
|
+
merchantCategory?: string | null;
|
|
258
|
+
requireHumanApprovalAboveUsd?: number;
|
|
259
|
+
allowedMerchants?: string[] | null;
|
|
260
|
+
validFrom?: string;
|
|
261
|
+
validUntil?: string;
|
|
262
|
+
}
|
|
263
|
+
export declare enum ArohaErrorCode {
|
|
264
|
+
Unauthorized = "Aroha_UNAUTHORIZED",// missing or invalid credential
|
|
265
|
+
Forbidden = "Aroha_FORBIDDEN",// credential valid but role denied
|
|
266
|
+
InvalidSignature = "Aroha_INVALID_SIGNATURE",
|
|
267
|
+
ExpiredMessage = "Aroha_EXPIRED_MESSAGE",
|
|
268
|
+
ReplayDetected = "Aroha_REPLAY_DETECTED",
|
|
269
|
+
UnknownCapability = "Aroha_UNKNOWN_CAPABILITY",
|
|
270
|
+
TrustLevelInsufficient = "Aroha_TRUST_LEVEL_INSUFFICIENT",
|
|
271
|
+
ReservationFailed = "Aroha_RESERVATION_FAILED",
|
|
272
|
+
ReservationExpired = "Aroha_RESERVATION_EXPIRED",
|
|
273
|
+
CommitFailed = "Aroha_COMMIT_FAILED",
|
|
274
|
+
CancelFailed = "Aroha_CANCEL_FAILED",
|
|
275
|
+
InvalidToken = "Aroha_INVALID_TOKEN",
|
|
276
|
+
NoInventory = "Aroha_NO_INVENTORY",
|
|
277
|
+
CapacityExceeded = "Aroha_CAPACITY_EXCEEDED",
|
|
278
|
+
ServiceUnavailable = "Aroha_SERVICE_UNAVAILABLE",
|
|
279
|
+
InternalError = "Aroha_INTERNAL_ERROR",
|
|
280
|
+
InvalidParams = "Aroha_INVALID_PARAMS",
|
|
281
|
+
CSN_NO_STRUCTURAL_MATCH = "CSN_NO_STRUCTURAL_MATCH"
|
|
282
|
+
}
|
|
283
|
+
export type ArohaMessageType = "ArohaRequest" | "ArohaResponse" | "ArohaStream" | "ArohaNegotiate" | "ArohaCounterOffer" | "ArohaAccept" | "ArohaReserve" | "ArohaReserveAck" | "ArohaCommit" | "ArohaCommitAck" | "ArohaCancel" | "ArohaCancelAck" | "ArohaDelegate" | "ArohaError" | "ArohaSatisfactionSignal" | "ArohaSpendingMandate";
|
|
284
|
+
export type ArohaBodyByType = {
|
|
285
|
+
ArohaRequest: ArohaRequestBody;
|
|
286
|
+
ArohaResponse: ArohaResponseBody;
|
|
287
|
+
ArohaStream: ArohaStreamBody;
|
|
288
|
+
ArohaNegotiate: ArohaNegotiateBody;
|
|
289
|
+
ArohaCounterOffer: ArohaCounterOfferBody;
|
|
290
|
+
ArohaAccept: ArohaAcceptBody;
|
|
291
|
+
ArohaReserve: ArohaReserveBody;
|
|
292
|
+
ArohaReserveAck: ArohaReserveAckBody;
|
|
293
|
+
ArohaCommit: ArohaCommitBody;
|
|
294
|
+
ArohaCommitAck: ArohaCommitAckBody;
|
|
295
|
+
ArohaCancel: ArohaCancelBody;
|
|
296
|
+
ArohaCancelAck: ArohaCancelAckBody;
|
|
297
|
+
ArohaDelegate: ArohaDelegateBody;
|
|
298
|
+
ArohaError: ArohaErrorBody;
|
|
299
|
+
ArohaSatisfactionSignal: ArohaSatisfactionSignalBody;
|
|
300
|
+
ArohaSpendingMandate: ArohaSpendingMandateBody;
|
|
301
|
+
};
|
|
302
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messages/types.ts"],"names":[],"mappings":"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"}
|