@omnitype-code/journal 2.0.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/blame/legacy.d.ts +24 -0
- package/dist/blame/legacy.d.ts.map +1 -0
- package/dist/blame/legacy.js +219 -0
- package/dist/blame/legacy.js.map +1 -0
- package/dist/blame/merge.d.ts +17 -0
- package/dist/blame/merge.d.ts.map +1 -0
- package/dist/blame/merge.js +32 -0
- package/dist/blame/merge.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +638 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud/anchor.d.ts +78 -0
- package/dist/cloud/anchor.d.ts.map +1 -0
- package/dist/cloud/anchor.js +220 -0
- package/dist/cloud/anchor.js.map +1 -0
- package/dist/cloud/pending.d.ts +29 -0
- package/dist/cloud/pending.d.ts.map +1 -0
- package/dist/cloud/pending.js +115 -0
- package/dist/cloud/pending.js.map +1 -0
- package/dist/cloud/shipper.d.ts +67 -0
- package/dist/cloud/shipper.d.ts.map +1 -0
- package/dist/cloud/shipper.js +177 -0
- package/dist/cloud/shipper.js.map +1 -0
- package/dist/crypto/chain.d.ts +19 -0
- package/dist/crypto/chain.d.ts.map +1 -0
- package/dist/crypto/chain.js +123 -0
- package/dist/crypto/chain.js.map +1 -0
- package/dist/daemon/journal.d.ts +92 -0
- package/dist/daemon/journal.d.ts.map +1 -0
- package/dist/daemon/journal.js +370 -0
- package/dist/daemon/journal.js.map +1 -0
- package/dist/daemon/server.d.ts +89 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +323 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/log/segment.d.ts +43 -0
- package/dist/log/segment.d.ts.map +1 -0
- package/dist/log/segment.js +180 -0
- package/dist/log/segment.js.map +1 -0
- package/dist/materializer/db.d.ts +47 -0
- package/dist/materializer/db.d.ts.map +1 -0
- package/dist/materializer/db.js +385 -0
- package/dist/materializer/db.js.map +1 -0
- package/dist/notes/git-notes.d.ts +50 -0
- package/dist/notes/git-notes.d.ts.map +1 -0
- package/dist/notes/git-notes.js +94 -0
- package/dist/notes/git-notes.js.map +1 -0
- package/dist/schema/events.d.ts +224 -0
- package/dist/schema/events.d.ts.map +1 -0
- package/dist/schema/events.js +10 -0
- package/dist/schema/events.js.map +1 -0
- package/dist/security/developer-identity.d.ts +35 -0
- package/dist/security/developer-identity.d.ts.map +1 -0
- package/dist/security/developer-identity.js +105 -0
- package/dist/security/developer-identity.js.map +1 -0
- package/dist/security/keychain.d.ts +20 -0
- package/dist/security/keychain.d.ts.map +1 -0
- package/dist/security/keychain.js +167 -0
- package/dist/security/keychain.js.map +1 -0
- package/dist/verify/chain-verify.d.ts +43 -0
- package/dist/verify/chain-verify.d.ts.map +1 -0
- package/dist/verify/chain-verify.js +119 -0
- package/dist/verify/chain-verify.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unix Domain Socket server.
|
|
3
|
+
*
|
|
4
|
+
* Protocol: newline-delimited JSON over UDS (or named pipe on Windows).
|
|
5
|
+
* Each message: { type, id, payload }
|
|
6
|
+
* Each response: { type: "reply", id, ok, payload? }
|
|
7
|
+
*
|
|
8
|
+
* Message types the daemon accepts:
|
|
9
|
+
* append — write one event to the journal
|
|
10
|
+
* append_batch — write multiple events in one flush
|
|
11
|
+
* query_spans — read materialized spans for a file
|
|
12
|
+
* query_file — read file state
|
|
13
|
+
* query_health — get chain head + stats
|
|
14
|
+
* subscribe — register for live event push (streaming mode)
|
|
15
|
+
*/
|
|
16
|
+
import { createServer, createConnection } from 'node:net';
|
|
17
|
+
import { mkdirSync, existsSync, unlinkSync } from 'node:fs';
|
|
18
|
+
import { join, dirname } from 'node:path';
|
|
19
|
+
import { randomBytes, createHmac, timingSafeEqual } from 'node:crypto';
|
|
20
|
+
import { deriveAdapterSubkey } from '../crypto/chain.js';
|
|
21
|
+
export function getSocketPath(journalRoot) {
|
|
22
|
+
if (process.platform === 'win32') {
|
|
23
|
+
return '\\\\.\\pipe\\omnitype-journal';
|
|
24
|
+
}
|
|
25
|
+
return join(journalRoot, 'daemon.sock');
|
|
26
|
+
}
|
|
27
|
+
export class DaemonServer {
|
|
28
|
+
server;
|
|
29
|
+
journal;
|
|
30
|
+
subscribers = new Set();
|
|
31
|
+
installKey;
|
|
32
|
+
hardened;
|
|
33
|
+
// Map from socket to auth state — unauthenticated connections can only call `handshake`
|
|
34
|
+
connState = new Map();
|
|
35
|
+
constructor(journal, socketPath, installKey, hardened = false) {
|
|
36
|
+
this.journal = journal;
|
|
37
|
+
this.installKey = installKey;
|
|
38
|
+
this.hardened = hardened;
|
|
39
|
+
// Clean up stale socket
|
|
40
|
+
if (process.platform !== 'win32' && existsSync(socketPath)) {
|
|
41
|
+
unlinkSync(socketPath);
|
|
42
|
+
}
|
|
43
|
+
mkdirSync(dirname(socketPath), { recursive: true });
|
|
44
|
+
this.server = createServer((socket) => this.handleConnection(socket));
|
|
45
|
+
// Broadcast journal events to subscribers
|
|
46
|
+
journal.subscribe((event) => {
|
|
47
|
+
if (this.subscribers.size === 0)
|
|
48
|
+
return;
|
|
49
|
+
const msg = JSON.stringify({ type: 'event', payload: event }) + '\n';
|
|
50
|
+
for (const sub of this.subscribers) {
|
|
51
|
+
sub.write(msg, () => { });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
this.server.listen(socketPath, () => {
|
|
55
|
+
console.error(`[omnitype-daemon] listening on ${socketPath}`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
handleConnection(socket) {
|
|
59
|
+
let buf = '';
|
|
60
|
+
// Each new connection starts unauthenticated
|
|
61
|
+
this.connState.set(socket, { adapterId: null, challenge: null, authenticated: false });
|
|
62
|
+
socket.on('data', (chunk) => {
|
|
63
|
+
buf += chunk.toString('utf-8');
|
|
64
|
+
const lines = buf.split('\n');
|
|
65
|
+
buf = lines.pop() ?? '';
|
|
66
|
+
for (const line of lines) {
|
|
67
|
+
if (!line.trim())
|
|
68
|
+
continue;
|
|
69
|
+
this.handleMessage(socket, line);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
socket.on('close', () => {
|
|
73
|
+
this.subscribers.delete(socket);
|
|
74
|
+
this.connState.delete(socket);
|
|
75
|
+
});
|
|
76
|
+
socket.on('error', () => {
|
|
77
|
+
this.subscribers.delete(socket);
|
|
78
|
+
this.connState.delete(socket);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
handleMessage(socket, line) {
|
|
82
|
+
let msg;
|
|
83
|
+
try {
|
|
84
|
+
msg = JSON.parse(line);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
this.send(socket, { type: 'reply', id: '', ok: false, error: 'invalid JSON' });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const result = this.dispatch(msg, socket);
|
|
92
|
+
if (result instanceof Promise) {
|
|
93
|
+
result
|
|
94
|
+
.then((payload) => this.send(socket, { type: 'reply', id: msg.id, ok: true, payload }))
|
|
95
|
+
.catch((err) => this.send(socket, { type: 'reply', id: msg.id, ok: false, error: String(err) }));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.send(socket, { type: 'reply', id: msg.id, ok: true, payload: result });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
this.send(socket, { type: 'reply', id: msg.id, ok: false, error: String(err) });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
dispatch(msg, socket) {
|
|
106
|
+
const state = this.connState.get(socket);
|
|
107
|
+
// ── Handshake phase (Day 2: §1.1) ────────────────────────────────────────
|
|
108
|
+
// Step 1: client sends { type:'handshake_init', adapter_id }
|
|
109
|
+
// Daemon responds with a random challenge.
|
|
110
|
+
// Step 2: client sends { type:'handshake_response', adapter_id, response: HMAC(subkey, challenge) }
|
|
111
|
+
// Daemon verifies; marks connection authenticated.
|
|
112
|
+
// All other message types are rejected until authenticated.
|
|
113
|
+
if (msg.type === 'handshake_init') {
|
|
114
|
+
const { adapter_id } = msg.payload;
|
|
115
|
+
const challenge = randomBytes(32);
|
|
116
|
+
state.adapterId = adapter_id;
|
|
117
|
+
state.challenge = challenge;
|
|
118
|
+
state.authenticated = false;
|
|
119
|
+
// Advertise hardened mode so adapters know not to attempt a key-based
|
|
120
|
+
// response (in hardened mode the key never leaves the daemon).
|
|
121
|
+
return { challenge: challenge.toString('hex'), hardened: this.hardened };
|
|
122
|
+
}
|
|
123
|
+
if (msg.type === 'handshake_response') {
|
|
124
|
+
const { adapter_id, response } = msg.payload;
|
|
125
|
+
if (!state.challenge || state.adapterId !== adapter_id) {
|
|
126
|
+
throw new Error('handshake_response before handshake_init');
|
|
127
|
+
}
|
|
128
|
+
if (this.hardened) {
|
|
129
|
+
// Hardened mode: the daemon is the sole key-holder and brokers all
|
|
130
|
+
// signing, so adapters cannot (and must not) prove key possession. The
|
|
131
|
+
// socket is same-user gated by OS filesystem permissions; integrity is
|
|
132
|
+
// guaranteed at rest by the keychain-held key and pinned server-side by
|
|
133
|
+
// the cloud anchor. We accept the connection without a subkey challenge.
|
|
134
|
+
// NOTE: this does not prove the *caller's* process identity — closing the
|
|
135
|
+
// live same-user-impostor gap requires OS-level adapter code-signing.
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const subkey = deriveAdapterSubkey(this.installKey, adapter_id);
|
|
139
|
+
const expected = createHmac('sha256', subkey).update(state.challenge).digest();
|
|
140
|
+
const provided = Buffer.from(response, 'hex');
|
|
141
|
+
if (provided.length !== expected.length || !timingSafeEqual(expected, provided)) {
|
|
142
|
+
state.authenticated = false;
|
|
143
|
+
throw new Error('adapter authentication failed — subkey mismatch');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
state.authenticated = true;
|
|
147
|
+
// Emit CapabilityClaim + AdapterInstalled
|
|
148
|
+
const { capabilities, manifest_sig_verified, runtime_mode } = msg.payload;
|
|
149
|
+
this.journal.registerAdapter(adapter_id, capabilities ?? {}, manifest_sig_verified ?? false, runtime_mode ?? 'hook');
|
|
150
|
+
return { authenticated: true };
|
|
151
|
+
}
|
|
152
|
+
// All write operations require authentication
|
|
153
|
+
if (!state.authenticated && msg.type !== 'query_health') {
|
|
154
|
+
throw new Error(`unauthenticated: call handshake_init + handshake_response before ${msg.type}`);
|
|
155
|
+
}
|
|
156
|
+
switch (msg.type) {
|
|
157
|
+
case 'append': {
|
|
158
|
+
const { actor, body, tier, adapter_id, sync } = msg.payload;
|
|
159
|
+
// Enforce: adapter_id in message must match the authenticated adapter (Day 2: §1.1)
|
|
160
|
+
if (state.adapterId && adapter_id !== state.adapterId) {
|
|
161
|
+
throw new Error(`adapter_id mismatch: authenticated as ${state.adapterId}, got ${adapter_id}`);
|
|
162
|
+
}
|
|
163
|
+
const seq = this.journal.append(actor, body, tier, adapter_id, sync ?? false);
|
|
164
|
+
return { seq };
|
|
165
|
+
}
|
|
166
|
+
case 'append_batch': {
|
|
167
|
+
const { events, adapter_id } = msg.payload;
|
|
168
|
+
if (state.adapterId && adapter_id !== state.adapterId) {
|
|
169
|
+
throw new Error(`adapter_id mismatch: authenticated as ${state.adapterId}, got ${adapter_id}`);
|
|
170
|
+
}
|
|
171
|
+
const seqs = [];
|
|
172
|
+
for (const e of events) {
|
|
173
|
+
seqs.push(this.journal.append(e.actor, e.body, e.tier, adapter_id));
|
|
174
|
+
}
|
|
175
|
+
return { seqs };
|
|
176
|
+
}
|
|
177
|
+
case 'query_spans': {
|
|
178
|
+
const { path, min_tier } = msg.payload;
|
|
179
|
+
return { spans: this.journal.getSpans(path, min_tier) };
|
|
180
|
+
}
|
|
181
|
+
case 'query_attribution': {
|
|
182
|
+
const { path } = msg.payload;
|
|
183
|
+
return { summary: this.journal.getAttributionSummary(path) };
|
|
184
|
+
}
|
|
185
|
+
case 'query_attestations': {
|
|
186
|
+
const { path } = msg.payload;
|
|
187
|
+
return { attestations: this.journal.getHighestTierAttestations(path) };
|
|
188
|
+
}
|
|
189
|
+
case 'query_conflicts': {
|
|
190
|
+
const { path } = msg.payload;
|
|
191
|
+
return { conflicts: this.journal.getConcurrencyConflicts(path) };
|
|
192
|
+
}
|
|
193
|
+
case 'query_health': {
|
|
194
|
+
const head = this.journal.getChainHead();
|
|
195
|
+
const info = this.journal.getInstallInfo();
|
|
196
|
+
return { head, install: info };
|
|
197
|
+
}
|
|
198
|
+
case 'subscribe': {
|
|
199
|
+
this.subscribers.add(socket);
|
|
200
|
+
return { subscribed: true };
|
|
201
|
+
}
|
|
202
|
+
default:
|
|
203
|
+
throw new Error(`unknown message type: ${msg.type}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
send(socket, reply) {
|
|
207
|
+
socket.write(JSON.stringify(reply) + '\n');
|
|
208
|
+
}
|
|
209
|
+
close() {
|
|
210
|
+
return new Promise((resolve) => this.server.close(() => resolve()));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// ─── Client (used by VSCode extension and CLI) ────────────────────────────────
|
|
214
|
+
export class JournalClient {
|
|
215
|
+
socketPath;
|
|
216
|
+
socket = null;
|
|
217
|
+
pending = new Map();
|
|
218
|
+
buf = '';
|
|
219
|
+
idCounter = 0;
|
|
220
|
+
constructor(socketPath) {
|
|
221
|
+
this.socketPath = socketPath;
|
|
222
|
+
}
|
|
223
|
+
async connect() {
|
|
224
|
+
return new Promise((resolve, reject) => {
|
|
225
|
+
this.socket = createConnection(this.socketPath, () => resolve());
|
|
226
|
+
this.socket.on('error', reject);
|
|
227
|
+
this.socket.on('data', (chunk) => {
|
|
228
|
+
this.buf += chunk.toString('utf-8');
|
|
229
|
+
const lines = this.buf.split('\n');
|
|
230
|
+
this.buf = lines.pop() ?? '';
|
|
231
|
+
for (const line of lines) {
|
|
232
|
+
if (!line.trim())
|
|
233
|
+
continue;
|
|
234
|
+
try {
|
|
235
|
+
const reply = JSON.parse(line);
|
|
236
|
+
if (reply.type === 'event') {
|
|
237
|
+
// Subscribed events — no pending promise to resolve
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const handler = this.pending.get(reply.id);
|
|
241
|
+
if (!handler)
|
|
242
|
+
continue;
|
|
243
|
+
this.pending.delete(reply.id);
|
|
244
|
+
if (reply.ok) {
|
|
245
|
+
handler.resolve(reply.payload);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
handler.reject(new Error(reply.error ?? 'unknown error'));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch { /* ignore malformed reply */ }
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
this.socket.on('close', () => {
|
|
255
|
+
for (const { reject } of this.pending.values()) {
|
|
256
|
+
reject(new Error('daemon disconnected'));
|
|
257
|
+
}
|
|
258
|
+
this.pending.clear();
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Authenticate with the daemon using the per-adapter subkey. (Day 2: §1.1)
|
|
264
|
+
* Must be called after connect() and before any append calls.
|
|
265
|
+
* installKey is the 32-byte install key; adapterId is this adapter's ID.
|
|
266
|
+
*/
|
|
267
|
+
async authenticate(installKey, adapterId, opts = {}) {
|
|
268
|
+
const { createHmac: hmac } = await import('node:crypto');
|
|
269
|
+
const initResult = await this.send('handshake_init', { adapter_id: adapterId });
|
|
270
|
+
const challenge = Buffer.from(initResult.challenge, 'hex');
|
|
271
|
+
// Derive subkey and respond to challenge
|
|
272
|
+
const subkey = hmac('sha256', installKey).update(`adapter-subkey:${adapterId}`).digest();
|
|
273
|
+
const response = hmac('sha256', subkey).update(challenge).digest('hex');
|
|
274
|
+
await this.send('handshake_response', {
|
|
275
|
+
adapter_id: adapterId,
|
|
276
|
+
response,
|
|
277
|
+
capabilities: opts.capabilities ?? {},
|
|
278
|
+
manifest_sig_verified: opts.manifestSigVerified ?? false,
|
|
279
|
+
runtime_mode: opts.runtimeMode ?? 'hook',
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
async send(type, payload) {
|
|
283
|
+
const id = String(++this.idCounter);
|
|
284
|
+
return new Promise((resolve, reject) => {
|
|
285
|
+
this.pending.set(id, {
|
|
286
|
+
resolve: (v) => resolve(v),
|
|
287
|
+
reject,
|
|
288
|
+
});
|
|
289
|
+
this.socket.write(JSON.stringify({ type, id, payload }) + '\n');
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
async append(actor, body, tier, adapterId, sync = false) {
|
|
293
|
+
return this.send('append', { actor, body, tier, adapter_id: adapterId, sync });
|
|
294
|
+
}
|
|
295
|
+
async appendBatch(events, adapterId) {
|
|
296
|
+
return this.send('append_batch', { events, adapter_id: adapterId });
|
|
297
|
+
}
|
|
298
|
+
async querySpans(path, minTier) {
|
|
299
|
+
return this.send('query_spans', { path, min_tier: minTier });
|
|
300
|
+
}
|
|
301
|
+
async health() {
|
|
302
|
+
return this.send('query_health', {});
|
|
303
|
+
}
|
|
304
|
+
disconnect() {
|
|
305
|
+
this.socket?.destroy();
|
|
306
|
+
this.socket = null;
|
|
307
|
+
}
|
|
308
|
+
/** Check if the daemon is running without connecting. */
|
|
309
|
+
static async isRunning(socketPath) {
|
|
310
|
+
return new Promise((resolve) => {
|
|
311
|
+
const s = createConnection(socketPath, () => {
|
|
312
|
+
s.destroy();
|
|
313
|
+
resolve(true);
|
|
314
|
+
});
|
|
315
|
+
s.on('error', () => resolve(false));
|
|
316
|
+
s.setTimeout(500, () => {
|
|
317
|
+
s.destroy();
|
|
318
|
+
resolve(false);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './schema/events.js';
|
|
2
|
+
export * from './crypto/chain.js';
|
|
3
|
+
export { Journal, resolvePaths } from './daemon/journal.js';
|
|
4
|
+
export { DaemonServer, JournalClient, getSocketPath } from './daemon/server.js';
|
|
5
|
+
export { SegmentWriter, SegmentReader } from './log/segment.js';
|
|
6
|
+
export { Materializer } from './materializer/db.js';
|
|
7
|
+
export { CloudAnchor, AnchorQueue, signAnchor, verifyAnchor } from './cloud/anchor.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Public API for @omnitype-code/journal
|
|
2
|
+
export * from './schema/events.js';
|
|
3
|
+
export * from './crypto/chain.js';
|
|
4
|
+
export { Journal, resolvePaths } from './daemon/journal.js';
|
|
5
|
+
export { DaemonServer, JournalClient, getSocketPath } from './daemon/server.js';
|
|
6
|
+
export { SegmentWriter, SegmentReader } from './log/segment.js';
|
|
7
|
+
export { Materializer } from './materializer/db.js';
|
|
8
|
+
export { CloudAnchor, AnchorQueue, signAnchor, verifyAnchor } from './cloud/anchor.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append-only log segment.
|
|
3
|
+
*
|
|
4
|
+
* Wire format per record:
|
|
5
|
+
* u32 length (BE) | JSON bytes | u32 length (BE) | u32 CRC32C
|
|
6
|
+
*
|
|
7
|
+
* Trailing length enables backward scan (crash recovery from end).
|
|
8
|
+
* CRC32C validates the record in forward iteration.
|
|
9
|
+
*
|
|
10
|
+
* Segments rotate at MAX_SEGMENT_BYTES or MAX_SEGMENT_AGE_MS.
|
|
11
|
+
* Rotated segments are immutable; the current segment is always current.log.
|
|
12
|
+
*/
|
|
13
|
+
import type { JournalEvent } from '../schema/events.js';
|
|
14
|
+
export interface SegmentInfo {
|
|
15
|
+
id: number;
|
|
16
|
+
path: string;
|
|
17
|
+
size: number;
|
|
18
|
+
createdAt: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class SegmentWriter {
|
|
21
|
+
private fd;
|
|
22
|
+
private bytesWritten;
|
|
23
|
+
private createdAt;
|
|
24
|
+
private segmentsDir;
|
|
25
|
+
currentId: number;
|
|
26
|
+
constructor(segmentsDir: string);
|
|
27
|
+
private currentPath;
|
|
28
|
+
append(event: JournalEvent): void;
|
|
29
|
+
appendBatch(events: JournalEvent[]): void;
|
|
30
|
+
private shouldRotate;
|
|
31
|
+
private rotate;
|
|
32
|
+
close(): void;
|
|
33
|
+
listSegments(): SegmentInfo[];
|
|
34
|
+
}
|
|
35
|
+
export declare class SegmentReader {
|
|
36
|
+
static readAll(segmentsDir: string): Generator<JournalEvent>;
|
|
37
|
+
/** Find last valid seq in a segment (for crash recovery). */
|
|
38
|
+
static recoverLastValid(segPath: string): {
|
|
39
|
+
lastSeq: number;
|
|
40
|
+
truncateAt: number;
|
|
41
|
+
} | null;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=segment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment.d.ts","sourceRoot":"","sources":["../../src/log/segment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA2CxD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IACrB,SAAS,EAAE,MAAM,CAAC;gBAEb,WAAW,EAAE,MAAM;IAiB/B,OAAO,CAAC,WAAW;IAInB,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAQjC,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI;IAUzC,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,MAAM;IAgBd,KAAK,IAAI,IAAI;IAKb,YAAY,IAAI,WAAW,EAAE;CAe9B;AAED,qBAAa,aAAa;IACxB,MAAM,CAAE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC;IAiB7D,6DAA6D;IAC7D,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAsBzF"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append-only log segment.
|
|
3
|
+
*
|
|
4
|
+
* Wire format per record:
|
|
5
|
+
* u32 length (BE) | JSON bytes | u32 length (BE) | u32 CRC32C
|
|
6
|
+
*
|
|
7
|
+
* Trailing length enables backward scan (crash recovery from end).
|
|
8
|
+
* CRC32C validates the record in forward iteration.
|
|
9
|
+
*
|
|
10
|
+
* Segments rotate at MAX_SEGMENT_BYTES or MAX_SEGMENT_AGE_MS.
|
|
11
|
+
* Rotated segments are immutable; the current segment is always current.log.
|
|
12
|
+
*/
|
|
13
|
+
import { openSync, writeSync, writeFileSync, fsyncSync, closeSync, readFileSync, statSync, readdirSync } from 'node:fs';
|
|
14
|
+
import { createHash } from 'node:crypto';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
const MAX_SEGMENT_BYTES = 64 * 1024 * 1024; // 64 MiB
|
|
17
|
+
const MAX_SEGMENT_AGE_MS = 60 * 60 * 1000; // 1 hour
|
|
18
|
+
function crc32c(buf) {
|
|
19
|
+
// Simple table-driven CRC32C (Castagnoli).
|
|
20
|
+
let crc = 0xffffffff;
|
|
21
|
+
for (let i = 0; i < buf.length; i++) {
|
|
22
|
+
crc ^= buf[i];
|
|
23
|
+
for (let j = 0; j < 8; j++) {
|
|
24
|
+
crc = (crc >>> 1) ^ (crc & 1 ? 0x82f63b78 : 0);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
28
|
+
}
|
|
29
|
+
function encodeRecord(event) {
|
|
30
|
+
const json = Buffer.from(JSON.stringify(event), 'utf-8');
|
|
31
|
+
const len = json.length;
|
|
32
|
+
const lenBuf = Buffer.allocUnsafe(4);
|
|
33
|
+
lenBuf.writeUInt32BE(len, 0);
|
|
34
|
+
const crcVal = crc32c(json);
|
|
35
|
+
const crcBuf = Buffer.allocUnsafe(4);
|
|
36
|
+
crcBuf.writeUInt32BE(crcVal, 0);
|
|
37
|
+
return Buffer.concat([lenBuf, json, lenBuf, crcBuf]);
|
|
38
|
+
}
|
|
39
|
+
function decodeRecord(buf, offset) {
|
|
40
|
+
if (offset + 4 > buf.length)
|
|
41
|
+
return null;
|
|
42
|
+
const len = buf.readUInt32BE(offset);
|
|
43
|
+
if (offset + 4 + len + 8 > buf.length)
|
|
44
|
+
return null;
|
|
45
|
+
const jsonBuf = buf.subarray(offset + 4, offset + 4 + len);
|
|
46
|
+
const storedCrc = buf.readUInt32BE(offset + 4 + len + 4);
|
|
47
|
+
if (crc32c(jsonBuf) !== storedCrc)
|
|
48
|
+
return null;
|
|
49
|
+
try {
|
|
50
|
+
const event = JSON.parse(jsonBuf.toString('utf-8'));
|
|
51
|
+
return { event, next: offset + 4 + len + 8 };
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class SegmentWriter {
|
|
58
|
+
fd;
|
|
59
|
+
bytesWritten = 0;
|
|
60
|
+
createdAt;
|
|
61
|
+
segmentsDir;
|
|
62
|
+
currentId;
|
|
63
|
+
constructor(segmentsDir) {
|
|
64
|
+
this.segmentsDir = segmentsDir;
|
|
65
|
+
const existing = this.listSegments();
|
|
66
|
+
this.currentId = existing.length > 0
|
|
67
|
+
? Math.max(...existing.map((s) => s.id)) + 1
|
|
68
|
+
: 0;
|
|
69
|
+
const path = this.currentPath();
|
|
70
|
+
this.fd = openSync(path, 'a');
|
|
71
|
+
try {
|
|
72
|
+
this.bytesWritten = statSync(path).size;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
this.bytesWritten = 0;
|
|
76
|
+
}
|
|
77
|
+
this.createdAt = Date.now();
|
|
78
|
+
}
|
|
79
|
+
currentPath() {
|
|
80
|
+
return join(this.segmentsDir, `${String(this.currentId).padStart(8, '0')}.log`);
|
|
81
|
+
}
|
|
82
|
+
append(event) {
|
|
83
|
+
const record = encodeRecord(event);
|
|
84
|
+
writeSync(this.fd, record);
|
|
85
|
+
fsyncSync(this.fd);
|
|
86
|
+
this.bytesWritten += record.length;
|
|
87
|
+
if (this.shouldRotate())
|
|
88
|
+
this.rotate();
|
|
89
|
+
}
|
|
90
|
+
appendBatch(events) {
|
|
91
|
+
if (events.length === 0)
|
|
92
|
+
return;
|
|
93
|
+
const records = events.map(encodeRecord);
|
|
94
|
+
const combined = Buffer.concat(records);
|
|
95
|
+
writeSync(this.fd, combined);
|
|
96
|
+
fsyncSync(this.fd);
|
|
97
|
+
this.bytesWritten += combined.length;
|
|
98
|
+
if (this.shouldRotate())
|
|
99
|
+
this.rotate();
|
|
100
|
+
}
|
|
101
|
+
shouldRotate() {
|
|
102
|
+
return (this.bytesWritten >= MAX_SEGMENT_BYTES ||
|
|
103
|
+
Date.now() - this.createdAt >= MAX_SEGMENT_AGE_MS);
|
|
104
|
+
}
|
|
105
|
+
rotate() {
|
|
106
|
+
fsyncSync(this.fd);
|
|
107
|
+
closeSync(this.fd);
|
|
108
|
+
// Write segment checksum sidecar
|
|
109
|
+
const segPath = this.currentPath();
|
|
110
|
+
const segBuf = readFileSync(segPath);
|
|
111
|
+
const sha256 = createHash('sha256').update(segBuf).digest('hex');
|
|
112
|
+
writeFileSync(segPath + '.sha256', sha256 + '\n', 'utf-8');
|
|
113
|
+
this.currentId++;
|
|
114
|
+
const newPath = this.currentPath();
|
|
115
|
+
this.fd = openSync(newPath, 'a');
|
|
116
|
+
this.bytesWritten = 0;
|
|
117
|
+
this.createdAt = Date.now();
|
|
118
|
+
}
|
|
119
|
+
close() {
|
|
120
|
+
fsyncSync(this.fd);
|
|
121
|
+
closeSync(this.fd);
|
|
122
|
+
}
|
|
123
|
+
listSegments() {
|
|
124
|
+
try {
|
|
125
|
+
return readdirSync(this.segmentsDir)
|
|
126
|
+
.filter((f) => /^\d{8}\.log$/.test(f))
|
|
127
|
+
.map((f) => {
|
|
128
|
+
const id = parseInt(f, 10);
|
|
129
|
+
const path = join(this.segmentsDir, f);
|
|
130
|
+
const stat = statSync(path);
|
|
131
|
+
return { id, path, size: stat.size, createdAt: stat.ctimeMs };
|
|
132
|
+
})
|
|
133
|
+
.sort((a, b) => a.id - b.id);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export class SegmentReader {
|
|
141
|
+
static *readAll(segmentsDir) {
|
|
142
|
+
const entries = readdirSync(segmentsDir)
|
|
143
|
+
.filter((f) => /^\d{8}\.log$/.test(f))
|
|
144
|
+
.sort();
|
|
145
|
+
for (const file of entries) {
|
|
146
|
+
const buf = readFileSync(join(segmentsDir, file));
|
|
147
|
+
let offset = 0;
|
|
148
|
+
while (offset < buf.length) {
|
|
149
|
+
const result = decodeRecord(buf, offset);
|
|
150
|
+
if (!result)
|
|
151
|
+
break;
|
|
152
|
+
yield result.event;
|
|
153
|
+
offset = result.next;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Find last valid seq in a segment (for crash recovery). */
|
|
158
|
+
static recoverLastValid(segPath) {
|
|
159
|
+
let buf;
|
|
160
|
+
try {
|
|
161
|
+
buf = readFileSync(segPath);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
let lastGoodOffset = 0;
|
|
167
|
+
let lastSeq = -1;
|
|
168
|
+
let offset = 0;
|
|
169
|
+
while (offset < buf.length) {
|
|
170
|
+
const result = decodeRecord(buf, offset);
|
|
171
|
+
if (!result)
|
|
172
|
+
break;
|
|
173
|
+
lastGoodOffset = result.next;
|
|
174
|
+
lastSeq = result.event.seq;
|
|
175
|
+
offset = result.next;
|
|
176
|
+
}
|
|
177
|
+
return lastSeq >= 0 ? { lastSeq, truncateAt: lastGoodOffset } : null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=segment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment.js","sourceRoot":"","sources":["../../src/log/segment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite WAL materializer (using node:sqlite — built into Node 22.5+).
|
|
3
|
+
*
|
|
4
|
+
* The spans table is the derived view of who wrote which bytes.
|
|
5
|
+
* Reconstructible by replaying the journal from scratch.
|
|
6
|
+
*/
|
|
7
|
+
import type { FileState, JournalEvent, Origin, Span, Tier } from '../schema/events.js';
|
|
8
|
+
export declare class Materializer {
|
|
9
|
+
private db;
|
|
10
|
+
constructor(dbPath: string);
|
|
11
|
+
get lastAppliedSeq(): number;
|
|
12
|
+
apply(event: JournalEvent): void;
|
|
13
|
+
private applyEvent;
|
|
14
|
+
private applyFileOpened;
|
|
15
|
+
private applyEditOp;
|
|
16
|
+
private applyUnattributed;
|
|
17
|
+
private applySplice;
|
|
18
|
+
getSpans(path: string, minTier?: Tier): Span[];
|
|
19
|
+
getFile(path: string): FileState | undefined;
|
|
20
|
+
getAttributionSummary(path: string): Record<Origin, number>;
|
|
21
|
+
/**
|
|
22
|
+
* Day 18 (§3.4): Get highest-tier attribution for a byte range.
|
|
23
|
+
* Competes_with arbitration: when multiple adapters attest to the same bytes,
|
|
24
|
+
* the attestation with the lowest tier number (T0 < T1 < T2 < T3) wins.
|
|
25
|
+
* Ties are broken by highest confidence, then earliest seq.
|
|
26
|
+
*/
|
|
27
|
+
getHighestTierAttestations(path: string): Array<{
|
|
28
|
+
byte_start: number;
|
|
29
|
+
byte_end: number;
|
|
30
|
+
origin: Origin;
|
|
31
|
+
tier: Tier;
|
|
32
|
+
confidence: number;
|
|
33
|
+
adapter_id: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Day 15 (§4.1): Get pending concurrency conflicts — files that need retry.
|
|
37
|
+
* Returns the current hash the retrying tool should use as pre_hash.
|
|
38
|
+
*/
|
|
39
|
+
getConcurrencyConflicts(path?: string): Array<{
|
|
40
|
+
path: string;
|
|
41
|
+
conflicting_seq: number;
|
|
42
|
+
expected_hash: string;
|
|
43
|
+
actual_hash: string;
|
|
44
|
+
}>;
|
|
45
|
+
close(): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=db.d.ts.map
|