fivocell 6.0.2 → 6.1.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/__tests__/archive-versioning.test.d.ts +2 -0
- package/dist/__tests__/archive-versioning.test.d.ts.map +1 -0
- package/dist/__tests__/archive-versioning.test.js +131 -0
- package/dist/__tests__/archive-versioning.test.js.map +1 -0
- package/dist/__tests__/blob-vault.test.d.ts +2 -0
- package/dist/__tests__/blob-vault.test.d.ts.map +1 -0
- package/dist/__tests__/blob-vault.test.js +125 -0
- package/dist/__tests__/blob-vault.test.js.map +1 -0
- package/dist/__tests__/cell-mirror.test.d.ts +2 -0
- package/dist/__tests__/cell-mirror.test.d.ts.map +1 -0
- package/dist/__tests__/cell-mirror.test.js +122 -0
- package/dist/__tests__/cell-mirror.test.js.map +1 -0
- package/dist/__tests__/context-pipeline.test.d.ts +2 -0
- package/dist/__tests__/context-pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/context-pipeline.test.js +119 -0
- package/dist/__tests__/context-pipeline.test.js.map +1 -0
- package/dist/__tests__/key-provider.test.d.ts +2 -0
- package/dist/__tests__/key-provider.test.d.ts.map +1 -0
- package/dist/__tests__/key-provider.test.js +74 -0
- package/dist/__tests__/key-provider.test.js.map +1 -0
- package/dist/walls/06-memory/archive/archive-versioning.d.ts +33 -0
- package/dist/walls/06-memory/archive/archive-versioning.d.ts.map +1 -0
- package/dist/walls/06-memory/archive/archive-versioning.js +201 -0
- package/dist/walls/06-memory/archive/archive-versioning.js.map +1 -0
- package/dist/walls/06-memory/archive/blob-vault.d.ts +47 -0
- package/dist/walls/06-memory/archive/blob-vault.d.ts.map +1 -0
- package/dist/walls/06-memory/archive/blob-vault.js +272 -0
- package/dist/walls/06-memory/archive/blob-vault.js.map +1 -0
- package/dist/walls/06-memory/archive/memory-archive.d.ts.map +1 -1
- package/dist/walls/06-memory/archive/memory-archive.js +19 -5
- package/dist/walls/06-memory/archive/memory-archive.js.map +1 -1
- package/dist/walls/06-memory/database/database.d.ts.map +1 -1
- package/dist/walls/06-memory/database/database.js +63 -22
- package/dist/walls/06-memory/database/database.js.map +1 -1
- package/dist/walls/06-memory/mirror/cell-mirror.d.ts +30 -0
- package/dist/walls/06-memory/mirror/cell-mirror.d.ts.map +1 -0
- package/dist/walls/06-memory/mirror/cell-mirror.js +297 -0
- package/dist/walls/06-memory/mirror/cell-mirror.js.map +1 -0
- package/dist/walls/06-memory/privacy/key-migration.d.ts +14 -0
- package/dist/walls/06-memory/privacy/key-migration.d.ts.map +1 -0
- package/dist/walls/06-memory/privacy/key-migration.js +124 -0
- package/dist/walls/06-memory/privacy/key-migration.js.map +1 -0
- package/dist/walls/06-memory/privacy/key-provider-file.d.ts +9 -0
- package/dist/walls/06-memory/privacy/key-provider-file.d.ts.map +1 -0
- package/dist/walls/06-memory/privacy/key-provider-file.js +129 -0
- package/dist/walls/06-memory/privacy/key-provider-file.js.map +1 -0
- package/dist/walls/06-memory/privacy/key-provider-os.d.ts +22 -0
- package/dist/walls/06-memory/privacy/key-provider-os.d.ts.map +1 -0
- package/dist/walls/06-memory/privacy/key-provider-os.js +201 -0
- package/dist/walls/06-memory/privacy/key-provider-os.js.map +1 -0
- package/dist/walls/06-memory/privacy/key-provider.d.ts +21 -0
- package/dist/walls/06-memory/privacy/key-provider.d.ts.map +1 -0
- package/dist/walls/06-memory/privacy/key-provider.js +123 -0
- package/dist/walls/06-memory/privacy/key-provider.js.map +1 -0
- package/dist/walls/06-memory/retrieval/context-pipeline.d.ts +36 -0
- package/dist/walls/06-memory/retrieval/context-pipeline.d.ts.map +1 -0
- package/dist/walls/06-memory/retrieval/context-pipeline.js +266 -0
- package/dist/walls/06-memory/retrieval/context-pipeline.js.map +1 -0
- package/dist/walls/06-memory/stores/memory-search.d.ts.map +1 -1
- package/dist/walls/06-memory/stores/memory-search.js +18 -4
- package/dist/walls/06-memory/stores/memory-search.js.map +1 -1
- package/dist/walls/06-memory/stores/sync-engine.d.ts.map +1 -1
- package/dist/walls/06-memory/stores/sync-engine.js +15 -0
- package/dist/walls/06-memory/stores/sync-engine.js.map +1 -1
- package/dist/walls/07-runtime/cli/cli.js +121 -0
- package/dist/walls/07-runtime/cli/cli.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const key_provider_1 = require("../walls/06-memory/privacy/key-provider");
|
|
4
|
+
const key_provider_file_1 = require("../walls/06-memory/privacy/key-provider-file");
|
|
5
|
+
const key_migration_1 = require("../walls/06-memory/privacy/key-migration");
|
|
6
|
+
describe('Key Provider', () => {
|
|
7
|
+
it('detectOS returns a valid OS type', () => {
|
|
8
|
+
const os = (0, key_provider_1.detectOS)();
|
|
9
|
+
expect(['windows', 'macos', 'linux', 'unknown']).toContain(os);
|
|
10
|
+
});
|
|
11
|
+
it('deriveMachineKey returns 32-byte buffer', () => {
|
|
12
|
+
const key = (0, key_provider_1.deriveMachineKey)();
|
|
13
|
+
expect(key).toBeInstanceOf(Buffer);
|
|
14
|
+
expect(key.length).toBe(32);
|
|
15
|
+
});
|
|
16
|
+
it('deriveMachineKey is deterministic', () => {
|
|
17
|
+
const key1 = (0, key_provider_1.deriveMachineKey)();
|
|
18
|
+
const key2 = (0, key_provider_1.deriveMachineKey)();
|
|
19
|
+
expect(key1.equals(key2)).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
it('getKeyProviderInfo returns provider info', () => {
|
|
22
|
+
const info = (0, key_provider_1.getKeyProviderInfo)();
|
|
23
|
+
expect(info.os).toBeDefined();
|
|
24
|
+
expect(typeof info.name).toBe('string');
|
|
25
|
+
expect(typeof info.available).toBe('boolean');
|
|
26
|
+
});
|
|
27
|
+
it('FileKeyProvider can set and get keys', () => {
|
|
28
|
+
const provider = new key_provider_file_1.FileKeyProvider();
|
|
29
|
+
if (!provider.isAvailable())
|
|
30
|
+
return;
|
|
31
|
+
const testKey = Buffer.alloc(32, 0xab);
|
|
32
|
+
const testId = 'test-file-provider-' + Date.now();
|
|
33
|
+
const setResult = provider.setKey(testId, testKey);
|
|
34
|
+
expect(setResult).toBe(true);
|
|
35
|
+
const retrieved = provider.getKey(testId);
|
|
36
|
+
expect(retrieved).not.toBeNull();
|
|
37
|
+
expect(retrieved.equals(testKey)).toBe(true);
|
|
38
|
+
// Cleanup
|
|
39
|
+
provider.deleteKey(testId);
|
|
40
|
+
});
|
|
41
|
+
it('FileKeyProvider returns null for missing key', () => {
|
|
42
|
+
const provider = new key_provider_file_1.FileKeyProvider();
|
|
43
|
+
if (!provider.isAvailable())
|
|
44
|
+
return;
|
|
45
|
+
const result = provider.getKey('nonexistent-key-' + Date.now());
|
|
46
|
+
expect(result).toBeNull();
|
|
47
|
+
});
|
|
48
|
+
it('FileKeyProvider delete removes key', () => {
|
|
49
|
+
const provider = new key_provider_file_1.FileKeyProvider();
|
|
50
|
+
if (!provider.isAvailable())
|
|
51
|
+
return;
|
|
52
|
+
const testId = 'test-delete-' + Date.now();
|
|
53
|
+
provider.setKey(testId, Buffer.alloc(32, 0xcc));
|
|
54
|
+
expect(provider.getKey(testId)).not.toBeNull();
|
|
55
|
+
const deleted = provider.deleteKey(testId);
|
|
56
|
+
expect(deleted).toBe(true);
|
|
57
|
+
expect(provider.getKey(testId)).toBeNull();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('Key Migration', () => {
|
|
61
|
+
it('migrateKey returns a result', () => {
|
|
62
|
+
const result = (0, key_migration_1.migrateKey)(process.cwd());
|
|
63
|
+
expect(result).toBeDefined();
|
|
64
|
+
expect(result.provider).toBeDefined();
|
|
65
|
+
expect(result.message).toBeDefined();
|
|
66
|
+
});
|
|
67
|
+
it('getMigrationStatus returns status', () => {
|
|
68
|
+
const status = (0, key_migration_1.getMigrationStatus)();
|
|
69
|
+
expect(typeof status.newProviderHas).toBe('boolean');
|
|
70
|
+
expect(typeof status.oldGlobalExists).toBe('boolean');
|
|
71
|
+
expect(typeof status.needsMigration).toBe('boolean');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=key-provider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-provider.test.js","sourceRoot":"","sources":["../../src/__tests__/key-provider.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const ARCHIVE_FORMAT_VERSION = 2;
|
|
2
|
+
export interface ArchiveChunkMeta {
|
|
3
|
+
format_version: number;
|
|
4
|
+
compression: 'gzip' | 'zstd';
|
|
5
|
+
encryption: 'aes-256-gcm';
|
|
6
|
+
chunk_type: 'events' | 'sessions' | 'decisions' | 'mixed';
|
|
7
|
+
project: string;
|
|
8
|
+
date: string;
|
|
9
|
+
event_count: number;
|
|
10
|
+
created_at: string;
|
|
11
|
+
checksum?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ArchiveChunk {
|
|
14
|
+
meta: ArchiveChunkMeta;
|
|
15
|
+
data: Buffer;
|
|
16
|
+
}
|
|
17
|
+
export declare function readArchiveChunkMeta(projectDir: string, chunkType: string, date: Date): ArchiveChunkMeta | null;
|
|
18
|
+
export declare function listArchiveChunks(projectDir: string): Array<{
|
|
19
|
+
path: string;
|
|
20
|
+
meta: ArchiveChunkMeta | null;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function writeArchiveChunk(projectDir: string, project: string, chunkType: string, events: unknown[], _key: Buffer, date?: Date): {
|
|
23
|
+
chunkPath: string;
|
|
24
|
+
metaPath: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function verifyArchiveIntegrity(projectDir: string): {
|
|
27
|
+
totalChunks: number;
|
|
28
|
+
versionedChunks: number;
|
|
29
|
+
unversionedChunks: number;
|
|
30
|
+
totalEvents: number;
|
|
31
|
+
issues: string[];
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=archive-versioning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-versioning.d.ts","sourceRoot":"","sources":["../../../../src/walls/06-memory/archive/archive-versioning.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,UAAU,EAAE,aAAa,CAAC;IAC1B,UAAU,EAAE,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAyBD,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,gBAAgB,GAAG,IAAI,CAqB/G;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAA;CAAE,CAAC,CAyB5G;AAMD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EAAE,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,IAAI,GACV;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAiCzC;AAMD,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CA2BA"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ARCHIVE_FORMAT_VERSION = void 0;
|
|
37
|
+
exports.readArchiveChunkMeta = readArchiveChunkMeta;
|
|
38
|
+
exports.listArchiveChunks = listArchiveChunks;
|
|
39
|
+
exports.writeArchiveChunk = writeArchiveChunk;
|
|
40
|
+
exports.verifyArchiveIntegrity = verifyArchiveIntegrity;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
// ============================================================
|
|
44
|
+
// archive-versioning.ts — Archive format versioning + metadata
|
|
45
|
+
//
|
|
46
|
+
// Current format: gzip + AES-256-GCM (.jsonl.gz.enc)
|
|
47
|
+
// New format adds: versioned metadata header
|
|
48
|
+
//
|
|
49
|
+
// Archive chunk structure:
|
|
50
|
+
// .cell/memory/archive/YYYY/MM/events-YYYY-MM-DD.jsonl.gz.enc
|
|
51
|
+
// .cell/memory/archive/YYYY/MM/sessions-YYYY-MM-DD.jsonl.gz.enc
|
|
52
|
+
// .cell/memory/archive/YYYY/MM/decisions-YYYY-MM-DD.jsonl.gz.enc
|
|
53
|
+
//
|
|
54
|
+
// Metadata (inside each chunk or as sidecar):
|
|
55
|
+
// format_version: 2
|
|
56
|
+
// compression: 'gzip' | 'zstd'
|
|
57
|
+
// encryption: 'aes-256-gcm'
|
|
58
|
+
// chunk_type: 'events' | 'sessions' | 'decisions'
|
|
59
|
+
// project: string
|
|
60
|
+
// date: string
|
|
61
|
+
// event_count: number
|
|
62
|
+
// ============================================================
|
|
63
|
+
exports.ARCHIVE_FORMAT_VERSION = 2;
|
|
64
|
+
function getArchiveDir(projectDir, date) {
|
|
65
|
+
const d = date || new Date();
|
|
66
|
+
const year = d.getFullYear().toString();
|
|
67
|
+
const month = (d.getMonth() + 1).toString().padStart(2, '0');
|
|
68
|
+
const dir = path.join(projectDir, '.cell', 'memory', 'archive', year, month);
|
|
69
|
+
if (!fs.existsSync(dir))
|
|
70
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
71
|
+
return dir;
|
|
72
|
+
}
|
|
73
|
+
function getChunkFileName(chunkType, date) {
|
|
74
|
+
const dateStr = date.toISOString().slice(0, 10);
|
|
75
|
+
return `${chunkType}-${dateStr}.jsonl.gz.enc`;
|
|
76
|
+
}
|
|
77
|
+
function getChunkMetaFileName(chunkType, date) {
|
|
78
|
+
const dateStr = date.toISOString().slice(0, 10);
|
|
79
|
+
return `${chunkType}-${dateStr}.meta.json`;
|
|
80
|
+
}
|
|
81
|
+
// ============================================================
|
|
82
|
+
// Read — dual format support (v1 and v2)
|
|
83
|
+
// ============================================================
|
|
84
|
+
function readArchiveChunkMeta(projectDir, chunkType, date) {
|
|
85
|
+
const dir = getArchiveDir(projectDir, date);
|
|
86
|
+
const metaPath = path.join(dir, getChunkMetaFileName(chunkType, date));
|
|
87
|
+
if (!fs.existsSync(metaPath))
|
|
88
|
+
return null;
|
|
89
|
+
try {
|
|
90
|
+
const raw = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
91
|
+
// Backward compatible: if format_version missing, treat as v1
|
|
92
|
+
return {
|
|
93
|
+
format_version: raw.format_version || 1,
|
|
94
|
+
compression: raw.compression || 'gzip',
|
|
95
|
+
encryption: raw.encryption || 'aes-256-gcm',
|
|
96
|
+
chunk_type: raw.chunk_type || chunkType,
|
|
97
|
+
project: raw.project || '',
|
|
98
|
+
date: raw.date || date.toISOString().slice(0, 10),
|
|
99
|
+
event_count: raw.event_count || 0,
|
|
100
|
+
created_at: raw.created_at || new Date().toISOString(),
|
|
101
|
+
checksum: raw.checksum,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function listArchiveChunks(projectDir) {
|
|
109
|
+
const archiveRoot = path.join(projectDir, '.cell', 'memory', 'archive');
|
|
110
|
+
if (!fs.existsSync(archiveRoot))
|
|
111
|
+
return [];
|
|
112
|
+
const results = [];
|
|
113
|
+
const walk = (dir) => {
|
|
114
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
115
|
+
const fullPath = path.join(dir, entry.name);
|
|
116
|
+
if (entry.isDirectory()) {
|
|
117
|
+
walk(fullPath);
|
|
118
|
+
}
|
|
119
|
+
else if (entry.name.endsWith('.enc')) {
|
|
120
|
+
const baseName = entry.name.slice(0, -4); // remove .enc
|
|
121
|
+
const metaPath = path.join(dir, `${baseName}.meta.json`);
|
|
122
|
+
let meta = null;
|
|
123
|
+
if (fs.existsSync(metaPath)) {
|
|
124
|
+
try {
|
|
125
|
+
meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
126
|
+
}
|
|
127
|
+
catch { /* ignore */ }
|
|
128
|
+
}
|
|
129
|
+
results.push({ path: fullPath, meta });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
try {
|
|
134
|
+
walk(archiveRoot);
|
|
135
|
+
}
|
|
136
|
+
catch { /* ignore */ }
|
|
137
|
+
return results;
|
|
138
|
+
}
|
|
139
|
+
// ============================================================
|
|
140
|
+
// Write — create chunk with metadata sidecar
|
|
141
|
+
// ============================================================
|
|
142
|
+
function writeArchiveChunk(projectDir, project, chunkType, events, _key, date) {
|
|
143
|
+
const d = date || new Date();
|
|
144
|
+
const dir = getArchiveDir(projectDir, d);
|
|
145
|
+
const chunkFileName = getChunkFileName(chunkType, d);
|
|
146
|
+
const metaFileName = getChunkMetaFileName(chunkType, d);
|
|
147
|
+
const chunkPath = path.join(dir, chunkFileName);
|
|
148
|
+
const metaPath = path.join(dir, metaFileName);
|
|
149
|
+
// Create metadata
|
|
150
|
+
const meta = {
|
|
151
|
+
format_version: exports.ARCHIVE_FORMAT_VERSION,
|
|
152
|
+
compression: 'gzip',
|
|
153
|
+
encryption: 'aes-256-gcm',
|
|
154
|
+
chunk_type: chunkType,
|
|
155
|
+
project,
|
|
156
|
+
date: d.toISOString().slice(0, 10),
|
|
157
|
+
event_count: events.length,
|
|
158
|
+
created_at: new Date().toISOString(),
|
|
159
|
+
};
|
|
160
|
+
// Write metadata sidecar
|
|
161
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
162
|
+
// Write chunk placeholder (actual encryption done by memory-archive.ts)
|
|
163
|
+
// This module only handles versioning and metadata
|
|
164
|
+
if (!fs.existsSync(chunkPath) && events.length > 0) {
|
|
165
|
+
const lineData = events.map(e => JSON.stringify(e)).join('\n');
|
|
166
|
+
const compressed = require('zlib').gzipSync(Buffer.from(lineData, 'utf-8'));
|
|
167
|
+
fs.writeFileSync(chunkPath, compressed);
|
|
168
|
+
}
|
|
169
|
+
return { chunkPath, metaPath };
|
|
170
|
+
}
|
|
171
|
+
// ============================================================
|
|
172
|
+
// Integrity check
|
|
173
|
+
// ============================================================
|
|
174
|
+
function verifyArchiveIntegrity(projectDir) {
|
|
175
|
+
const chunks = listArchiveChunks(projectDir);
|
|
176
|
+
const issues = [];
|
|
177
|
+
let versioned = 0;
|
|
178
|
+
let unversioned = 0;
|
|
179
|
+
let totalEvents = 0;
|
|
180
|
+
for (const chunk of chunks) {
|
|
181
|
+
if (chunk.meta) {
|
|
182
|
+
versioned++;
|
|
183
|
+
totalEvents += chunk.meta.event_count;
|
|
184
|
+
if (chunk.meta.format_version < exports.ARCHIVE_FORMAT_VERSION) {
|
|
185
|
+
issues.push(`Old format v${chunk.meta.format_version}: ${chunk.path}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
unversioned++;
|
|
190
|
+
issues.push(`No metadata: ${chunk.path}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
totalChunks: chunks.length,
|
|
195
|
+
versionedChunks: versioned,
|
|
196
|
+
unversionedChunks: unversioned,
|
|
197
|
+
totalEvents,
|
|
198
|
+
issues,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=archive-versioning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-versioning.js","sourceRoot":"","sources":["../../../../src/walls/06-memory/archive/archive-versioning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface BlobMeta {
|
|
2
|
+
hash: string;
|
|
3
|
+
original_size: number;
|
|
4
|
+
compressed_size: number;
|
|
5
|
+
encrypted_size: number;
|
|
6
|
+
content_type: string;
|
|
7
|
+
created_at: string;
|
|
8
|
+
ref_count: number;
|
|
9
|
+
}
|
|
10
|
+
export interface BlobStats {
|
|
11
|
+
totalBlobs: number;
|
|
12
|
+
totalOriginalBytes: number;
|
|
13
|
+
totalEncryptedBytes: number;
|
|
14
|
+
dedupSavingsPercent: number;
|
|
15
|
+
avgRefCount: number;
|
|
16
|
+
contentTypes: Record<string, number>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Write content to blob vault (dedup by hash)
|
|
20
|
+
* Returns hash if written, null if error
|
|
21
|
+
*/
|
|
22
|
+
export declare function writeBlob(projectDir: string, content: Buffer, contentType?: string): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Read content from blob vault by hash
|
|
25
|
+
*/
|
|
26
|
+
export declare function readBlob(projectDir: string, hash: string): Buffer | null;
|
|
27
|
+
/**
|
|
28
|
+
* Check if blob exists
|
|
29
|
+
*/
|
|
30
|
+
export declare function blobExists(projectDir: string, hash: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Get blob metadata
|
|
33
|
+
*/
|
|
34
|
+
export declare function getBlobMeta(projectDir: string, hash: string): BlobMeta | null;
|
|
35
|
+
/**
|
|
36
|
+
* Delete blob (only if ref_count <= 1)
|
|
37
|
+
*/
|
|
38
|
+
export declare function deleteBlob(projectDir: string, hash: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Get vault statistics
|
|
41
|
+
*/
|
|
42
|
+
export declare function getBlobStats(projectDir: string): BlobStats;
|
|
43
|
+
/**
|
|
44
|
+
* List all blobs
|
|
45
|
+
*/
|
|
46
|
+
export declare function listBlobs(projectDir: string): BlobMeta[];
|
|
47
|
+
//# sourceMappingURL=blob-vault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blob-vault.d.ts","sourceRoot":"","sources":["../../../../src/walls/06-memory/archive/blob-vault.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAwDD;;;GAGG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAgB,GAC5B,MAAM,GAAG,IAAI,CA0Cf;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAI7E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAapE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CA2C1D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,EAAE,CAYxD"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.writeBlob = writeBlob;
|
|
37
|
+
exports.readBlob = readBlob;
|
|
38
|
+
exports.blobExists = blobExists;
|
|
39
|
+
exports.getBlobMeta = getBlobMeta;
|
|
40
|
+
exports.deleteBlob = deleteBlob;
|
|
41
|
+
exports.getBlobStats = getBlobStats;
|
|
42
|
+
exports.listBlobs = listBlobs;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const crypto = __importStar(require("crypto"));
|
|
46
|
+
const zlib = __importStar(require("zlib"));
|
|
47
|
+
// ============================================================
|
|
48
|
+
// blob-vault.ts — Content-addressed dedup storage
|
|
49
|
+
//
|
|
50
|
+
// Stores large content as SHA-256 hashed blobs
|
|
51
|
+
// Same content → 1 blob, N references
|
|
52
|
+
//
|
|
53
|
+
// Structure:
|
|
54
|
+
// .cell/memory/blobs/sha256-xxxx.enc
|
|
55
|
+
// .cell/memory/blobs/sha256-xxxx.meta.json
|
|
56
|
+
//
|
|
57
|
+
// Format: gzip compress → AES-256-GCM encrypt
|
|
58
|
+
// ============================================================
|
|
59
|
+
const ALGORITHM = 'aes-256-gcm';
|
|
60
|
+
const IV_LENGTH = 16;
|
|
61
|
+
const TAG_LENGTH = 16;
|
|
62
|
+
const KEY_LENGTH = 32;
|
|
63
|
+
// ============================================================
|
|
64
|
+
// Internal helpers
|
|
65
|
+
// ============================================================
|
|
66
|
+
function getBlobsDir(projectDir) {
|
|
67
|
+
const dir = path.join(projectDir, '.cell', 'memory', 'blobs');
|
|
68
|
+
if (!fs.existsSync(dir))
|
|
69
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
70
|
+
return dir;
|
|
71
|
+
}
|
|
72
|
+
function getBlobPath(projectDir, hash) {
|
|
73
|
+
return path.join(getBlobsDir(projectDir), `sha256-${hash}.enc`);
|
|
74
|
+
}
|
|
75
|
+
function getMetaPath(projectDir, hash) {
|
|
76
|
+
return path.join(getBlobsDir(projectDir), `sha256-${hash}.meta.json`);
|
|
77
|
+
}
|
|
78
|
+
function deriveKey() {
|
|
79
|
+
// Machine-bound key for blob encryption
|
|
80
|
+
const hostname = require('os').hostname();
|
|
81
|
+
const username = require('os').userInfo().username;
|
|
82
|
+
return crypto.scryptSync(`${hostname}:${username}:fivocell-blob-vault`, 'fivocell-blob-key', KEY_LENGTH);
|
|
83
|
+
}
|
|
84
|
+
function encrypt(data, key) {
|
|
85
|
+
const iv = crypto.randomBytes(IV_LENGTH);
|
|
86
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv, { authTagLength: TAG_LENGTH });
|
|
87
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
88
|
+
const authTag = cipher.getAuthTag();
|
|
89
|
+
return Buffer.concat([iv, authTag, encrypted]);
|
|
90
|
+
}
|
|
91
|
+
function decrypt(data, key) {
|
|
92
|
+
const iv = data.subarray(0, IV_LENGTH);
|
|
93
|
+
const authTag = data.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
|
|
94
|
+
const encrypted = data.subarray(IV_LENGTH + TAG_LENGTH);
|
|
95
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv, { authTagLength: TAG_LENGTH });
|
|
96
|
+
decipher.setAuthTag(authTag);
|
|
97
|
+
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
98
|
+
}
|
|
99
|
+
function computeHash(data) {
|
|
100
|
+
return crypto.createHash('sha256').update(data).digest('hex');
|
|
101
|
+
}
|
|
102
|
+
// ============================================================
|
|
103
|
+
// Public API
|
|
104
|
+
// ============================================================
|
|
105
|
+
/**
|
|
106
|
+
* Write content to blob vault (dedup by hash)
|
|
107
|
+
* Returns hash if written, null if error
|
|
108
|
+
*/
|
|
109
|
+
function writeBlob(projectDir, content, contentType = 'event') {
|
|
110
|
+
try {
|
|
111
|
+
const hash = computeHash(content);
|
|
112
|
+
// Dedup: check if blob already exists
|
|
113
|
+
if (blobExists(projectDir, hash)) {
|
|
114
|
+
// Increment ref_count
|
|
115
|
+
const metaPath = getMetaPath(projectDir, hash);
|
|
116
|
+
if (fs.existsSync(metaPath)) {
|
|
117
|
+
try {
|
|
118
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
119
|
+
meta.ref_count++;
|
|
120
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
121
|
+
}
|
|
122
|
+
catch { /* non-critical */ }
|
|
123
|
+
}
|
|
124
|
+
return hash;
|
|
125
|
+
}
|
|
126
|
+
// Compress
|
|
127
|
+
const compressed = zlib.gzipSync(content, { level: 6 });
|
|
128
|
+
// Encrypt
|
|
129
|
+
const key = deriveKey();
|
|
130
|
+
const encrypted = encrypt(compressed, key);
|
|
131
|
+
// Write encrypted blob
|
|
132
|
+
fs.writeFileSync(getBlobPath(projectDir, hash), encrypted);
|
|
133
|
+
// Write metadata sidecar
|
|
134
|
+
const meta = {
|
|
135
|
+
hash,
|
|
136
|
+
original_size: content.length,
|
|
137
|
+
compressed_size: compressed.length,
|
|
138
|
+
encrypted_size: encrypted.length,
|
|
139
|
+
content_type: contentType,
|
|
140
|
+
created_at: new Date().toISOString(),
|
|
141
|
+
ref_count: 1,
|
|
142
|
+
};
|
|
143
|
+
fs.writeFileSync(getMetaPath(projectDir, hash), JSON.stringify(meta, null, 2));
|
|
144
|
+
return hash;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Read content from blob vault by hash
|
|
152
|
+
*/
|
|
153
|
+
function readBlob(projectDir, hash) {
|
|
154
|
+
const blobPath = getBlobPath(projectDir, hash);
|
|
155
|
+
if (!fs.existsSync(blobPath))
|
|
156
|
+
return null;
|
|
157
|
+
try {
|
|
158
|
+
const encrypted = fs.readFileSync(blobPath);
|
|
159
|
+
const key = deriveKey();
|
|
160
|
+
const compressed = decrypt(encrypted, key);
|
|
161
|
+
return zlib.gunzipSync(compressed);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if blob exists
|
|
169
|
+
*/
|
|
170
|
+
function blobExists(projectDir, hash) {
|
|
171
|
+
return fs.existsSync(getBlobPath(projectDir, hash));
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get blob metadata
|
|
175
|
+
*/
|
|
176
|
+
function getBlobMeta(projectDir, hash) {
|
|
177
|
+
const metaPath = getMetaPath(projectDir, hash);
|
|
178
|
+
if (!fs.existsSync(metaPath))
|
|
179
|
+
return null;
|
|
180
|
+
try {
|
|
181
|
+
return JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Delete blob (only if ref_count <= 1)
|
|
189
|
+
*/
|
|
190
|
+
function deleteBlob(projectDir, hash) {
|
|
191
|
+
const meta = getBlobMeta(projectDir, hash);
|
|
192
|
+
if (!meta)
|
|
193
|
+
return false;
|
|
194
|
+
if (meta.ref_count > 1) {
|
|
195
|
+
meta.ref_count--;
|
|
196
|
+
fs.writeFileSync(getMetaPath(projectDir, hash), JSON.stringify(meta, null, 2));
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
fs.unlinkSync(getBlobPath(projectDir, hash));
|
|
201
|
+
fs.unlinkSync(getMetaPath(projectDir, hash));
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get vault statistics
|
|
210
|
+
*/
|
|
211
|
+
function getBlobStats(projectDir) {
|
|
212
|
+
const blobsDir = path.join(projectDir, '.cell', 'memory', 'blobs');
|
|
213
|
+
if (!fs.existsSync(blobsDir)) {
|
|
214
|
+
return {
|
|
215
|
+
totalBlobs: 0,
|
|
216
|
+
totalOriginalBytes: 0,
|
|
217
|
+
totalEncryptedBytes: 0,
|
|
218
|
+
dedupSavingsPercent: 0,
|
|
219
|
+
avgRefCount: 0,
|
|
220
|
+
contentTypes: {},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
let totalBlobs = 0;
|
|
224
|
+
let totalOriginal = 0;
|
|
225
|
+
let totalEncrypted = 0;
|
|
226
|
+
let totalRefCount = 0;
|
|
227
|
+
const contentTypes = {};
|
|
228
|
+
for (const file of fs.readdirSync(blobsDir)) {
|
|
229
|
+
if (!file.endsWith('.meta.json'))
|
|
230
|
+
continue;
|
|
231
|
+
try {
|
|
232
|
+
const meta = JSON.parse(fs.readFileSync(path.join(blobsDir, file), 'utf-8'));
|
|
233
|
+
totalBlobs++;
|
|
234
|
+
totalOriginal += meta.original_size;
|
|
235
|
+
totalEncrypted += meta.encrypted_size;
|
|
236
|
+
totalRefCount += meta.ref_count;
|
|
237
|
+
contentTypes[meta.content_type] = (contentTypes[meta.content_type] || 0) + 1;
|
|
238
|
+
}
|
|
239
|
+
catch { /* skip corrupt */ }
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
totalBlobs,
|
|
243
|
+
totalOriginalBytes: totalOriginal,
|
|
244
|
+
totalEncryptedBytes: totalEncrypted,
|
|
245
|
+
dedupSavingsPercent: totalOriginal > 0
|
|
246
|
+
? Math.round((1 - totalEncrypted / totalOriginal) * 100)
|
|
247
|
+
: 0,
|
|
248
|
+
avgRefCount: totalBlobs > 0
|
|
249
|
+
? Math.round(totalRefCount / totalBlobs * 10) / 10
|
|
250
|
+
: 0,
|
|
251
|
+
contentTypes,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* List all blobs
|
|
256
|
+
*/
|
|
257
|
+
function listBlobs(projectDir) {
|
|
258
|
+
const blobsDir = path.join(projectDir, '.cell', 'memory', 'blobs');
|
|
259
|
+
if (!fs.existsSync(blobsDir))
|
|
260
|
+
return [];
|
|
261
|
+
const results = [];
|
|
262
|
+
for (const file of fs.readdirSync(blobsDir)) {
|
|
263
|
+
if (!file.endsWith('.meta.json'))
|
|
264
|
+
continue;
|
|
265
|
+
try {
|
|
266
|
+
results.push(JSON.parse(fs.readFileSync(path.join(blobsDir, file), 'utf-8')));
|
|
267
|
+
}
|
|
268
|
+
catch { /* skip */ }
|
|
269
|
+
}
|
|
270
|
+
return results;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=blob-vault.js.map
|