sietch 0.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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/acl.d.ts +134 -0
- package/dist/acl.js +258 -0
- package/dist/acl.js.map +1 -0
- package/dist/crypto.d.ts +184 -0
- package/dist/crypto.js +459 -0
- package/dist/crypto.js.map +1 -0
- package/dist/errors.d.ts +42 -0
- package/dist/errors.js +68 -0
- package/dist/errors.js.map +1 -0
- package/dist/eviction.d.ts +75 -0
- package/dist/eviction.js +216 -0
- package/dist/eviction.js.map +1 -0
- package/dist/identity.d.ts +69 -0
- package/dist/identity.js +127 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/observability.d.ts +103 -0
- package/dist/observability.js +91 -0
- package/dist/observability.js.map +1 -0
- package/dist/query-index.d.ts +97 -0
- package/dist/query-index.js +246 -0
- package/dist/query-index.js.map +1 -0
- package/dist/server/acl-authority.d.ts +68 -0
- package/dist/server/acl-authority.js +233 -0
- package/dist/server/acl-authority.js.map +1 -0
- package/dist/server/auth.d.ts +88 -0
- package/dist/server/auth.js +173 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.js +15 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/pg-adapter.d.ts +57 -0
- package/dist/server/pg-adapter.js +241 -0
- package/dist/server/pg-adapter.js.map +1 -0
- package/dist/server/query-bridge.d.ts +166 -0
- package/dist/server/query-bridge.js +258 -0
- package/dist/server/query-bridge.js.map +1 -0
- package/dist/server/sync-service.d.ts +98 -0
- package/dist/server/sync-service.js +209 -0
- package/dist/server/sync-service.js.map +1 -0
- package/dist/storage.d.ts +53 -0
- package/dist/storage.js +340 -0
- package/dist/storage.js.map +1 -0
- package/dist/store.d.ts +195 -0
- package/dist/store.js +479 -0
- package/dist/store.js.map +1 -0
- package/dist/sync-engine.d.ts +187 -0
- package/dist/sync-engine.js +824 -0
- package/dist/sync-engine.js.map +1 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/yjs-engine.d.ts +107 -0
- package/dist/yjs-engine.js +422 -0
- package/dist/yjs-engine.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Query Bridge — Yjs observeDeep → PostgreSQL pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Architecture: §2.2 Server Components, Query Bridge
|
|
5
|
+
*
|
|
6
|
+
* Listens to Yjs updates on unencrypted subdocs and writes to:
|
|
7
|
+
* - `nodes` table (JSONB decoded properties)
|
|
8
|
+
* - `node_history` table (append-only version chain)
|
|
9
|
+
* - AGE graph (edges)
|
|
10
|
+
* - pgvector embeddings (vectors)
|
|
11
|
+
*
|
|
12
|
+
* Encrypted subtrees are stored as opaque BYTEA only.
|
|
13
|
+
*/
|
|
14
|
+
import type { ServerSyncService } from './sync-service.js';
|
|
15
|
+
import type { AclManager } from '../acl.js';
|
|
16
|
+
import type { ObservabilityContext } from '../observability.js';
|
|
17
|
+
/** Abstract database interface for PostgreSQL operations. */
|
|
18
|
+
export interface DatabaseAdapter {
|
|
19
|
+
/** Upsert a node's decoded data. */
|
|
20
|
+
upsertNode(id: string, subtree: string, data: Record<string, unknown>): Promise<void>;
|
|
21
|
+
/** Get a single node by ID. */
|
|
22
|
+
getNode(id: string): Promise<{
|
|
23
|
+
id: string;
|
|
24
|
+
subtree: string;
|
|
25
|
+
data: Record<string, unknown>;
|
|
26
|
+
updatedAt: Date;
|
|
27
|
+
} | null>;
|
|
28
|
+
/** List nodes, optionally filtered by subtree. */
|
|
29
|
+
listNodes(subtree?: string): Promise<Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
subtree: string;
|
|
32
|
+
data: Record<string, unknown>;
|
|
33
|
+
updatedAt: Date;
|
|
34
|
+
}>>;
|
|
35
|
+
/** Append to version history (immutable). */
|
|
36
|
+
appendHistory(id: string, version: number, data: Record<string, unknown>): Promise<void>;
|
|
37
|
+
/** Get the highest version number for a node (for restarting version counters). */
|
|
38
|
+
getMaxVersion(id: string): Promise<number>;
|
|
39
|
+
/** Store raw Yjs state (for encrypted subtrees). */
|
|
40
|
+
upsertSubdocState(subtreeId: string, yjsState: Uint8Array): Promise<void>;
|
|
41
|
+
/** Add a graph edge (AGE). */
|
|
42
|
+
addGraphEdge(source: string, label: string, target: string): Promise<void>;
|
|
43
|
+
/** Remove a graph edge (AGE). */
|
|
44
|
+
removeGraphEdge(source: string, label: string, target: string): Promise<void>;
|
|
45
|
+
/** Upsert a vector embedding (pgvector). */
|
|
46
|
+
upsertVector(nodeId: string, subtree: string, embedding: number[]): Promise<void>;
|
|
47
|
+
/** Query graph via openCypher. */
|
|
48
|
+
cypherQuery(query: string, params?: Record<string, unknown>): Promise<Record<string, unknown>[]>;
|
|
49
|
+
/** kNN vector search. */
|
|
50
|
+
vectorSearch(embedding: number[], k: number): Promise<Array<{
|
|
51
|
+
nodeId: string;
|
|
52
|
+
distance: number;
|
|
53
|
+
}>>;
|
|
54
|
+
/** Get version history for a node. */
|
|
55
|
+
getHistory(id: string, fromVersion?: number): Promise<Array<{
|
|
56
|
+
version: number;
|
|
57
|
+
data: Record<string, unknown>;
|
|
58
|
+
createdAt: Date;
|
|
59
|
+
}>>;
|
|
60
|
+
/** Get state at a specific timestamp. */
|
|
61
|
+
getVersionAtTimestamp(id: string, timestamp: Date): Promise<Record<string, unknown> | null>;
|
|
62
|
+
}
|
|
63
|
+
/** In-memory database adapter for testing without PostgreSQL. */
|
|
64
|
+
export declare class InMemoryDatabaseAdapter implements DatabaseAdapter {
|
|
65
|
+
readonly nodes: Map<string, {
|
|
66
|
+
subtree: string;
|
|
67
|
+
data: Record<string, unknown>;
|
|
68
|
+
}>;
|
|
69
|
+
readonly history: Array<{
|
|
70
|
+
id: string;
|
|
71
|
+
version: number;
|
|
72
|
+
data: Record<string, unknown>;
|
|
73
|
+
createdAt: Date;
|
|
74
|
+
}>;
|
|
75
|
+
readonly subdocStates: Map<string, Uint8Array<ArrayBufferLike>>;
|
|
76
|
+
readonly edges: Array<{
|
|
77
|
+
source: string;
|
|
78
|
+
label: string;
|
|
79
|
+
target: string;
|
|
80
|
+
}>;
|
|
81
|
+
readonly vectors: Map<string, {
|
|
82
|
+
subtree: string;
|
|
83
|
+
embedding: number[];
|
|
84
|
+
}>;
|
|
85
|
+
upsertNode(id: string, subtree: string, data: Record<string, unknown>): Promise<void>;
|
|
86
|
+
getNode(id: string): Promise<{
|
|
87
|
+
id: string;
|
|
88
|
+
subtree: string;
|
|
89
|
+
data: Record<string, unknown>;
|
|
90
|
+
updatedAt: Date;
|
|
91
|
+
} | null>;
|
|
92
|
+
listNodes(subtree?: string): Promise<Array<{
|
|
93
|
+
id: string;
|
|
94
|
+
subtree: string;
|
|
95
|
+
data: Record<string, unknown>;
|
|
96
|
+
updatedAt: Date;
|
|
97
|
+
}>>;
|
|
98
|
+
appendHistory(id: string, version: number, data: Record<string, unknown>): Promise<void>;
|
|
99
|
+
getMaxVersion(id: string): Promise<number>;
|
|
100
|
+
upsertSubdocState(subtreeId: string, yjsState: Uint8Array): Promise<void>;
|
|
101
|
+
addGraphEdge(source: string, label: string, target: string): Promise<void>;
|
|
102
|
+
removeGraphEdge(source: string, label: string, target: string): Promise<void>;
|
|
103
|
+
upsertVector(nodeId: string, subtree: string, embedding: number[]): Promise<void>;
|
|
104
|
+
cypherQuery(_query: string, _params?: Record<string, unknown>): Promise<Record<string, unknown>[]>;
|
|
105
|
+
vectorSearch(embedding: number[], k: number): Promise<Array<{
|
|
106
|
+
nodeId: string;
|
|
107
|
+
distance: number;
|
|
108
|
+
}>>;
|
|
109
|
+
getHistory(id: string): Promise<Array<{
|
|
110
|
+
version: number;
|
|
111
|
+
data: Record<string, unknown>;
|
|
112
|
+
createdAt: Date;
|
|
113
|
+
}>>;
|
|
114
|
+
getVersionAtTimestamp(id: string, timestamp: Date): Promise<Record<string, unknown> | null>;
|
|
115
|
+
}
|
|
116
|
+
export declare class ServerQueryBridge {
|
|
117
|
+
private readonly syncService;
|
|
118
|
+
private readonly acl;
|
|
119
|
+
private readonly db;
|
|
120
|
+
private readonly obs;
|
|
121
|
+
private readonly unsubscribes;
|
|
122
|
+
/** Per-node version counter. */
|
|
123
|
+
private readonly versionCounters;
|
|
124
|
+
constructor(syncService: ServerSyncService, acl: AclManager, db: DatabaseAdapter, obs: ObservabilityContext);
|
|
125
|
+
/**
|
|
126
|
+
* Start observing assigned subtrees and piping changes to the database.
|
|
127
|
+
*/
|
|
128
|
+
start(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Observe a single subtree for changes.
|
|
131
|
+
*/
|
|
132
|
+
observeSubtree(subtreeId: string): void;
|
|
133
|
+
/**
|
|
134
|
+
* Process a Yjs update and write decoded data to the database.
|
|
135
|
+
*/
|
|
136
|
+
private processUpdate;
|
|
137
|
+
/**
|
|
138
|
+
* Execute an openCypher query via the database.
|
|
139
|
+
*/
|
|
140
|
+
cypherQuery(query: string, params?: Record<string, unknown>): Promise<Record<string, unknown>[]>;
|
|
141
|
+
/**
|
|
142
|
+
* Execute a vector similarity search via the database.
|
|
143
|
+
*/
|
|
144
|
+
vectorSearch(embedding: number[], k: number): Promise<Array<{
|
|
145
|
+
nodeId: string;
|
|
146
|
+
distance: number;
|
|
147
|
+
}>>;
|
|
148
|
+
/**
|
|
149
|
+
* Get version history for a node.
|
|
150
|
+
*/
|
|
151
|
+
getHistory(nodeId: string): Promise<Array<{
|
|
152
|
+
version: number;
|
|
153
|
+
data: Record<string, unknown>;
|
|
154
|
+
createdAt: Date;
|
|
155
|
+
}>>;
|
|
156
|
+
/**
|
|
157
|
+
* Get state at a specific timestamp.
|
|
158
|
+
*/
|
|
159
|
+
getVersionAtTimestamp(nodeId: string, timestamp: Date): Promise<Record<string, unknown> | null>;
|
|
160
|
+
/**
|
|
161
|
+
* Stop observing and clean up.
|
|
162
|
+
*/
|
|
163
|
+
stop(): void;
|
|
164
|
+
/** Convert a Yjs value to a plain JSON-compatible object. */
|
|
165
|
+
private yjsValueToJson;
|
|
166
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Query Bridge — Yjs observeDeep → PostgreSQL pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Architecture: §2.2 Server Components, Query Bridge
|
|
5
|
+
*
|
|
6
|
+
* Listens to Yjs updates on unencrypted subdocs and writes to:
|
|
7
|
+
* - `nodes` table (JSONB decoded properties)
|
|
8
|
+
* - `node_history` table (append-only version chain)
|
|
9
|
+
* - AGE graph (edges)
|
|
10
|
+
* - pgvector embeddings (vectors)
|
|
11
|
+
*
|
|
12
|
+
* Encrypted subtrees are stored as opaque BYTEA only.
|
|
13
|
+
*/
|
|
14
|
+
import * as Y from 'yjs';
|
|
15
|
+
/** In-memory database adapter for testing without PostgreSQL. */
|
|
16
|
+
export class InMemoryDatabaseAdapter {
|
|
17
|
+
nodes = new Map();
|
|
18
|
+
history = [];
|
|
19
|
+
subdocStates = new Map();
|
|
20
|
+
edges = [];
|
|
21
|
+
vectors = new Map();
|
|
22
|
+
async upsertNode(id, subtree, data) {
|
|
23
|
+
this.nodes.set(id, { subtree, data });
|
|
24
|
+
}
|
|
25
|
+
async getNode(id) {
|
|
26
|
+
const entry = this.nodes.get(id);
|
|
27
|
+
if (!entry)
|
|
28
|
+
return null;
|
|
29
|
+
return { id, subtree: entry.subtree, data: entry.data, updatedAt: new Date() };
|
|
30
|
+
}
|
|
31
|
+
async listNodes(subtree) {
|
|
32
|
+
const results = [];
|
|
33
|
+
for (const [id, entry] of this.nodes) {
|
|
34
|
+
if (subtree === undefined || entry.subtree === subtree) {
|
|
35
|
+
results.push({ id, subtree: entry.subtree, data: entry.data, updatedAt: new Date() });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
async appendHistory(id, version, data) {
|
|
41
|
+
this.history.push({ id, version, data, createdAt: new Date() });
|
|
42
|
+
}
|
|
43
|
+
async getMaxVersion(id) {
|
|
44
|
+
let max = 0;
|
|
45
|
+
for (const entry of this.history) {
|
|
46
|
+
if (entry.id === id && entry.version > max)
|
|
47
|
+
max = entry.version;
|
|
48
|
+
}
|
|
49
|
+
return max;
|
|
50
|
+
}
|
|
51
|
+
async upsertSubdocState(subtreeId, yjsState) {
|
|
52
|
+
this.subdocStates.set(subtreeId, yjsState);
|
|
53
|
+
}
|
|
54
|
+
async addGraphEdge(source, label, target) {
|
|
55
|
+
this.edges.push({ source, label, target });
|
|
56
|
+
}
|
|
57
|
+
async removeGraphEdge(source, label, target) {
|
|
58
|
+
const idx = this.edges.findIndex((e) => e.source === source && e.label === label && e.target === target);
|
|
59
|
+
if (idx >= 0)
|
|
60
|
+
this.edges.splice(idx, 1);
|
|
61
|
+
}
|
|
62
|
+
async upsertVector(nodeId, subtree, embedding) {
|
|
63
|
+
this.vectors.set(nodeId, { subtree, embedding });
|
|
64
|
+
}
|
|
65
|
+
async cypherQuery(_query, _params) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
async vectorSearch(embedding, k) {
|
|
69
|
+
// Simple cosine distance
|
|
70
|
+
const results = [];
|
|
71
|
+
for (const [nodeId, entry] of this.vectors) {
|
|
72
|
+
const dist = cosineDistance(embedding, entry.embedding);
|
|
73
|
+
results.push({ nodeId, distance: dist });
|
|
74
|
+
}
|
|
75
|
+
results.sort((a, b) => a.distance - b.distance);
|
|
76
|
+
return results.slice(0, k);
|
|
77
|
+
}
|
|
78
|
+
async getHistory(id) {
|
|
79
|
+
return this.history
|
|
80
|
+
.filter((h) => h.id === id)
|
|
81
|
+
.sort((a, b) => a.version - b.version);
|
|
82
|
+
}
|
|
83
|
+
async getVersionAtTimestamp(id, timestamp) {
|
|
84
|
+
const entries = this.history
|
|
85
|
+
.filter((h) => h.id === id && h.createdAt.getTime() <= timestamp.getTime())
|
|
86
|
+
.sort((a, b) => b.version - a.version);
|
|
87
|
+
return entries.length > 0 ? entries[0].data : null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ── Query Bridge ───────────────────────────────────────────
|
|
91
|
+
// @req FR-46
|
|
92
|
+
// @req FR-50
|
|
93
|
+
// @req FR-51
|
|
94
|
+
// @req FR-52
|
|
95
|
+
// @req FR-53
|
|
96
|
+
// @req FR-54
|
|
97
|
+
export class ServerQueryBridge {
|
|
98
|
+
syncService;
|
|
99
|
+
acl;
|
|
100
|
+
db;
|
|
101
|
+
obs;
|
|
102
|
+
unsubscribes = [];
|
|
103
|
+
/** Per-node version counter. */
|
|
104
|
+
versionCounters = new Map();
|
|
105
|
+
constructor(syncService, acl, db, obs) {
|
|
106
|
+
this.syncService = syncService;
|
|
107
|
+
this.acl = acl;
|
|
108
|
+
this.db = db;
|
|
109
|
+
this.obs = obs;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Start observing assigned subtrees and piping changes to the database.
|
|
113
|
+
*/
|
|
114
|
+
start() {
|
|
115
|
+
const subtrees = this.syncService.getAssignedSubtrees();
|
|
116
|
+
for (const subtreeId of subtrees) {
|
|
117
|
+
this.observeSubtree(subtreeId);
|
|
118
|
+
}
|
|
119
|
+
this.obs.logger.info({ subtreeCount: subtrees.length }, 'query bridge started');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Observe a single subtree for changes.
|
|
123
|
+
*/
|
|
124
|
+
observeSubtree(subtreeId) {
|
|
125
|
+
const unsub = this.syncService.onUpdate(subtreeId, (_sid, update) => {
|
|
126
|
+
void this.processUpdate(subtreeId, update);
|
|
127
|
+
});
|
|
128
|
+
this.unsubscribes.push(unsub);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Process a Yjs update and write decoded data to the database.
|
|
132
|
+
*/
|
|
133
|
+
// @req FR-31
|
|
134
|
+
// @req FR-52
|
|
135
|
+
// @req FR-54
|
|
136
|
+
async processUpdate(subtreeId, _update) {
|
|
137
|
+
// Check if subtree is encrypted — if so, only store opaque state
|
|
138
|
+
if (this.acl.hasAcl(subtreeId)) {
|
|
139
|
+
const node = this.acl.getRefNode(subtreeId);
|
|
140
|
+
if (node?.encrypted) {
|
|
141
|
+
// Encrypted subtrees: store only raw Yjs state
|
|
142
|
+
const state = this.syncService.encodeStateAsUpdate(subtreeId);
|
|
143
|
+
await this.db.upsertSubdocState(subtreeId, state);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Unencrypted: decode Yjs state and write to PostgreSQL
|
|
148
|
+
const doc = this.syncService.getSubdoc(subtreeId);
|
|
149
|
+
const nodesMap = doc.getMap('nodes');
|
|
150
|
+
for (const [key, value] of nodesMap.entries()) {
|
|
151
|
+
const nodeId = `${subtreeId}.${key}`;
|
|
152
|
+
const data = this.yjsValueToJson(value);
|
|
153
|
+
if (data && typeof data === 'object' && !Array.isArray(data)) {
|
|
154
|
+
// Upsert to nodes table
|
|
155
|
+
await this.db.upsertNode(nodeId, subtreeId, data);
|
|
156
|
+
// Append to version history (append-only, FR-54)
|
|
157
|
+
// On first write after startup, seed from DB to survive restarts
|
|
158
|
+
if (!this.versionCounters.has(nodeId)) {
|
|
159
|
+
this.versionCounters.set(nodeId, await this.db.getMaxVersion(nodeId));
|
|
160
|
+
}
|
|
161
|
+
const version = this.versionCounters.get(nodeId) + 1;
|
|
162
|
+
this.versionCounters.set(nodeId, version);
|
|
163
|
+
await this.db.appendHistory(nodeId, version, data);
|
|
164
|
+
}
|
|
165
|
+
// Check for vector embeddings
|
|
166
|
+
if (data && typeof data === 'object' && !Array.isArray(data)) {
|
|
167
|
+
const record = data;
|
|
168
|
+
if (record['_vector'] && Array.isArray(record['_vector'])) {
|
|
169
|
+
await this.db.upsertVector(nodeId, subtreeId, record['_vector']);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Process edges
|
|
174
|
+
const edgesMap = doc.getMap('edges');
|
|
175
|
+
for (const [edgeKey, value] of edgesMap.entries()) {
|
|
176
|
+
// Edge keys are stored as 'label\0target'
|
|
177
|
+
const sepIdx = edgeKey.indexOf('\0');
|
|
178
|
+
if (sepIdx >= 0 && value === true) {
|
|
179
|
+
const label = edgeKey.substring(0, sepIdx);
|
|
180
|
+
const target = edgeKey.substring(sepIdx + 1);
|
|
181
|
+
await this.db.addGraphEdge(subtreeId, label, target);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Execute an openCypher query via the database.
|
|
187
|
+
*/
|
|
188
|
+
// @req FR-46
|
|
189
|
+
async cypherQuery(query, params) {
|
|
190
|
+
return this.db.cypherQuery(query, params);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Execute a vector similarity search via the database.
|
|
194
|
+
*/
|
|
195
|
+
// @req FR-50
|
|
196
|
+
async vectorSearch(embedding, k) {
|
|
197
|
+
return this.db.vectorSearch(embedding, k);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get version history for a node.
|
|
201
|
+
*/
|
|
202
|
+
// @req FR-52
|
|
203
|
+
// @req FR-53
|
|
204
|
+
async getHistory(nodeId) {
|
|
205
|
+
return this.db.getHistory(nodeId);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get state at a specific timestamp.
|
|
209
|
+
*/
|
|
210
|
+
// @req FR-53
|
|
211
|
+
async getVersionAtTimestamp(nodeId, timestamp) {
|
|
212
|
+
return this.db.getVersionAtTimestamp(nodeId, timestamp);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Stop observing and clean up.
|
|
216
|
+
*/
|
|
217
|
+
stop() {
|
|
218
|
+
for (const unsub of this.unsubscribes) {
|
|
219
|
+
unsub();
|
|
220
|
+
}
|
|
221
|
+
this.unsubscribes.length = 0;
|
|
222
|
+
}
|
|
223
|
+
// ── Helpers ─────────────────────────────────────────────
|
|
224
|
+
/** Convert a Yjs value to a plain JSON-compatible object. */
|
|
225
|
+
yjsValueToJson(value) {
|
|
226
|
+
if (value instanceof Y.Map) {
|
|
227
|
+
const obj = {};
|
|
228
|
+
for (const [k, v] of value.entries()) {
|
|
229
|
+
obj[k] = this.yjsValueToJson(v);
|
|
230
|
+
}
|
|
231
|
+
return obj;
|
|
232
|
+
}
|
|
233
|
+
if (value instanceof Y.Array) {
|
|
234
|
+
const arr = [];
|
|
235
|
+
for (const item of value) {
|
|
236
|
+
arr.push(this.yjsValueToJson(item));
|
|
237
|
+
}
|
|
238
|
+
return arr;
|
|
239
|
+
}
|
|
240
|
+
return value;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// ── Utilities ──────────────────────────────────────────────
|
|
244
|
+
function cosineDistance(a, b) {
|
|
245
|
+
let dot = 0;
|
|
246
|
+
let magA = 0;
|
|
247
|
+
let magB = 0;
|
|
248
|
+
for (let i = 0; i < a.length; i++) {
|
|
249
|
+
dot += (a[i] ?? 0) * (b[i] ?? 0);
|
|
250
|
+
magA += (a[i] ?? 0) ** 2;
|
|
251
|
+
magB += (b[i] ?? 0) ** 2;
|
|
252
|
+
}
|
|
253
|
+
const denom = Math.sqrt(magA) * Math.sqrt(magB);
|
|
254
|
+
if (denom === 0)
|
|
255
|
+
return 1;
|
|
256
|
+
return 1 - dot / denom;
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=query-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-bridge.js","sourceRoot":"","sources":["../../src/server/query-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Yjs Sync Service — relay with selective replication.
|
|
3
|
+
*
|
|
4
|
+
* Architecture: §2.2 Server Components, Yjs Sync Service
|
|
5
|
+
*
|
|
6
|
+
* - Maintains Yjs state in memory per subdocument
|
|
7
|
+
* - Selective replication based on ACL
|
|
8
|
+
* - Never evicts data (persistent source of truth)
|
|
9
|
+
* - Manages subtree assignments (FR-37, FR-38)
|
|
10
|
+
*/
|
|
11
|
+
import * as Y from 'yjs';
|
|
12
|
+
import type { AclManager } from '../acl.js';
|
|
13
|
+
import type { ObservabilityContext } from '../observability.js';
|
|
14
|
+
export interface SubtreeAssignment {
|
|
15
|
+
subtreeId: string;
|
|
16
|
+
maxSize?: number;
|
|
17
|
+
vectorDimensions?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ServerSyncConfig {
|
|
20
|
+
/** Subtrees this server is configured to replicate. */
|
|
21
|
+
subtrees: SubtreeAssignment[];
|
|
22
|
+
}
|
|
23
|
+
export interface PeerAuthorization {
|
|
24
|
+
peerId: string;
|
|
25
|
+
/** Subtrees this peer is authorized to sync. */
|
|
26
|
+
authorizedSubtrees: Set<string>;
|
|
27
|
+
}
|
|
28
|
+
export declare class ServerSyncService {
|
|
29
|
+
private readonly acl;
|
|
30
|
+
private readonly obs;
|
|
31
|
+
/** Yjs docs maintained by the server — persistent, never evicted. */
|
|
32
|
+
private readonly subdocs;
|
|
33
|
+
/** Configured subtree assignments. */
|
|
34
|
+
private readonly assignments;
|
|
35
|
+
/** Authorized peers. */
|
|
36
|
+
private readonly peers;
|
|
37
|
+
/** Change listeners for observeDeep pipelines. */
|
|
38
|
+
private readonly changeListeners;
|
|
39
|
+
constructor(acl: AclManager, obs: ObservabilityContext, config?: ServerSyncConfig);
|
|
40
|
+
/**
|
|
41
|
+
* Get or create a Yjs doc for a subtree.
|
|
42
|
+
* Server never evicts — all docs are retained.
|
|
43
|
+
*/
|
|
44
|
+
getSubdoc(subtreeId: string): Y.Doc;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a subtree is configured for replication on this server.
|
|
47
|
+
*/
|
|
48
|
+
isAssigned(subtreeId: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Request inclusion of a new subtree (client-initiated).
|
|
51
|
+
*/
|
|
52
|
+
requestInclusion(subtreeId: string, requesterId: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Authorize a peer for specific subtree(s).
|
|
55
|
+
*/
|
|
56
|
+
authorizePeer(peerId: string, subtreeIds: string[]): void;
|
|
57
|
+
/**
|
|
58
|
+
* Deauthorize a peer.
|
|
59
|
+
*/
|
|
60
|
+
deauthorizePeer(peerId: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Check if a peer is authorized to sync a subtree.
|
|
63
|
+
*/
|
|
64
|
+
isPeerAuthorized(peerId: string, subtreeId: string): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Apply a Yjs update to a server-side subdoc.
|
|
67
|
+
* Only processes if the subtree is assigned.
|
|
68
|
+
*/
|
|
69
|
+
applyUpdate(subtreeId: string, update: Uint8Array, fromPeerId?: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get Yjs state vector for a subtree.
|
|
72
|
+
*/
|
|
73
|
+
getStateVector(subtreeId: string): Uint8Array;
|
|
74
|
+
/**
|
|
75
|
+
* Encode state as update (diff from remote state vector).
|
|
76
|
+
*/
|
|
77
|
+
encodeStateAsUpdate(subtreeId: string, remoteStateVector?: Uint8Array): Uint8Array;
|
|
78
|
+
/**
|
|
79
|
+
* Subscribe to changes on a subtree (for Query Bridge pipeline).
|
|
80
|
+
*/
|
|
81
|
+
onUpdate(subtreeId: string, listener: (subtreeId: string, update: Uint8Array) => void): () => void;
|
|
82
|
+
/**
|
|
83
|
+
* Get all assigned subtree IDs.
|
|
84
|
+
*/
|
|
85
|
+
getAssignedSubtrees(): string[];
|
|
86
|
+
/**
|
|
87
|
+
* Get count of subdocs held in memory.
|
|
88
|
+
*/
|
|
89
|
+
getSubdocCount(): number;
|
|
90
|
+
/**
|
|
91
|
+
* Get authorized peers for a subtree.
|
|
92
|
+
*/
|
|
93
|
+
getAuthorizedPeers(subtreeId: string): string[];
|
|
94
|
+
/**
|
|
95
|
+
* Clean up all resources.
|
|
96
|
+
*/
|
|
97
|
+
close(): void;
|
|
98
|
+
}
|