@hasna/contacts 0.6.2 → 0.6.4
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/index.js +94 -21
- package/dist/db/documents.d.ts +1 -0
- package/dist/db/documents.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +72 -20
- package/dist/lib/vault.d.ts +10 -1
- package/dist/lib/vault.d.ts.map +1 -1
- package/dist/mcp/index.js +74 -23
- package/dist/server/index.js +22 -0
- package/dist/server/serve.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4813,6 +4813,25 @@ async function handleExport(req) {
|
|
|
4813
4813
|
}
|
|
4814
4814
|
});
|
|
4815
4815
|
}
|
|
4816
|
+
function handleDocumentFiles(req, segments) {
|
|
4817
|
+
const docId = segments[2];
|
|
4818
|
+
const sub = segments[3];
|
|
4819
|
+
if (!docId)
|
|
4820
|
+
return apiError("Document ID required");
|
|
4821
|
+
if (req.method !== "GET")
|
|
4822
|
+
return apiError("Method not allowed", 405);
|
|
4823
|
+
if (sub === "file") {
|
|
4824
|
+
const db = getDatabase();
|
|
4825
|
+
const row = db.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(docId);
|
|
4826
|
+
if (!row?.encrypted_file_path || !existsSync4(row.encrypted_file_path)) {
|
|
4827
|
+
return new Response("No file attachment", { status: 404 });
|
|
4828
|
+
}
|
|
4829
|
+
return new Response(Bun.file(row.encrypted_file_path), {
|
|
4830
|
+
headers: { "Cache-Control": "public, max-age=3600" }
|
|
4831
|
+
});
|
|
4832
|
+
}
|
|
4833
|
+
return apiError("Use /api/documents/:id/file to get the attachment", 400);
|
|
4834
|
+
}
|
|
4816
4835
|
async function handleImages(req, _url, segments) {
|
|
4817
4836
|
const entityId = segments[2];
|
|
4818
4837
|
if (!entityId)
|
|
@@ -4909,6 +4928,9 @@ function startServer(port) {
|
|
|
4909
4928
|
case "images":
|
|
4910
4929
|
response = await handleImages(req, url, segments);
|
|
4911
4930
|
break;
|
|
4931
|
+
case "documents":
|
|
4932
|
+
response = handleDocumentFiles(req, segments);
|
|
4933
|
+
break;
|
|
4912
4934
|
default:
|
|
4913
4935
|
response = apiError("Not found", 404);
|
|
4914
4936
|
}
|
|
@@ -6052,23 +6074,53 @@ var init_org_chart = __esm(() => {
|
|
|
6052
6074
|
var exports_vault = {};
|
|
6053
6075
|
__export(exports_vault, {
|
|
6054
6076
|
unlockVault: () => unlockVault,
|
|
6077
|
+
storeFile: () => storeFile,
|
|
6055
6078
|
requireVault: () => requireVault,
|
|
6056
6079
|
lockVault: () => lockVault,
|
|
6057
6080
|
isVaultUnlocked: () => isVaultUnlocked,
|
|
6058
6081
|
isVaultInitialized: () => isVaultInitialized,
|
|
6059
6082
|
initVault: () => initVault,
|
|
6060
6083
|
getDocumentsDir: () => getDocumentsDir,
|
|
6061
|
-
|
|
6084
|
+
getDocumentFilePath: () => getDocumentFilePath,
|
|
6062
6085
|
encrypt: () => encrypt,
|
|
6063
6086
|
decryptFile: () => decryptFile,
|
|
6064
6087
|
decrypt: () => decrypt
|
|
6065
6088
|
});
|
|
6066
|
-
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
6089
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, unlinkSync as unlinkSync2 } from "fs";
|
|
6067
6090
|
import { join as join5 } from "path";
|
|
6068
6091
|
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync, createHash } from "crypto";
|
|
6069
6092
|
function deriveKey(passphrase, salt) {
|
|
6070
6093
|
return pbkdf2Sync(passphrase, salt, 1e5, 32, "sha512");
|
|
6071
6094
|
}
|
|
6095
|
+
function saveSession(key) {
|
|
6096
|
+
const session = {
|
|
6097
|
+
key: key.toString("hex"),
|
|
6098
|
+
expires_at: new Date(Date.now() + SESSION_TTL_MS).toISOString()
|
|
6099
|
+
};
|
|
6100
|
+
writeFileSync3(VAULT_SESSION, JSON.stringify(session), { mode: 384 });
|
|
6101
|
+
}
|
|
6102
|
+
function loadSession() {
|
|
6103
|
+
if (!existsSync5(VAULT_SESSION))
|
|
6104
|
+
return null;
|
|
6105
|
+
try {
|
|
6106
|
+
const session = JSON.parse(readFileSync3(VAULT_SESSION, "utf-8"));
|
|
6107
|
+
if (new Date(session.expires_at).getTime() < Date.now()) {
|
|
6108
|
+
try {
|
|
6109
|
+
unlinkSync2(VAULT_SESSION);
|
|
6110
|
+
} catch {}
|
|
6111
|
+
return null;
|
|
6112
|
+
}
|
|
6113
|
+
return Buffer.from(session.key, "hex");
|
|
6114
|
+
} catch {
|
|
6115
|
+
return null;
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
function clearSession() {
|
|
6119
|
+
try {
|
|
6120
|
+
if (existsSync5(VAULT_SESSION))
|
|
6121
|
+
unlinkSync2(VAULT_SESSION);
|
|
6122
|
+
} catch {}
|
|
6123
|
+
}
|
|
6072
6124
|
function initVault(passphrase) {
|
|
6073
6125
|
if (!existsSync5(VAULT_DIR))
|
|
6074
6126
|
mkdirSync4(VAULT_DIR, { recursive: true });
|
|
@@ -6080,6 +6132,7 @@ function initVault(passphrase) {
|
|
|
6080
6132
|
const config = { salt: salt.toString("hex"), key_hash: keyHash, created_at: new Date().toISOString() };
|
|
6081
6133
|
writeFileSync3(VAULT_CONFIG, JSON.stringify(config, null, 2));
|
|
6082
6134
|
_derivedKey = key;
|
|
6135
|
+
saveSession(key);
|
|
6083
6136
|
}
|
|
6084
6137
|
function isVaultInitialized() {
|
|
6085
6138
|
return existsSync5(VAULT_CONFIG);
|
|
@@ -6094,18 +6147,32 @@ function unlockVault(passphrase) {
|
|
|
6094
6147
|
if (keyHash !== config.key_hash)
|
|
6095
6148
|
return false;
|
|
6096
6149
|
_derivedKey = key;
|
|
6150
|
+
saveSession(key);
|
|
6097
6151
|
return true;
|
|
6098
6152
|
}
|
|
6099
6153
|
function lockVault() {
|
|
6100
6154
|
_derivedKey = null;
|
|
6155
|
+
clearSession();
|
|
6101
6156
|
}
|
|
6102
6157
|
function isVaultUnlocked() {
|
|
6103
|
-
|
|
6158
|
+
if (_derivedKey)
|
|
6159
|
+
return true;
|
|
6160
|
+
const sessionKey = loadSession();
|
|
6161
|
+
if (sessionKey) {
|
|
6162
|
+
_derivedKey = sessionKey;
|
|
6163
|
+
return true;
|
|
6164
|
+
}
|
|
6165
|
+
return false;
|
|
6104
6166
|
}
|
|
6105
6167
|
function requireVault() {
|
|
6106
|
-
if (
|
|
6107
|
-
|
|
6108
|
-
|
|
6168
|
+
if (_derivedKey)
|
|
6169
|
+
return _derivedKey;
|
|
6170
|
+
const sessionKey = loadSession();
|
|
6171
|
+
if (sessionKey) {
|
|
6172
|
+
_derivedKey = sessionKey;
|
|
6173
|
+
return _derivedKey;
|
|
6174
|
+
}
|
|
6175
|
+
throw new Error("Vault is locked. Unlock with 'contacts vault unlock --passphrase <pass>' or vault_unlock MCP tool first.");
|
|
6109
6176
|
}
|
|
6110
6177
|
function encrypt(plaintext) {
|
|
6111
6178
|
const key = requireVault();
|
|
@@ -6127,20 +6194,23 @@ function decrypt(ciphertext, iv) {
|
|
|
6127
6194
|
decrypted += decipher.final("utf8");
|
|
6128
6195
|
return decrypted;
|
|
6129
6196
|
}
|
|
6130
|
-
function
|
|
6131
|
-
const key = requireVault();
|
|
6197
|
+
function storeFile(sourcePath, entityId) {
|
|
6132
6198
|
if (!existsSync5(DOCUMENTS_DIR))
|
|
6133
6199
|
mkdirSync4(DOCUMENTS_DIR, { recursive: true });
|
|
6200
|
+
const ext = sourcePath.split(".").pop() || "bin";
|
|
6201
|
+
const destPath = join5(DOCUMENTS_DIR, `${entityId}.${ext}`);
|
|
6134
6202
|
const data = readFileSync3(sourcePath);
|
|
6135
|
-
|
|
6136
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
6137
|
-
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
6138
|
-
const authTag = cipher.getAuthTag();
|
|
6139
|
-
const destPath = join5(DOCUMENTS_DIR, `${entityId}.enc`);
|
|
6140
|
-
const output = Buffer.concat([iv, authTag, encrypted]);
|
|
6141
|
-
writeFileSync3(destPath, output);
|
|
6203
|
+
writeFileSync3(destPath, data);
|
|
6142
6204
|
return destPath;
|
|
6143
6205
|
}
|
|
6206
|
+
function getDocumentFilePath(entityId) {
|
|
6207
|
+
if (!existsSync5(DOCUMENTS_DIR))
|
|
6208
|
+
return null;
|
|
6209
|
+
const { readdirSync: readdirSync2 } = __require("fs");
|
|
6210
|
+
const files = readdirSync2(DOCUMENTS_DIR);
|
|
6211
|
+
const match = files.find((f) => f.startsWith(`${entityId}.`) && !f.endsWith(".enc"));
|
|
6212
|
+
return match ? join5(DOCUMENTS_DIR, match) : null;
|
|
6213
|
+
}
|
|
6144
6214
|
function decryptFile(encPath) {
|
|
6145
6215
|
const key = requireVault();
|
|
6146
6216
|
const data = readFileSync3(encPath);
|
|
@@ -6156,11 +6226,13 @@ function getDocumentsDir() {
|
|
|
6156
6226
|
mkdirSync4(DOCUMENTS_DIR, { recursive: true });
|
|
6157
6227
|
return DOCUMENTS_DIR;
|
|
6158
6228
|
}
|
|
6159
|
-
var VAULT_DIR, VAULT_CONFIG, DOCUMENTS_DIR, _derivedKey = null;
|
|
6229
|
+
var VAULT_DIR, VAULT_CONFIG, VAULT_SESSION, DOCUMENTS_DIR, SESSION_TTL_MS, _derivedKey = null;
|
|
6160
6230
|
var init_vault = __esm(() => {
|
|
6161
6231
|
VAULT_DIR = join5(process.env["HOME"] || "~", ".contacts");
|
|
6162
6232
|
VAULT_CONFIG = join5(VAULT_DIR, "vault.json");
|
|
6233
|
+
VAULT_SESSION = join5(VAULT_DIR, ".vault-session");
|
|
6163
6234
|
DOCUMENTS_DIR = join5(VAULT_DIR, "documents");
|
|
6235
|
+
SESSION_TTL_MS = 30 * 60 * 1000;
|
|
6164
6236
|
});
|
|
6165
6237
|
|
|
6166
6238
|
// src/db/documents.ts
|
|
@@ -6172,17 +6244,17 @@ __export(exports_documents, {
|
|
|
6172
6244
|
addDocument: () => addDocument,
|
|
6173
6245
|
DOCUMENT_TYPES: () => DOCUMENT_TYPES
|
|
6174
6246
|
});
|
|
6175
|
-
import { existsSync as existsSync6, unlinkSync as
|
|
6247
|
+
import { existsSync as existsSync6, unlinkSync as unlinkSync3 } from "fs";
|
|
6176
6248
|
function addDocument(input, db) {
|
|
6177
6249
|
requireVault();
|
|
6178
6250
|
const _db2 = db || getDatabase();
|
|
6179
6251
|
const id = uuid();
|
|
6180
6252
|
const { ciphertext, iv } = encrypt(input.value);
|
|
6181
|
-
let
|
|
6253
|
+
let filePath = null;
|
|
6182
6254
|
if (input.file_path) {
|
|
6183
|
-
|
|
6255
|
+
filePath = storeFile(input.file_path, id);
|
|
6184
6256
|
}
|
|
6185
|
-
_db2.query(`INSERT INTO contact_documents (id, contact_id, doc_type, label, encrypted_value, iv, encrypted_file_path, metadata, expires_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(id, input.contact_id, input.doc_type, input.label ?? null, ciphertext, iv,
|
|
6257
|
+
_db2.query(`INSERT INTO contact_documents (id, contact_id, doc_type, label, encrypted_value, iv, encrypted_file_path, metadata, expires_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(id, input.contact_id, input.doc_type, input.label ?? null, ciphertext, iv, filePath, JSON.stringify(input.metadata || {}), input.expires_at ?? null, now(), now());
|
|
6186
6258
|
return getDocument(id, _db2);
|
|
6187
6259
|
}
|
|
6188
6260
|
function getDocument(id, db) {
|
|
@@ -6210,7 +6282,7 @@ function deleteDocument(id, db) {
|
|
|
6210
6282
|
const row = _db2.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(id);
|
|
6211
6283
|
if (row?.encrypted_file_path && existsSync6(row.encrypted_file_path)) {
|
|
6212
6284
|
try {
|
|
6213
|
-
|
|
6285
|
+
unlinkSync3(row.encrypted_file_path);
|
|
6214
6286
|
} catch {}
|
|
6215
6287
|
}
|
|
6216
6288
|
_db2.query(`DELETE FROM contact_documents WHERE id = ?`).run(id);
|
|
@@ -6223,6 +6295,7 @@ function rowToDoc(row) {
|
|
|
6223
6295
|
label: row.label,
|
|
6224
6296
|
value: decrypt(row.encrypted_value, row.iv),
|
|
6225
6297
|
has_file: !!row.encrypted_file_path,
|
|
6298
|
+
file_path: row.encrypted_file_path,
|
|
6226
6299
|
metadata: JSON.parse(row.metadata || "{}"),
|
|
6227
6300
|
expires_at: row.expires_at,
|
|
6228
6301
|
created_at: row.created_at,
|
package/dist/db/documents.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/db/documents.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,cAAc,wSAMjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,mBAAmB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,eAAe,CAYtF;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,eAAe,CAMtE;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,sBAAsB,EAAE,CASxF;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAO9D"}
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/db/documents.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,cAAc,wSAMjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,mBAAmB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,eAAe,CAYtF;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,eAAe,CAMtE;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,sBAAsB,EAAE,CASxF;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAO9D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export type { ParsedSignature } from "./lib/signature-parser.js";
|
|
|
62
62
|
export { ingestMeetingParticipants } from "./lib/meeting-capture.js";
|
|
63
63
|
export { findOrCreateContact } from "./db/contacts.js";
|
|
64
64
|
export { saveImage, getImagePath, getImageAsBase64, deleteImage, listImages, getImagesDir } from "./lib/images.js";
|
|
65
|
-
export { initVault, unlockVault, lockVault, isVaultUnlocked, isVaultInitialized, encrypt, decrypt,
|
|
65
|
+
export { initVault, unlockVault, lockVault, isVaultUnlocked, isVaultInitialized, encrypt, decrypt, storeFile, getDocumentFilePath, decryptFile, requireVault, getDocumentsDir } from "./lib/vault.js";
|
|
66
66
|
export { addDocument, getDocument, listDocuments, deleteDocument, DOCUMENT_TYPES } from "./db/documents.js";
|
|
67
67
|
export type { DocumentType, ContactDocument, ContactDocumentSummary, CreateDocumentInput } from "./db/documents.js";
|
|
68
68
|
export { setHealthData, getHealthData, deleteHealthData } from "./db/health.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
12
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
13
|
+
var __require = import.meta.require;
|
|
13
14
|
|
|
14
15
|
// src/db/database.ts
|
|
15
16
|
import { Database } from "bun:sqlite";
|
|
@@ -4503,16 +4504,47 @@ function listImages() {
|
|
|
4503
4504
|
}));
|
|
4504
4505
|
}
|
|
4505
4506
|
// src/lib/vault.ts
|
|
4506
|
-
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
4507
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
4507
4508
|
import { join as join4 } from "path";
|
|
4508
4509
|
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync, createHash } from "crypto";
|
|
4509
4510
|
var VAULT_DIR = join4(process.env["HOME"] || "~", ".contacts");
|
|
4510
4511
|
var VAULT_CONFIG = join4(VAULT_DIR, "vault.json");
|
|
4512
|
+
var VAULT_SESSION = join4(VAULT_DIR, ".vault-session");
|
|
4511
4513
|
var DOCUMENTS_DIR = join4(VAULT_DIR, "documents");
|
|
4514
|
+
var SESSION_TTL_MS = 30 * 60 * 1000;
|
|
4512
4515
|
var _derivedKey = null;
|
|
4513
4516
|
function deriveKey(passphrase, salt) {
|
|
4514
4517
|
return pbkdf2Sync(passphrase, salt, 1e5, 32, "sha512");
|
|
4515
4518
|
}
|
|
4519
|
+
function saveSession(key) {
|
|
4520
|
+
const session = {
|
|
4521
|
+
key: key.toString("hex"),
|
|
4522
|
+
expires_at: new Date(Date.now() + SESSION_TTL_MS).toISOString()
|
|
4523
|
+
};
|
|
4524
|
+
writeFileSync2(VAULT_SESSION, JSON.stringify(session), { mode: 384 });
|
|
4525
|
+
}
|
|
4526
|
+
function loadSession() {
|
|
4527
|
+
if (!existsSync4(VAULT_SESSION))
|
|
4528
|
+
return null;
|
|
4529
|
+
try {
|
|
4530
|
+
const session = JSON.parse(readFileSync3(VAULT_SESSION, "utf-8"));
|
|
4531
|
+
if (new Date(session.expires_at).getTime() < Date.now()) {
|
|
4532
|
+
try {
|
|
4533
|
+
unlinkSync2(VAULT_SESSION);
|
|
4534
|
+
} catch {}
|
|
4535
|
+
return null;
|
|
4536
|
+
}
|
|
4537
|
+
return Buffer.from(session.key, "hex");
|
|
4538
|
+
} catch {
|
|
4539
|
+
return null;
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
function clearSession() {
|
|
4543
|
+
try {
|
|
4544
|
+
if (existsSync4(VAULT_SESSION))
|
|
4545
|
+
unlinkSync2(VAULT_SESSION);
|
|
4546
|
+
} catch {}
|
|
4547
|
+
}
|
|
4516
4548
|
function initVault(passphrase) {
|
|
4517
4549
|
if (!existsSync4(VAULT_DIR))
|
|
4518
4550
|
mkdirSync3(VAULT_DIR, { recursive: true });
|
|
@@ -4524,6 +4556,7 @@ function initVault(passphrase) {
|
|
|
4524
4556
|
const config = { salt: salt.toString("hex"), key_hash: keyHash, created_at: new Date().toISOString() };
|
|
4525
4557
|
writeFileSync2(VAULT_CONFIG, JSON.stringify(config, null, 2));
|
|
4526
4558
|
_derivedKey = key;
|
|
4559
|
+
saveSession(key);
|
|
4527
4560
|
}
|
|
4528
4561
|
function isVaultInitialized() {
|
|
4529
4562
|
return existsSync4(VAULT_CONFIG);
|
|
@@ -4538,18 +4571,32 @@ function unlockVault(passphrase) {
|
|
|
4538
4571
|
if (keyHash !== config.key_hash)
|
|
4539
4572
|
return false;
|
|
4540
4573
|
_derivedKey = key;
|
|
4574
|
+
saveSession(key);
|
|
4541
4575
|
return true;
|
|
4542
4576
|
}
|
|
4543
4577
|
function lockVault() {
|
|
4544
4578
|
_derivedKey = null;
|
|
4579
|
+
clearSession();
|
|
4545
4580
|
}
|
|
4546
4581
|
function isVaultUnlocked() {
|
|
4547
|
-
|
|
4582
|
+
if (_derivedKey)
|
|
4583
|
+
return true;
|
|
4584
|
+
const sessionKey = loadSession();
|
|
4585
|
+
if (sessionKey) {
|
|
4586
|
+
_derivedKey = sessionKey;
|
|
4587
|
+
return true;
|
|
4588
|
+
}
|
|
4589
|
+
return false;
|
|
4548
4590
|
}
|
|
4549
4591
|
function requireVault() {
|
|
4550
|
-
if (
|
|
4551
|
-
|
|
4552
|
-
|
|
4592
|
+
if (_derivedKey)
|
|
4593
|
+
return _derivedKey;
|
|
4594
|
+
const sessionKey = loadSession();
|
|
4595
|
+
if (sessionKey) {
|
|
4596
|
+
_derivedKey = sessionKey;
|
|
4597
|
+
return _derivedKey;
|
|
4598
|
+
}
|
|
4599
|
+
throw new Error("Vault is locked. Unlock with 'contacts vault unlock --passphrase <pass>' or vault_unlock MCP tool first.");
|
|
4553
4600
|
}
|
|
4554
4601
|
function encrypt(plaintext) {
|
|
4555
4602
|
const key = requireVault();
|
|
@@ -4571,20 +4618,23 @@ function decrypt(ciphertext, iv) {
|
|
|
4571
4618
|
decrypted += decipher.final("utf8");
|
|
4572
4619
|
return decrypted;
|
|
4573
4620
|
}
|
|
4574
|
-
function
|
|
4575
|
-
const key = requireVault();
|
|
4621
|
+
function storeFile(sourcePath, entityId) {
|
|
4576
4622
|
if (!existsSync4(DOCUMENTS_DIR))
|
|
4577
4623
|
mkdirSync3(DOCUMENTS_DIR, { recursive: true });
|
|
4624
|
+
const ext = sourcePath.split(".").pop() || "bin";
|
|
4625
|
+
const destPath = join4(DOCUMENTS_DIR, `${entityId}.${ext}`);
|
|
4578
4626
|
const data = readFileSync3(sourcePath);
|
|
4579
|
-
|
|
4580
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
4581
|
-
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
4582
|
-
const authTag = cipher.getAuthTag();
|
|
4583
|
-
const destPath = join4(DOCUMENTS_DIR, `${entityId}.enc`);
|
|
4584
|
-
const output = Buffer.concat([iv, authTag, encrypted]);
|
|
4585
|
-
writeFileSync2(destPath, output);
|
|
4627
|
+
writeFileSync2(destPath, data);
|
|
4586
4628
|
return destPath;
|
|
4587
4629
|
}
|
|
4630
|
+
function getDocumentFilePath(entityId) {
|
|
4631
|
+
if (!existsSync4(DOCUMENTS_DIR))
|
|
4632
|
+
return null;
|
|
4633
|
+
const { readdirSync: readdirSync2 } = __require("fs");
|
|
4634
|
+
const files = readdirSync2(DOCUMENTS_DIR);
|
|
4635
|
+
const match = files.find((f) => f.startsWith(`${entityId}.`) && !f.endsWith(".enc"));
|
|
4636
|
+
return match ? join4(DOCUMENTS_DIR, match) : null;
|
|
4637
|
+
}
|
|
4588
4638
|
function decryptFile(encPath) {
|
|
4589
4639
|
const key = requireVault();
|
|
4590
4640
|
const data = readFileSync3(encPath);
|
|
@@ -4602,7 +4652,7 @@ function getDocumentsDir() {
|
|
|
4602
4652
|
}
|
|
4603
4653
|
// src/db/documents.ts
|
|
4604
4654
|
init_database();
|
|
4605
|
-
import { existsSync as existsSync5, unlinkSync as
|
|
4655
|
+
import { existsSync as existsSync5, unlinkSync as unlinkSync3 } from "fs";
|
|
4606
4656
|
var DOCUMENT_TYPES = [
|
|
4607
4657
|
"passport",
|
|
4608
4658
|
"national_id",
|
|
@@ -4629,11 +4679,11 @@ function addDocument(input, db) {
|
|
|
4629
4679
|
const _db2 = db || getDatabase();
|
|
4630
4680
|
const id = uuid();
|
|
4631
4681
|
const { ciphertext, iv } = encrypt(input.value);
|
|
4632
|
-
let
|
|
4682
|
+
let filePath = null;
|
|
4633
4683
|
if (input.file_path) {
|
|
4634
|
-
|
|
4684
|
+
filePath = storeFile(input.file_path, id);
|
|
4635
4685
|
}
|
|
4636
|
-
_db2.query(`INSERT INTO contact_documents (id, contact_id, doc_type, label, encrypted_value, iv, encrypted_file_path, metadata, expires_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(id, input.contact_id, input.doc_type, input.label ?? null, ciphertext, iv,
|
|
4686
|
+
_db2.query(`INSERT INTO contact_documents (id, contact_id, doc_type, label, encrypted_value, iv, encrypted_file_path, metadata, expires_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(id, input.contact_id, input.doc_type, input.label ?? null, ciphertext, iv, filePath, JSON.stringify(input.metadata || {}), input.expires_at ?? null, now(), now());
|
|
4637
4687
|
return getDocument(id, _db2);
|
|
4638
4688
|
}
|
|
4639
4689
|
function getDocument(id, db) {
|
|
@@ -4661,7 +4711,7 @@ function deleteDocument(id, db) {
|
|
|
4661
4711
|
const row = _db2.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(id);
|
|
4662
4712
|
if (row?.encrypted_file_path && existsSync5(row.encrypted_file_path)) {
|
|
4663
4713
|
try {
|
|
4664
|
-
|
|
4714
|
+
unlinkSync3(row.encrypted_file_path);
|
|
4665
4715
|
} catch {}
|
|
4666
4716
|
}
|
|
4667
4717
|
_db2.query(`DELETE FROM contact_documents WHERE id = ?`).run(id);
|
|
@@ -4674,6 +4724,7 @@ function rowToDoc(row) {
|
|
|
4674
4724
|
label: row.label,
|
|
4675
4725
|
value: decrypt(row.encrypted_value, row.iv),
|
|
4676
4726
|
has_file: !!row.encrypted_file_path,
|
|
4727
|
+
file_path: row.encrypted_file_path,
|
|
4677
4728
|
metadata: JSON.parse(row.metadata || "{}"),
|
|
4678
4729
|
expires_at: row.expires_at,
|
|
4679
4730
|
created_at: row.created_at,
|
|
@@ -4881,6 +4932,7 @@ export {
|
|
|
4881
4932
|
unlockVault,
|
|
4882
4933
|
unarchiveContact,
|
|
4883
4934
|
unarchiveCompany,
|
|
4935
|
+
storeFile,
|
|
4884
4936
|
setHealthData,
|
|
4885
4937
|
setDealContactRole,
|
|
4886
4938
|
semanticSearch,
|
|
@@ -4987,6 +5039,7 @@ export {
|
|
|
4987
5039
|
getEvent,
|
|
4988
5040
|
getEntityTeam,
|
|
4989
5041
|
getDocumentsDir,
|
|
5042
|
+
getDocumentFilePath,
|
|
4990
5043
|
getDocument,
|
|
4991
5044
|
getDealsByStage,
|
|
4992
5045
|
getDealTeam,
|
|
@@ -5014,7 +5067,6 @@ export {
|
|
|
5014
5067
|
extractContactsFromEmailThread,
|
|
5015
5068
|
exportFromApple,
|
|
5016
5069
|
exportContacts,
|
|
5017
|
-
encryptFile,
|
|
5018
5070
|
encrypt,
|
|
5019
5071
|
embedContact,
|
|
5020
5072
|
embedAllContacts,
|
package/dist/lib/vault.d.ts
CHANGED
|
@@ -9,7 +9,16 @@ export declare function encrypt(plaintext: string): {
|
|
|
9
9
|
iv: string;
|
|
10
10
|
};
|
|
11
11
|
export declare function decrypt(ciphertext: string, iv: string): string;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Store a file attachment (PLAIN, not encrypted) so agents can access it directly.
|
|
14
|
+
* Text values in the DB are encrypted; file attachments are plain for agent access.
|
|
15
|
+
* Returns the destination path.
|
|
16
|
+
*/
|
|
17
|
+
export declare function storeFile(sourcePath: string, entityId: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Get the file path for a document attachment. Returns null if no file exists.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getDocumentFilePath(entityId: string): string | null;
|
|
13
22
|
export declare function decryptFile(encPath: string): Buffer;
|
|
14
23
|
export declare function getDocumentsDir(): string;
|
|
15
24
|
//# sourceMappingURL=vault.d.ts.map
|
package/dist/lib/vault.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../src/lib/vault.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../src/lib/vault.ts"],"names":[],"mappings":"AAgDA,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAUlD;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAUvD;AAED,wBAAgB,SAAS,IAAI,IAAI,CAGhC;AAED,wBAAgB,eAAe,IAAI,OAAO,CASzC;AAED,wBAAgB,YAAY,IAAI,MAAM,CASrC;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAQ7E;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAS9D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOtE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMnE;AAGD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASnD;AAED,wBAAgB,eAAe,IAAI,MAAM,CAGxC"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -4317,16 +4317,47 @@ function deleteImage(entityId) {
|
|
|
4317
4317
|
}
|
|
4318
4318
|
|
|
4319
4319
|
// src/lib/vault.ts
|
|
4320
|
-
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
4320
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
4321
4321
|
import { join as join4 } from "path";
|
|
4322
4322
|
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync, createHash } from "crypto";
|
|
4323
4323
|
var VAULT_DIR = join4(process.env["HOME"] || "~", ".contacts");
|
|
4324
4324
|
var VAULT_CONFIG = join4(VAULT_DIR, "vault.json");
|
|
4325
|
+
var VAULT_SESSION = join4(VAULT_DIR, ".vault-session");
|
|
4325
4326
|
var DOCUMENTS_DIR = join4(VAULT_DIR, "documents");
|
|
4327
|
+
var SESSION_TTL_MS = 30 * 60 * 1000;
|
|
4326
4328
|
var _derivedKey = null;
|
|
4327
4329
|
function deriveKey(passphrase, salt) {
|
|
4328
4330
|
return pbkdf2Sync(passphrase, salt, 1e5, 32, "sha512");
|
|
4329
4331
|
}
|
|
4332
|
+
function saveSession(key) {
|
|
4333
|
+
const session = {
|
|
4334
|
+
key: key.toString("hex"),
|
|
4335
|
+
expires_at: new Date(Date.now() + SESSION_TTL_MS).toISOString()
|
|
4336
|
+
};
|
|
4337
|
+
writeFileSync2(VAULT_SESSION, JSON.stringify(session), { mode: 384 });
|
|
4338
|
+
}
|
|
4339
|
+
function loadSession() {
|
|
4340
|
+
if (!existsSync4(VAULT_SESSION))
|
|
4341
|
+
return null;
|
|
4342
|
+
try {
|
|
4343
|
+
const session = JSON.parse(readFileSync3(VAULT_SESSION, "utf-8"));
|
|
4344
|
+
if (new Date(session.expires_at).getTime() < Date.now()) {
|
|
4345
|
+
try {
|
|
4346
|
+
unlinkSync2(VAULT_SESSION);
|
|
4347
|
+
} catch {}
|
|
4348
|
+
return null;
|
|
4349
|
+
}
|
|
4350
|
+
return Buffer.from(session.key, "hex");
|
|
4351
|
+
} catch {
|
|
4352
|
+
return null;
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4355
|
+
function clearSession() {
|
|
4356
|
+
try {
|
|
4357
|
+
if (existsSync4(VAULT_SESSION))
|
|
4358
|
+
unlinkSync2(VAULT_SESSION);
|
|
4359
|
+
} catch {}
|
|
4360
|
+
}
|
|
4330
4361
|
function initVault(passphrase) {
|
|
4331
4362
|
if (!existsSync4(VAULT_DIR))
|
|
4332
4363
|
mkdirSync3(VAULT_DIR, { recursive: true });
|
|
@@ -4338,6 +4369,7 @@ function initVault(passphrase) {
|
|
|
4338
4369
|
const config = { salt: salt.toString("hex"), key_hash: keyHash, created_at: new Date().toISOString() };
|
|
4339
4370
|
writeFileSync2(VAULT_CONFIG, JSON.stringify(config, null, 2));
|
|
4340
4371
|
_derivedKey = key;
|
|
4372
|
+
saveSession(key);
|
|
4341
4373
|
}
|
|
4342
4374
|
function isVaultInitialized() {
|
|
4343
4375
|
return existsSync4(VAULT_CONFIG);
|
|
@@ -4352,18 +4384,32 @@ function unlockVault(passphrase) {
|
|
|
4352
4384
|
if (keyHash !== config.key_hash)
|
|
4353
4385
|
return false;
|
|
4354
4386
|
_derivedKey = key;
|
|
4387
|
+
saveSession(key);
|
|
4355
4388
|
return true;
|
|
4356
4389
|
}
|
|
4357
4390
|
function lockVault() {
|
|
4358
4391
|
_derivedKey = null;
|
|
4392
|
+
clearSession();
|
|
4359
4393
|
}
|
|
4360
4394
|
function isVaultUnlocked() {
|
|
4361
|
-
|
|
4395
|
+
if (_derivedKey)
|
|
4396
|
+
return true;
|
|
4397
|
+
const sessionKey = loadSession();
|
|
4398
|
+
if (sessionKey) {
|
|
4399
|
+
_derivedKey = sessionKey;
|
|
4400
|
+
return true;
|
|
4401
|
+
}
|
|
4402
|
+
return false;
|
|
4362
4403
|
}
|
|
4363
4404
|
function requireVault() {
|
|
4364
|
-
if (
|
|
4365
|
-
|
|
4366
|
-
|
|
4405
|
+
if (_derivedKey)
|
|
4406
|
+
return _derivedKey;
|
|
4407
|
+
const sessionKey = loadSession();
|
|
4408
|
+
if (sessionKey) {
|
|
4409
|
+
_derivedKey = sessionKey;
|
|
4410
|
+
return _derivedKey;
|
|
4411
|
+
}
|
|
4412
|
+
throw new Error("Vault is locked. Unlock with 'contacts vault unlock --passphrase <pass>' or vault_unlock MCP tool first.");
|
|
4367
4413
|
}
|
|
4368
4414
|
function encrypt(plaintext) {
|
|
4369
4415
|
const key = requireVault();
|
|
@@ -4385,24 +4431,19 @@ function decrypt(ciphertext, iv) {
|
|
|
4385
4431
|
decrypted += decipher.final("utf8");
|
|
4386
4432
|
return decrypted;
|
|
4387
4433
|
}
|
|
4388
|
-
function
|
|
4389
|
-
const key = requireVault();
|
|
4434
|
+
function storeFile(sourcePath, entityId) {
|
|
4390
4435
|
if (!existsSync4(DOCUMENTS_DIR))
|
|
4391
4436
|
mkdirSync3(DOCUMENTS_DIR, { recursive: true });
|
|
4437
|
+
const ext = sourcePath.split(".").pop() || "bin";
|
|
4438
|
+
const destPath = join4(DOCUMENTS_DIR, `${entityId}.${ext}`);
|
|
4392
4439
|
const data = readFileSync3(sourcePath);
|
|
4393
|
-
|
|
4394
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
4395
|
-
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
4396
|
-
const authTag = cipher.getAuthTag();
|
|
4397
|
-
const destPath = join4(DOCUMENTS_DIR, `${entityId}.enc`);
|
|
4398
|
-
const output = Buffer.concat([iv, authTag, encrypted]);
|
|
4399
|
-
writeFileSync2(destPath, output);
|
|
4440
|
+
writeFileSync2(destPath, data);
|
|
4400
4441
|
return destPath;
|
|
4401
4442
|
}
|
|
4402
4443
|
|
|
4403
4444
|
// src/db/documents.ts
|
|
4404
4445
|
init_database();
|
|
4405
|
-
import { existsSync as existsSync5, unlinkSync as
|
|
4446
|
+
import { existsSync as existsSync5, unlinkSync as unlinkSync3 } from "fs";
|
|
4406
4447
|
var DOCUMENT_TYPES = [
|
|
4407
4448
|
"passport",
|
|
4408
4449
|
"national_id",
|
|
@@ -4429,11 +4470,11 @@ function addDocument(input, db) {
|
|
|
4429
4470
|
const _db2 = db || getDatabase();
|
|
4430
4471
|
const id = uuid();
|
|
4431
4472
|
const { ciphertext, iv } = encrypt(input.value);
|
|
4432
|
-
let
|
|
4473
|
+
let filePath = null;
|
|
4433
4474
|
if (input.file_path) {
|
|
4434
|
-
|
|
4475
|
+
filePath = storeFile(input.file_path, id);
|
|
4435
4476
|
}
|
|
4436
|
-
_db2.query(`INSERT INTO contact_documents (id, contact_id, doc_type, label, encrypted_value, iv, encrypted_file_path, metadata, expires_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(id, input.contact_id, input.doc_type, input.label ?? null, ciphertext, iv,
|
|
4477
|
+
_db2.query(`INSERT INTO contact_documents (id, contact_id, doc_type, label, encrypted_value, iv, encrypted_file_path, metadata, expires_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(id, input.contact_id, input.doc_type, input.label ?? null, ciphertext, iv, filePath, JSON.stringify(input.metadata || {}), input.expires_at ?? null, now(), now());
|
|
4437
4478
|
return getDocument(id, _db2);
|
|
4438
4479
|
}
|
|
4439
4480
|
function getDocument(id, db) {
|
|
@@ -4461,7 +4502,7 @@ function deleteDocument(id, db) {
|
|
|
4461
4502
|
const row = _db2.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(id);
|
|
4462
4503
|
if (row?.encrypted_file_path && existsSync5(row.encrypted_file_path)) {
|
|
4463
4504
|
try {
|
|
4464
|
-
|
|
4505
|
+
unlinkSync3(row.encrypted_file_path);
|
|
4465
4506
|
} catch {}
|
|
4466
4507
|
}
|
|
4467
4508
|
_db2.query(`DELETE FROM contact_documents WHERE id = ?`).run(id);
|
|
@@ -4474,6 +4515,7 @@ function rowToDoc(row) {
|
|
|
4474
4515
|
label: row.label,
|
|
4475
4516
|
value: decrypt(row.encrypted_value, row.iv),
|
|
4476
4517
|
has_file: !!row.encrypted_file_path,
|
|
4518
|
+
file_path: row.encrypted_file_path,
|
|
4477
4519
|
metadata: JSON.parse(row.metadata || "{}"),
|
|
4478
4520
|
expires_at: row.expires_at,
|
|
4479
4521
|
created_at: row.created_at,
|
|
@@ -6146,10 +6188,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
6146
6188
|
{ name: "vault_unlock", description: "Unlock the vault for this session with a passphrase.", inputSchema: { type: "object", properties: { passphrase: { type: "string" } }, required: ["passphrase"] } },
|
|
6147
6189
|
{ name: "vault_lock", description: "Lock the vault, clearing the encryption key from memory.", inputSchema: { type: "object", properties: {} } },
|
|
6148
6190
|
{ name: "vault_status", description: "Check vault initialization and lock status.", inputSchema: { type: "object", properties: {} } },
|
|
6149
|
-
{ name: "add_document", description: "Store
|
|
6150
|
-
{ name: "list_documents", description: "List documents for a contact (metadata only \u2014 no decryption needed).", inputSchema: { type: "object", properties: { contact_id: { type: "string" } }, required: ["contact_id"] } },
|
|
6151
|
-
{ name: "get_document", description: "Get a document with decrypted value. Vault must be unlocked.", inputSchema: { type: "object", properties: { document_id: { type: "string" } }, required: ["document_id"] } },
|
|
6152
|
-
{ name: "
|
|
6191
|
+
{ name: "add_document", description: "Store a document for a contact (passport, tax_id, medical_record, etc.). Text values are encrypted; file attachments are stored plain so agents can read them. Vault must be unlocked.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, doc_type: { type: "string", enum: [...DOCUMENT_TYPES] }, label: { type: "string" }, value: { type: "string", description: "Plaintext value (will be encrypted in DB)" }, file_path: { type: "string", description: "File to attach \u2014 stored PLAIN in ~/.contacts/documents/ for agent access" }, metadata: { type: "object" }, expires_at: { type: "string" } }, required: ["contact_id", "doc_type", "value"] } },
|
|
6192
|
+
{ name: "list_documents", description: "List documents for a contact (metadata only \u2014 no decryption needed). Returns file_path for attachments so agents can read them directly.", inputSchema: { type: "object", properties: { contact_id: { type: "string" } }, required: ["contact_id"] } },
|
|
6193
|
+
{ name: "get_document", description: "Get a document with decrypted value and file_path. Vault must be unlocked for the text value; file is always accessible.", inputSchema: { type: "object", properties: { document_id: { type: "string" } }, required: ["document_id"] } },
|
|
6194
|
+
{ name: "get_document_file", description: "Get the plain file path for a document attachment. Agents can read this file directly \u2014 it is NOT encrypted. Returns null if no file attached.", inputSchema: { type: "object", properties: { document_id: { type: "string" } }, required: ["document_id"] } },
|
|
6195
|
+
{ name: "delete_document", description: "Delete a document and its file attachment.", inputSchema: { type: "object", properties: { document_id: { type: "string" } }, required: ["document_id"] } },
|
|
6153
6196
|
{ name: "scan_document", description: "Scan a document image using AI vision (OpenAI GPT-4o) to extract structured data. Optionally auto-save to vault.", inputSchema: { type: "object", properties: { image: { type: "string", description: "File path or base64 image data" }, doc_type: { type: "string", description: "Hint: passport, national_id, drivers_license, etc." }, contact_id: { type: "string", description: "Contact to associate scanned document with" }, auto_save: { type: "boolean", description: "Automatically save extracted data as a vault document" } }, required: ["image"] } },
|
|
6154
6197
|
{ name: "set_health_data", description: "Set or update health data for a contact. Vault must be unlocked.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, blood_type: { type: "string" }, allergies: { type: "array", items: { type: "string" } }, medical_conditions: { type: "array", items: { type: "string" } }, medications: { type: "array", items: { type: "string" } }, emergency_contacts: { type: "array", items: { type: "object", properties: { name: { type: "string" }, phone: { type: "string" }, relationship: { type: "string" } }, required: ["name", "phone", "relationship"] } }, health_insurance_provider: { type: "string" }, health_insurance_id: { type: "string" }, primary_physician: { type: "string" }, primary_physician_phone: { type: "string" }, organ_donor: { type: "boolean" }, notes: { type: "string" } }, required: ["contact_id"] } },
|
|
6155
6198
|
{ name: "get_health_data", description: "Get health data for a contact. Vault must be unlocked.", inputSchema: { type: "object", properties: { contact_id: { type: "string" } }, required: ["contact_id"] } },
|
|
@@ -7737,6 +7780,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
7737
7780
|
const doc = getDocument(a.document_id);
|
|
7738
7781
|
return { content: [{ type: "text", text: JSON.stringify(doc, null, 2) }] };
|
|
7739
7782
|
}
|
|
7783
|
+
case "get_document_file": {
|
|
7784
|
+
const db = getDatabase();
|
|
7785
|
+
const row = db.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(a.document_id);
|
|
7786
|
+
if (!row)
|
|
7787
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "Document not found" }) }], isError: true };
|
|
7788
|
+
const filePath = row.encrypted_file_path;
|
|
7789
|
+
return { content: [{ type: "text", text: JSON.stringify({ document_id: a.document_id, file_path: filePath, has_file: !!filePath }) }] };
|
|
7790
|
+
}
|
|
7740
7791
|
case "delete_document": {
|
|
7741
7792
|
deleteDocument(a.document_id);
|
|
7742
7793
|
return { content: [{ type: "text", text: JSON.stringify({ deleted: true }) }] };
|
package/dist/server/index.js
CHANGED
|
@@ -2035,6 +2035,25 @@ async function handleExport(req) {
|
|
|
2035
2035
|
}
|
|
2036
2036
|
});
|
|
2037
2037
|
}
|
|
2038
|
+
function handleDocumentFiles(req, segments) {
|
|
2039
|
+
const docId = segments[2];
|
|
2040
|
+
const sub = segments[3];
|
|
2041
|
+
if (!docId)
|
|
2042
|
+
return apiError("Document ID required");
|
|
2043
|
+
if (req.method !== "GET")
|
|
2044
|
+
return apiError("Method not allowed", 405);
|
|
2045
|
+
if (sub === "file") {
|
|
2046
|
+
const db = getDatabase();
|
|
2047
|
+
const row = db.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(docId);
|
|
2048
|
+
if (!row?.encrypted_file_path || !existsSync3(row.encrypted_file_path)) {
|
|
2049
|
+
return new Response("No file attachment", { status: 404 });
|
|
2050
|
+
}
|
|
2051
|
+
return new Response(Bun.file(row.encrypted_file_path), {
|
|
2052
|
+
headers: { "Cache-Control": "public, max-age=3600" }
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
return apiError("Use /api/documents/:id/file to get the attachment", 400);
|
|
2056
|
+
}
|
|
2038
2057
|
async function handleImages(req, _url, segments) {
|
|
2039
2058
|
const entityId = segments[2];
|
|
2040
2059
|
if (!entityId)
|
|
@@ -2131,6 +2150,9 @@ function startServer(port) {
|
|
|
2131
2150
|
case "images":
|
|
2132
2151
|
response = await handleImages(req, url, segments);
|
|
2133
2152
|
break;
|
|
2153
|
+
case "documents":
|
|
2154
|
+
response = handleDocumentFiles(req, segments);
|
|
2155
|
+
break;
|
|
2134
2156
|
default:
|
|
2135
2157
|
response = apiError("Not found", 404);
|
|
2136
2158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"AA2WA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA4E9C"}
|