@agentvault/agentvault 0.17.5 → 0.18.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/cli.js +231 -1
- package/dist/cli.js.map +4 -4
- package/dist/index.js +246 -10
- package/dist/index.js.map +4 -4
- package/dist/openclaw-entry.js +45057 -87
- package/dist/openclaw-entry.js.map +4 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -46204,6 +46204,123 @@ var init_dist = __esm({
|
|
|
46204
46204
|
}
|
|
46205
46205
|
});
|
|
46206
46206
|
|
|
46207
|
+
// src/credential-store.ts
|
|
46208
|
+
var CredentialStore;
|
|
46209
|
+
var init_credential_store = __esm({
|
|
46210
|
+
"src/credential-store.ts"() {
|
|
46211
|
+
"use strict";
|
|
46212
|
+
CredentialStore = class _CredentialStore {
|
|
46213
|
+
/** Map<roomId, Map<credentialKey, RenterCredential>> */
|
|
46214
|
+
_store = /* @__PURE__ */ new Map();
|
|
46215
|
+
/** Seen nonces for replay prevention — bounded per room */
|
|
46216
|
+
_seenNonces = /* @__PURE__ */ new Map();
|
|
46217
|
+
static MAX_NONCES_PER_ROOM = 1e3;
|
|
46218
|
+
constructor() {
|
|
46219
|
+
const purge = () => this.purgeAll();
|
|
46220
|
+
process.on("exit", purge);
|
|
46221
|
+
process.on("SIGINT", () => {
|
|
46222
|
+
purge();
|
|
46223
|
+
process.exit(0);
|
|
46224
|
+
});
|
|
46225
|
+
process.on("SIGTERM", () => {
|
|
46226
|
+
purge();
|
|
46227
|
+
process.exit(0);
|
|
46228
|
+
});
|
|
46229
|
+
}
|
|
46230
|
+
/**
|
|
46231
|
+
* Check if a nonce has been seen (replay prevention).
|
|
46232
|
+
* Returns true if the nonce is new (not a replay), false if seen before.
|
|
46233
|
+
*/
|
|
46234
|
+
checkNonce(roomId, nonce) {
|
|
46235
|
+
if (!nonce) return true;
|
|
46236
|
+
let nonces = this._seenNonces.get(roomId);
|
|
46237
|
+
if (!nonces) {
|
|
46238
|
+
nonces = /* @__PURE__ */ new Set();
|
|
46239
|
+
this._seenNonces.set(roomId, nonces);
|
|
46240
|
+
}
|
|
46241
|
+
if (nonces.has(nonce)) return false;
|
|
46242
|
+
nonces.add(nonce);
|
|
46243
|
+
if (nonces.size > _CredentialStore.MAX_NONCES_PER_ROOM) {
|
|
46244
|
+
const iter = nonces.values();
|
|
46245
|
+
for (let i2 = 0; i2 < 100; i2++) {
|
|
46246
|
+
const val = iter.next().value;
|
|
46247
|
+
if (val !== void 0) nonces.delete(val);
|
|
46248
|
+
}
|
|
46249
|
+
}
|
|
46250
|
+
return true;
|
|
46251
|
+
}
|
|
46252
|
+
/** Store a credential for a room. */
|
|
46253
|
+
grant(roomId, credential) {
|
|
46254
|
+
let room = this._store.get(roomId);
|
|
46255
|
+
if (!room) {
|
|
46256
|
+
room = /* @__PURE__ */ new Map();
|
|
46257
|
+
this._store.set(roomId, room);
|
|
46258
|
+
}
|
|
46259
|
+
room.set(credential.key, credential);
|
|
46260
|
+
}
|
|
46261
|
+
/** Revoke a specific credential. */
|
|
46262
|
+
revoke(roomId, key) {
|
|
46263
|
+
const room = this._store.get(roomId);
|
|
46264
|
+
if (!room) return false;
|
|
46265
|
+
return room.delete(key);
|
|
46266
|
+
}
|
|
46267
|
+
/** Revoke all credentials for a room. */
|
|
46268
|
+
revokeAll(roomId) {
|
|
46269
|
+
this._store.delete(roomId);
|
|
46270
|
+
}
|
|
46271
|
+
/** Get a credential value. */
|
|
46272
|
+
get(roomId, key) {
|
|
46273
|
+
return this._store.get(roomId)?.get(key);
|
|
46274
|
+
}
|
|
46275
|
+
/** Get all credentials for a room (values included — only for agent context injection). */
|
|
46276
|
+
getAll(roomId) {
|
|
46277
|
+
const room = this._store.get(roomId);
|
|
46278
|
+
if (!room) return [];
|
|
46279
|
+
return Array.from(room.values());
|
|
46280
|
+
}
|
|
46281
|
+
/** Get credential info without values (safe for logging). */
|
|
46282
|
+
getInfo(roomId) {
|
|
46283
|
+
const room = this._store.get(roomId);
|
|
46284
|
+
if (!room) return [];
|
|
46285
|
+
return Array.from(room.values()).map((c2) => ({
|
|
46286
|
+
key: c2.key,
|
|
46287
|
+
type: c2.type,
|
|
46288
|
+
scope: c2.scope,
|
|
46289
|
+
grantedAt: c2.grantedAt
|
|
46290
|
+
}));
|
|
46291
|
+
}
|
|
46292
|
+
/** Check if a specific credential exists. */
|
|
46293
|
+
has(roomId, key) {
|
|
46294
|
+
return this._store.get(roomId)?.has(key) ?? false;
|
|
46295
|
+
}
|
|
46296
|
+
/** Get credential count for a room. */
|
|
46297
|
+
count(roomId) {
|
|
46298
|
+
return this._store.get(roomId)?.size ?? 0;
|
|
46299
|
+
}
|
|
46300
|
+
/** Purge all credentials for a room (rental end). */
|
|
46301
|
+
purgeForRoom(roomId) {
|
|
46302
|
+
this._store.delete(roomId);
|
|
46303
|
+
this._seenNonces.delete(roomId);
|
|
46304
|
+
}
|
|
46305
|
+
/** Purge everything (process exit). */
|
|
46306
|
+
purgeAll() {
|
|
46307
|
+
this._store.clear();
|
|
46308
|
+
this._seenNonces.clear();
|
|
46309
|
+
}
|
|
46310
|
+
/** Get a map of credential key → value for context injection. */
|
|
46311
|
+
getCredentialMap(roomId) {
|
|
46312
|
+
const room = this._store.get(roomId);
|
|
46313
|
+
if (!room) return {};
|
|
46314
|
+
const result = {};
|
|
46315
|
+
for (const [key, cred] of room) {
|
|
46316
|
+
result[key] = cred.value;
|
|
46317
|
+
}
|
|
46318
|
+
return result;
|
|
46319
|
+
}
|
|
46320
|
+
};
|
|
46321
|
+
}
|
|
46322
|
+
});
|
|
46323
|
+
|
|
46207
46324
|
// src/crypto-helpers.ts
|
|
46208
46325
|
var init_crypto_helpers = __esm({
|
|
46209
46326
|
async "src/crypto-helpers.ts"() {
|
|
@@ -46873,12 +46990,13 @@ function migratePersistedState(raw) {
|
|
|
46873
46990
|
messageHistory: []
|
|
46874
46991
|
};
|
|
46875
46992
|
}
|
|
46876
|
-
var ROOM_AGENT_TYPES, POLL_INTERVAL_MS, RECONNECT_BASE_MS, RECONNECT_MAX_MS, PENDING_POLL_INTERVAL_MS, SecureChannel;
|
|
46993
|
+
var ROOM_AGENT_TYPES, CREDENTIAL_MESSAGE_TYPES, POLL_INTERVAL_MS, RECONNECT_BASE_MS, RECONNECT_MAX_MS, PENDING_POLL_INTERVAL_MS, SecureChannel;
|
|
46877
46994
|
var init_channel = __esm({
|
|
46878
46995
|
async "src/channel.ts"() {
|
|
46879
46996
|
"use strict";
|
|
46880
46997
|
await init_libsodium_wrappers();
|
|
46881
46998
|
await init_dist();
|
|
46999
|
+
init_credential_store();
|
|
46882
47000
|
await init_crypto_helpers();
|
|
46883
47001
|
await init_state();
|
|
46884
47002
|
init_transport2();
|
|
@@ -46889,6 +47007,11 @@ var init_channel = __esm({
|
|
|
46889
47007
|
"decision_response",
|
|
46890
47008
|
"artifact_share"
|
|
46891
47009
|
]);
|
|
47010
|
+
CREDENTIAL_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
47011
|
+
"credential_grant",
|
|
47012
|
+
"credential_revoke",
|
|
47013
|
+
"credential_request"
|
|
47014
|
+
]);
|
|
46892
47015
|
POLL_INTERVAL_MS = 6e3;
|
|
46893
47016
|
RECONNECT_BASE_MS = 1e3;
|
|
46894
47017
|
RECONNECT_MAX_MS = 3e4;
|
|
@@ -46931,6 +47054,8 @@ var init_channel = __esm({
|
|
|
46931
47054
|
_senderKeyChains = /* @__PURE__ */ new Map();
|
|
46932
47055
|
/** Sender Key peer state — peer chains per room for decryption */
|
|
46933
47056
|
_senderKeyStates = /* @__PURE__ */ new Map();
|
|
47057
|
+
/** In-memory credential store for renter-provided credentials (never persisted). */
|
|
47058
|
+
_credentialStore = new CredentialStore();
|
|
46934
47059
|
/** Queued A2A messages for responder channels not yet activated (no first initiator message received). */
|
|
46935
47060
|
_a2aPendingQueue = {};
|
|
46936
47061
|
/** Dedup buffer for A2A message IDs (prevents double-delivery via direct + Redis) */
|
|
@@ -49717,6 +49842,14 @@ ${messageText}`;
|
|
|
49717
49842
|
messageType = "message";
|
|
49718
49843
|
messageText = plaintext;
|
|
49719
49844
|
}
|
|
49845
|
+
if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
|
|
49846
|
+
this._handleCredentialMessage(msgData.room_id, messageType, messageText, msgData.message_id);
|
|
49847
|
+
if (msgData.created_at && this._persisted) {
|
|
49848
|
+
this._persisted.lastMessageTimestamp = msgData.created_at;
|
|
49849
|
+
}
|
|
49850
|
+
await this._persistState();
|
|
49851
|
+
return;
|
|
49852
|
+
}
|
|
49720
49853
|
if (!ROOM_AGENT_TYPES.has(messageType)) {
|
|
49721
49854
|
return;
|
|
49722
49855
|
}
|
|
@@ -49753,6 +49886,94 @@ ${messageText}`;
|
|
|
49753
49886
|
console.error("[SecureChannel] onMessage callback error:", err);
|
|
49754
49887
|
});
|
|
49755
49888
|
}
|
|
49889
|
+
/**
|
|
49890
|
+
* Handle credential protocol messages (grant, revoke, request).
|
|
49891
|
+
* These are intercepted before reaching the agent's onMessage callback.
|
|
49892
|
+
*/
|
|
49893
|
+
_handleCredentialMessage(roomId, messageType, plaintext, messageId) {
|
|
49894
|
+
try {
|
|
49895
|
+
const payload = JSON.parse(plaintext);
|
|
49896
|
+
if (messageType === "credential_grant") {
|
|
49897
|
+
const grant = payload;
|
|
49898
|
+
if (grant.nonce && !this._credentialStore.checkNonce(roomId, grant.nonce)) {
|
|
49899
|
+
console.warn(`[SecureChannel] Credential grant replay detected for room ${roomId.slice(0, 8)}..., ignoring`);
|
|
49900
|
+
return;
|
|
49901
|
+
}
|
|
49902
|
+
const keys = [];
|
|
49903
|
+
for (const cred of grant.credentials || []) {
|
|
49904
|
+
this._credentialStore.grant(roomId, {
|
|
49905
|
+
key: cred.key,
|
|
49906
|
+
value: cred.value,
|
|
49907
|
+
type: cred.type,
|
|
49908
|
+
scope: cred.scope,
|
|
49909
|
+
grantedAt: grant.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
49910
|
+
agreementId: grant.agreement_id,
|
|
49911
|
+
roomId
|
|
49912
|
+
});
|
|
49913
|
+
keys.push(cred.key);
|
|
49914
|
+
}
|
|
49915
|
+
console.log(
|
|
49916
|
+
`[SecureChannel] Credentials granted for room ${roomId.slice(0, 8)}...: ${keys.join(", ")} (${keys.length} keys)`
|
|
49917
|
+
);
|
|
49918
|
+
this._sendCredentialAck(roomId, grant.agreement_id, keys, "stored");
|
|
49919
|
+
this.emit("credentials_granted", { roomId, keys, agreementId: grant.agreement_id });
|
|
49920
|
+
} else if (messageType === "credential_revoke") {
|
|
49921
|
+
const revoke = payload;
|
|
49922
|
+
const revoked = [];
|
|
49923
|
+
for (const key of revoke.credential_keys || []) {
|
|
49924
|
+
if (this._credentialStore.revoke(roomId, key)) {
|
|
49925
|
+
revoked.push(key);
|
|
49926
|
+
}
|
|
49927
|
+
}
|
|
49928
|
+
console.log(
|
|
49929
|
+
`[SecureChannel] Credentials revoked for room ${roomId.slice(0, 8)}...: ${revoked.join(", ")} (reason: ${revoke.reason || "none"})`
|
|
49930
|
+
);
|
|
49931
|
+
this._sendCredentialAck(roomId, revoke.agreement_id, revoked, "revoked");
|
|
49932
|
+
this.emit("credentials_revoked", { roomId, keys: revoked, agreementId: revoke.agreement_id });
|
|
49933
|
+
}
|
|
49934
|
+
} catch (err) {
|
|
49935
|
+
console.error("[SecureChannel] Error handling credential message:", err);
|
|
49936
|
+
}
|
|
49937
|
+
if (messageId) {
|
|
49938
|
+
this._sendAck(messageId);
|
|
49939
|
+
}
|
|
49940
|
+
}
|
|
49941
|
+
/**
|
|
49942
|
+
* Send a credential_ack back to a room.
|
|
49943
|
+
*/
|
|
49944
|
+
_sendCredentialAck(roomId, agreementId, keys, ackStatus) {
|
|
49945
|
+
const ack = JSON.stringify({
|
|
49946
|
+
type: "credential_ack",
|
|
49947
|
+
agreement_id: agreementId,
|
|
49948
|
+
acknowledged_keys: keys,
|
|
49949
|
+
status: ackStatus,
|
|
49950
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
49951
|
+
});
|
|
49952
|
+
this.sendToRoom(roomId, ack, { messageType: "credential_ack" }).catch((err) => {
|
|
49953
|
+
console.warn("[SecureChannel] Failed to send credential ACK:", err);
|
|
49954
|
+
});
|
|
49955
|
+
}
|
|
49956
|
+
// --- Public credential accessors ---
|
|
49957
|
+
/** Get a specific renter credential for a room. */
|
|
49958
|
+
getCredential(roomId, key) {
|
|
49959
|
+
return this._credentialStore.get(roomId, key);
|
|
49960
|
+
}
|
|
49961
|
+
/** Get all renter credentials for a room (includes values — for agent context). */
|
|
49962
|
+
getCredentials(roomId) {
|
|
49963
|
+
return this._credentialStore.getAll(roomId);
|
|
49964
|
+
}
|
|
49965
|
+
/** Get credential key→value map for a room (for context injection). */
|
|
49966
|
+
getCredentialMap(roomId) {
|
|
49967
|
+
return this._credentialStore.getCredentialMap(roomId);
|
|
49968
|
+
}
|
|
49969
|
+
/** Check if a specific credential exists for a room. */
|
|
49970
|
+
hasCredential(roomId, key) {
|
|
49971
|
+
return this._credentialStore.has(roomId, key);
|
|
49972
|
+
}
|
|
49973
|
+
/** Purge all credentials for a room (call on rental end). */
|
|
49974
|
+
purgeRoomCredentials(roomId) {
|
|
49975
|
+
this._credentialStore.purgeForRoom(roomId);
|
|
49976
|
+
}
|
|
49756
49977
|
/**
|
|
49757
49978
|
* Find the pairwise conversation ID for a given sender in a room.
|
|
49758
49979
|
*/
|
|
@@ -49915,6 +50136,14 @@ ${messageText}`;
|
|
|
49915
50136
|
messageType = "message";
|
|
49916
50137
|
messageText = plaintext;
|
|
49917
50138
|
}
|
|
50139
|
+
if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
|
|
50140
|
+
this._handleCredentialMessage(msgData.room_id, messageType, messageText, msgData.message_id);
|
|
50141
|
+
if (msgData.created_at && this._persisted) {
|
|
50142
|
+
this._persisted.lastMessageTimestamp = msgData.created_at;
|
|
50143
|
+
}
|
|
50144
|
+
await this._persistState();
|
|
50145
|
+
return;
|
|
50146
|
+
}
|
|
49918
50147
|
if (!ROOM_AGENT_TYPES.has(messageType)) {
|
|
49919
50148
|
return;
|
|
49920
50149
|
}
|
|
@@ -71149,6 +71378,7 @@ var init_index = __esm({
|
|
|
71149
71378
|
"use strict";
|
|
71150
71379
|
await init_channel();
|
|
71151
71380
|
init_types();
|
|
71381
|
+
init_credential_store();
|
|
71152
71382
|
init_account_config();
|
|
71153
71383
|
await init_openclaw_plugin();
|
|
71154
71384
|
init_gateway_send();
|