sietch 0.10.3 → 0.14.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/server/acl-authority.js +12 -0
- package/dist/server/acl-authority.js.map +1 -1
- package/dist/server/pg-storage.d.ts +18 -1
- package/dist/server/pg-storage.js +69 -10
- package/dist/server/pg-storage.js.map +1 -1
- package/dist/server/query-bridge.d.ts +25 -1
- package/dist/server/query-bridge.js +31 -4
- package/dist/server/query-bridge.js.map +1 -1
- package/dist/server/server.d.ts +73 -6
- package/dist/server/server.js +137 -20
- package/dist/server/server.js.map +1 -1
- package/dist/server/sync-service.d.ts +15 -0
- package/dist/server/sync-service.js +30 -0
- package/dist/server/sync-service.js.map +1 -1
- package/dist/store.d.ts +7 -0
- package/dist/store.js +21 -0
- package/dist/store.js.map +1 -1
- package/dist/sync-engine.d.ts +74 -0
- package/dist/sync-engine.js +121 -10
- package/dist/sync-engine.js.map +1 -1
- package/dist/yjs-engine.d.ts +13 -0
- package/dist/yjs-engine.js +31 -1
- package/dist/yjs-engine.js.map +1 -1
- package/package.json +2 -1
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
import { sign, verify, generateCek, wrapCek, } from '../crypto.js';
|
|
12
12
|
import { serializeAclPayload, } from '../acl.js';
|
|
13
13
|
import { AclError, PermissionDeniedError } from '../errors.js';
|
|
14
|
+
// AMD-006: libp2p peerIds are base58-encoded multihashes with stable
|
|
15
|
+
// prefixes — Ed25519 starts with "12D3KooW", legacy RSA with "Qm".
|
|
16
|
+
// Sietch identity peerIds are lowercase-hex digests (no such prefix).
|
|
17
|
+
const LIBP2P_PEERID_SHAPE = /^(12D3KooW|Qm[1-9A-HJ-NP-Za-km-z]{43,46})/;
|
|
14
18
|
/** Default signing backend wrapping a HybridKeypair. */
|
|
15
19
|
export class DefaultSigningBackend {
|
|
16
20
|
keypair;
|
|
@@ -171,6 +175,14 @@ export class ServerAclAuthority {
|
|
|
171
175
|
if (!request.permissions) {
|
|
172
176
|
return { ok: false, error: new AclError('Grant requires permissions', 'ACL_MISSING_PERMS') };
|
|
173
177
|
}
|
|
178
|
+
// AMD-006: warn if targetUserId looks like a libp2p peerId. Sietch
|
|
179
|
+
// identityPeerIds are 32-byte hex digests; libp2p peerIds are
|
|
180
|
+
// base58-encoded multihashes starting with `12D3` (Ed25519) or `Qm`
|
|
181
|
+
// (RSA). Grants keyed against libp2p peerIds silently no-op because
|
|
182
|
+
// the sync gate checks sietch identityPeerId.
|
|
183
|
+
if (LIBP2P_PEERID_SHAPE.test(request.targetUserId)) {
|
|
184
|
+
this.obs.logger.warn({ subtreeId: request.subtreeId, targetUserId: request.targetUserId }, '[AMD-006] ACL grant target looks like a libp2p peerId — write gate keys on sietch identityPeerId. Grants against libp2p peerIds silently no-op. Use ctx.aclTarget (== ctx.sietchIdentityPeerId) from the HandshakeHook instead.');
|
|
185
|
+
}
|
|
174
186
|
// For existing subtrees, validate requester is admin
|
|
175
187
|
if (existing) {
|
|
176
188
|
const requesterPerms = existing.acl[request.requesterId];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acl-authority.js","sourceRoot":"","sources":["../../src/server/acl-authority.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,IAAI,EACJ,MAAM,EACN,WAAW,EACX,OAAO,GAIR,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"acl-authority.js","sourceRoot":"","sources":["../../src/server/acl-authority.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The pool is NOT owned by this backend — close() is a no-op.
|
|
9
9
|
* The caller owns the pool and may share it with PostgreSQLDatabaseAdapter.
|
|
10
|
+
*
|
|
11
|
+
* AMD-008: `pg.Pool` emits an `'error'` event when a connection is closed
|
|
12
|
+
* by the server (administrator command, restart, ECONNRESET); unhandled,
|
|
13
|
+
* this crashes the process. The constructor now registers a listener so
|
|
14
|
+
* such errors are logged and swallowed. All queries are wrapped in a
|
|
15
|
+
* retry-on-transient loop (3 attempts, 100/500/2500 ms backoff) so a
|
|
16
|
+
* brief PG bounce no longer fails caller writes.
|
|
10
17
|
*/
|
|
11
18
|
import pg from 'pg';
|
|
12
19
|
import type { StorageBackend } from '../storage.js';
|
|
13
20
|
import type { StorageCapacity } from '../types.js';
|
|
21
|
+
import type { ObservabilityContext } from '../observability.js';
|
|
14
22
|
export declare class PostgresStorageBackend implements StorageBackend {
|
|
15
23
|
readonly type: "postgres";
|
|
16
24
|
private pool;
|
|
17
25
|
private schemaReady;
|
|
18
|
-
|
|
26
|
+
private obs;
|
|
27
|
+
constructor(pool: pg.Pool, obs?: ObservabilityContext);
|
|
19
28
|
/**
|
|
20
29
|
* Ensure required tables exist. Idempotent — safe to call on every startup.
|
|
21
30
|
* Does NOT create `nodes`, `node_history`, `vectors`, or AGE graph —
|
|
@@ -47,4 +56,12 @@ export declare class PostgresStorageBackend implements StorageBackend {
|
|
|
47
56
|
close(): Promise<void>;
|
|
48
57
|
private kvUpsert;
|
|
49
58
|
private kvLoad;
|
|
59
|
+
/**
|
|
60
|
+
* AMD-008: per-query retry on transient PG errors.
|
|
61
|
+
*
|
|
62
|
+
* Retries up to 3 times (4 total attempts) on `terminating connection`,
|
|
63
|
+
* `ECONNRESET`, and similar disconnect classes. Backoff: 100, 500, 2500 ms.
|
|
64
|
+
* Permanent errors (auth, syntax, schema) bypass retries and throw.
|
|
65
|
+
*/
|
|
66
|
+
private runQuery;
|
|
50
67
|
}
|
|
@@ -7,14 +7,47 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The pool is NOT owned by this backend — close() is a no-op.
|
|
9
9
|
* The caller owns the pool and may share it with PostgreSQLDatabaseAdapter.
|
|
10
|
+
*
|
|
11
|
+
* AMD-008: `pg.Pool` emits an `'error'` event when a connection is closed
|
|
12
|
+
* by the server (administrator command, restart, ECONNRESET); unhandled,
|
|
13
|
+
* this crashes the process. The constructor now registers a listener so
|
|
14
|
+
* such errors are logged and swallowed. All queries are wrapped in a
|
|
15
|
+
* retry-on-transient loop (3 attempts, 100/500/2500 ms backoff) so a
|
|
16
|
+
* brief PG bounce no longer fails caller writes.
|
|
10
17
|
*/
|
|
18
|
+
// AMD-008: transient PG error class detection. We retry on:
|
|
19
|
+
// - Connection terminated by administrator (`57P01`)
|
|
20
|
+
// - Crash shutdown (`57P02`), cannot connect now (`57P03`)
|
|
21
|
+
// - Admin shutdown (`57P04`), idle session timeout (`57P05`)
|
|
22
|
+
// - ECONNRESET / EPIPE / read ECONNRESET at the socket layer
|
|
23
|
+
// - "Connection terminated unexpectedly" — node-postgres pool message
|
|
24
|
+
const TRANSIENT_PG_CODES = new Set(['57P01', '57P02', '57P03', '57P04', '57P05']);
|
|
25
|
+
const TRANSIENT_PG_MESSAGE = /terminating connection|Connection terminated|ECONNRESET|EPIPE|read ECONNRESET|server closed the connection unexpectedly/i;
|
|
26
|
+
function isTransientPgError(err) {
|
|
27
|
+
if (!err || typeof err !== 'object')
|
|
28
|
+
return false;
|
|
29
|
+
const e = err;
|
|
30
|
+
if (typeof e.code === 'string' && TRANSIENT_PG_CODES.has(e.code))
|
|
31
|
+
return true;
|
|
32
|
+
if (typeof e.message === 'string' && TRANSIENT_PG_MESSAGE.test(e.message))
|
|
33
|
+
return true;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const RETRY_DELAYS_MS = [100, 500, 2500];
|
|
11
37
|
// @req FR-02
|
|
12
38
|
export class PostgresStorageBackend {
|
|
13
39
|
type = 'postgres';
|
|
14
40
|
pool;
|
|
15
41
|
schemaReady = false;
|
|
16
|
-
|
|
42
|
+
obs;
|
|
43
|
+
constructor(pool, obs) {
|
|
17
44
|
this.pool = pool;
|
|
45
|
+
this.obs = obs;
|
|
46
|
+
// AMD-008: trap pool-level errors that otherwise propagate as
|
|
47
|
+
// uncaughtException and crash the process during PG restarts.
|
|
48
|
+
pool.on('error', (err) => {
|
|
49
|
+
this.obs?.logger.warn({ err: String(err), code: err.code }, '[AMD-008] pg.Pool error swallowed — query-level retry will handle reconnection');
|
|
50
|
+
});
|
|
18
51
|
}
|
|
19
52
|
/**
|
|
20
53
|
* Ensure required tables exist. Idempotent — safe to call on every startup.
|
|
@@ -24,14 +57,14 @@ export class PostgresStorageBackend {
|
|
|
24
57
|
async ensureSchema() {
|
|
25
58
|
if (this.schemaReady)
|
|
26
59
|
return;
|
|
27
|
-
await this.
|
|
60
|
+
await this.runQuery(`
|
|
28
61
|
CREATE TABLE IF NOT EXISTS subdoc_states (
|
|
29
62
|
subtree_id TEXT PRIMARY KEY,
|
|
30
63
|
yjs_state BYTEA NOT NULL,
|
|
31
64
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
32
65
|
)
|
|
33
66
|
`);
|
|
34
|
-
await this.
|
|
67
|
+
await this.runQuery(`
|
|
35
68
|
CREATE TABLE IF NOT EXISTS sietch_kv (
|
|
36
69
|
key TEXT PRIMARY KEY,
|
|
37
70
|
value BYTEA NOT NULL,
|
|
@@ -42,22 +75,22 @@ export class PostgresStorageBackend {
|
|
|
42
75
|
}
|
|
43
76
|
// ── Subdoc persistence ──────────────────────────────────
|
|
44
77
|
async persistSubdoc(subtreeId, state) {
|
|
45
|
-
await this.
|
|
78
|
+
await this.runQuery(`INSERT INTO subdoc_states (subtree_id, yjs_state, updated_at)
|
|
46
79
|
VALUES ($1, $2, now())
|
|
47
80
|
ON CONFLICT (subtree_id) DO UPDATE SET yjs_state = $2, updated_at = now()`, [subtreeId, Buffer.from(state)]);
|
|
48
81
|
}
|
|
49
82
|
async loadSubdoc(subtreeId) {
|
|
50
|
-
const result = await this.
|
|
83
|
+
const result = await this.runQuery('SELECT yjs_state FROM subdoc_states WHERE subtree_id = $1', [subtreeId]);
|
|
51
84
|
if (result.rows.length === 0)
|
|
52
85
|
return null;
|
|
53
86
|
const buf = result.rows[0].yjs_state;
|
|
54
87
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
55
88
|
}
|
|
56
89
|
async deleteSubdoc(subtreeId) {
|
|
57
|
-
await this.
|
|
90
|
+
await this.runQuery('DELETE FROM subdoc_states WHERE subtree_id = $1', [subtreeId]);
|
|
58
91
|
}
|
|
59
92
|
async listSubdocs() {
|
|
60
|
-
const result = await this.
|
|
93
|
+
const result = await this.runQuery('SELECT subtree_id FROM subdoc_states ORDER BY subtree_id');
|
|
61
94
|
return result.rows.map((row) => row.subtree_id);
|
|
62
95
|
}
|
|
63
96
|
// ── Capacity ────────────────────────────────────────────
|
|
@@ -94,7 +127,7 @@ export class PostgresStorageBackend {
|
|
|
94
127
|
await this.kvUpsert(`meta:${id}`, encoded);
|
|
95
128
|
}
|
|
96
129
|
async listSubdocMetadata() {
|
|
97
|
-
const result = await this.
|
|
130
|
+
const result = await this.runQuery("SELECT key, value FROM sietch_kv WHERE key LIKE 'meta:%' ORDER BY key");
|
|
98
131
|
return result.rows.map((row) => {
|
|
99
132
|
const id = row.key.slice(5); // strip 'meta:'
|
|
100
133
|
const meta = JSON.parse(row.value.toString());
|
|
@@ -107,16 +140,42 @@ export class PostgresStorageBackend {
|
|
|
107
140
|
}
|
|
108
141
|
// ── Private helpers ─────────────────────────────────────
|
|
109
142
|
async kvUpsert(key, value) {
|
|
110
|
-
await this.
|
|
143
|
+
await this.runQuery(`INSERT INTO sietch_kv (key, value, updated_at)
|
|
111
144
|
VALUES ($1, $2, now())
|
|
112
145
|
ON CONFLICT (key) DO UPDATE SET value = $2, updated_at = now()`, [key, value]);
|
|
113
146
|
}
|
|
114
147
|
async kvLoad(key) {
|
|
115
|
-
const result = await this.
|
|
148
|
+
const result = await this.runQuery('SELECT value FROM sietch_kv WHERE key = $1', [key]);
|
|
116
149
|
if (result.rows.length === 0)
|
|
117
150
|
return null;
|
|
118
151
|
const buf = result.rows[0].value;
|
|
119
152
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
120
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* AMD-008: per-query retry on transient PG errors.
|
|
156
|
+
*
|
|
157
|
+
* Retries up to 3 times (4 total attempts) on `terminating connection`,
|
|
158
|
+
* `ECONNRESET`, and similar disconnect classes. Backoff: 100, 500, 2500 ms.
|
|
159
|
+
* Permanent errors (auth, syntax, schema) bypass retries and throw.
|
|
160
|
+
*/
|
|
161
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
162
|
+
async runQuery(text, params) {
|
|
163
|
+
let lastErr;
|
|
164
|
+
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
|
|
165
|
+
try {
|
|
166
|
+
return await this.pool.query(text, params);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
lastErr = err;
|
|
170
|
+
if (!isTransientPgError(err) || attempt === RETRY_DELAYS_MS.length) {
|
|
171
|
+
throw err;
|
|
172
|
+
}
|
|
173
|
+
const delay = RETRY_DELAYS_MS[attempt];
|
|
174
|
+
this.obs?.logger.warn({ attempt: attempt + 1, delay, err: String(err) }, '[AMD-008] transient PG error, retrying');
|
|
175
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
throw lastErr;
|
|
179
|
+
}
|
|
121
180
|
}
|
|
122
181
|
//# sourceMappingURL=pg-storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-storage.js","sourceRoot":"","sources":["../../src/server/pg-storage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pg-storage.js","sourceRoot":"","sources":["../../src/server/pg-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,18 @@ export interface BridgeStateSource {
|
|
|
24
24
|
encodeStateAsUpdate(subtreeId: string, remoteStateVector?: Uint8Array): Uint8Array | Promise<Uint8Array>;
|
|
25
25
|
/** Get list of assigned/active subtrees. */
|
|
26
26
|
getAssignedSubtrees(): string[];
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to subdoc-materialization events. Fires on first load and on
|
|
29
|
+
* every post-eviction reload. AMD-004: lets the bridge auto-discover
|
|
30
|
+
* subtrees that appear from remote sync, not just locally written ones.
|
|
31
|
+
*/
|
|
32
|
+
onSubdocLoaded(listener: (subtreeId: string) => void): () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Subscribe to subdoc-unload events. Fires when a subdoc is evicted from
|
|
35
|
+
* memory. The bridge clears its per-subtree tracking so a subsequent
|
|
36
|
+
* reload re-attaches a fresh update observer to the new `Y.Doc`.
|
|
37
|
+
*/
|
|
38
|
+
onSubdocUnloaded(listener: (subtreeId: string) => void): () => void;
|
|
27
39
|
}
|
|
28
40
|
/** Abstract database interface for PostgreSQL operations. */
|
|
29
41
|
export interface DatabaseAdapter {
|
|
@@ -140,12 +152,24 @@ export declare class ServerQueryBridge {
|
|
|
140
152
|
*/
|
|
141
153
|
private readonly lastSeenHash;
|
|
142
154
|
constructor(stateSource: BridgeStateSource, acl: AclManager, db: DatabaseAdapter, obs: ObservabilityContext);
|
|
155
|
+
/** Subtrees this bridge has already attached an observer for. */
|
|
156
|
+
private readonly observed;
|
|
143
157
|
/**
|
|
144
158
|
* Start observing assigned subtrees and piping changes to the database.
|
|
159
|
+
*
|
|
160
|
+
* Bridge discovery is bridge-owned (AMD-004): subtrees materialized by
|
|
161
|
+
* remote sync are auto-observed via `onSubdocLoaded` in addition to the
|
|
162
|
+
* subtrees the state source reports at boot. The bridge no longer
|
|
163
|
+
* requires the server to plumb `ensureBridged` calls through write
|
|
164
|
+
* paths.
|
|
165
|
+
*
|
|
166
|
+
* @req FR-74
|
|
145
167
|
*/
|
|
146
168
|
start(): void;
|
|
147
169
|
/**
|
|
148
|
-
* Observe a single subtree for changes.
|
|
170
|
+
* Observe a single subtree for changes. Idempotent — repeated calls for
|
|
171
|
+
* the same subtree (e.g. boot list plus an early `onSubdocLoaded` event)
|
|
172
|
+
* attach only one observer.
|
|
149
173
|
*/
|
|
150
174
|
observeSubtree(subtreeId: string): void;
|
|
151
175
|
/**
|
|
@@ -115,20 +115,47 @@ export class ServerQueryBridge {
|
|
|
115
115
|
this.db = db;
|
|
116
116
|
this.obs = obs;
|
|
117
117
|
}
|
|
118
|
+
/** Subtrees this bridge has already attached an observer for. */
|
|
119
|
+
observed = new Set();
|
|
118
120
|
/**
|
|
119
121
|
* Start observing assigned subtrees and piping changes to the database.
|
|
122
|
+
*
|
|
123
|
+
* Bridge discovery is bridge-owned (AMD-004): subtrees materialized by
|
|
124
|
+
* remote sync are auto-observed via `onSubdocLoaded` in addition to the
|
|
125
|
+
* subtrees the state source reports at boot. The bridge no longer
|
|
126
|
+
* requires the server to plumb `ensureBridged` calls through write
|
|
127
|
+
* paths.
|
|
128
|
+
*
|
|
129
|
+
* @req FR-74
|
|
120
130
|
*/
|
|
121
131
|
start() {
|
|
122
|
-
const
|
|
123
|
-
for (const subtreeId of
|
|
132
|
+
const initial = this.stateSource.getAssignedSubtrees();
|
|
133
|
+
for (const subtreeId of initial) {
|
|
124
134
|
this.observeSubtree(subtreeId);
|
|
125
135
|
}
|
|
126
|
-
|
|
136
|
+
// Auto-discover subtrees materialized after boot (remote sync,
|
|
137
|
+
// post-eviction reload, deferred local writes).
|
|
138
|
+
const unsubLoad = this.stateSource.onSubdocLoaded((subtreeId) => {
|
|
139
|
+
this.observeSubtree(subtreeId);
|
|
140
|
+
});
|
|
141
|
+
this.unsubscribes.push(unsubLoad);
|
|
142
|
+
// Drop per-subtree tracking on eviction so the next load re-attaches
|
|
143
|
+
// an observer to the new Y.Doc (the old observer dies with doc.destroy).
|
|
144
|
+
const unsubUnload = this.stateSource.onSubdocUnloaded((subtreeId) => {
|
|
145
|
+
this.observed.delete(subtreeId);
|
|
146
|
+
});
|
|
147
|
+
this.unsubscribes.push(unsubUnload);
|
|
148
|
+
this.obs.logger.info({ subtreeCount: this.observed.size }, 'query bridge started');
|
|
127
149
|
}
|
|
128
150
|
/**
|
|
129
|
-
* Observe a single subtree for changes.
|
|
151
|
+
* Observe a single subtree for changes. Idempotent — repeated calls for
|
|
152
|
+
* the same subtree (e.g. boot list plus an early `onSubdocLoaded` event)
|
|
153
|
+
* attach only one observer.
|
|
130
154
|
*/
|
|
131
155
|
observeSubtree(subtreeId) {
|
|
156
|
+
if (this.observed.has(subtreeId))
|
|
157
|
+
return;
|
|
158
|
+
this.observed.add(subtreeId);
|
|
132
159
|
const unsub = this.stateSource.onUpdate(subtreeId, (_sid, update) => {
|
|
133
160
|
void this.processUpdate(subtreeId, update);
|
|
134
161
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-bridge.js","sourceRoot":"","sources":["../../src/server/query-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"query-bridge.js","sourceRoot":"","sources":["../../src/server/query-bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/server/server.d.ts
CHANGED
|
@@ -16,7 +16,10 @@ import { type PublicIdentity } from '../identity.js';
|
|
|
16
16
|
import { type StorageBackend } from '../storage.js';
|
|
17
17
|
import type { SyncConfig, HandshakeHook } from '../sync-engine.js';
|
|
18
18
|
import { type DatabaseAdapter } from './query-bridge.js';
|
|
19
|
-
import { type AclSigningBackend } from './acl-authority.js';
|
|
19
|
+
import { ServerAclAuthority, type AclSigningBackend } from './acl-authority.js';
|
|
20
|
+
import { type AclReferenceNode } from '../acl.js';
|
|
21
|
+
import type { AclPermissions } from '../types.js';
|
|
22
|
+
import type { HybridPublicKey } from '../crypto.js';
|
|
20
23
|
import type { CrdtValue, EvictionPolicy, MutationEvent, StorageMetrics, StorageType, Unsubscribe, WriteConfirmation, ReadResult } from '../types.js';
|
|
21
24
|
/** Server-side eviction options (Tier 1 only — memory to disk). */
|
|
22
25
|
export interface ServerEvictionOptions extends EvictionPolicy {
|
|
@@ -76,10 +79,8 @@ export declare class SietchServer {
|
|
|
76
79
|
private readonly obs;
|
|
77
80
|
private readonly storage;
|
|
78
81
|
private queryBridge?;
|
|
79
|
-
private
|
|
82
|
+
private _aclAuthority?;
|
|
80
83
|
private evictionMgr?;
|
|
81
|
-
/** Subtrees already registered with the query bridge. */
|
|
82
|
-
private readonly bridgedSubtrees;
|
|
83
84
|
/** Private — use createServer(). */
|
|
84
85
|
private constructor();
|
|
85
86
|
/** Factory — initializes all subsystems in correct order. */
|
|
@@ -126,10 +127,76 @@ export declare class SietchServer {
|
|
|
126
127
|
cleared: boolean;
|
|
127
128
|
priorDisconnects: number;
|
|
128
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* AMD-009: read-only access to the underlying `ServerAclAuthority`.
|
|
132
|
+
*
|
|
133
|
+
* `undefined` if `aclSigningBackend` was not passed to `createServer`.
|
|
134
|
+
* Use this when you need direct access to the authority primitives
|
|
135
|
+
* (e.g. low-level `processChange` or CEK handling for encrypted
|
|
136
|
+
* subtrees). For most flows the high-level `setAcl` / `grant` /
|
|
137
|
+
* `revoke` / `createOwnedSubtree` methods below are friendlier.
|
|
138
|
+
*
|
|
139
|
+
* @req FR-28
|
|
140
|
+
* @req FR-36
|
|
141
|
+
*/
|
|
142
|
+
get aclAuthority(): ServerAclAuthority | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* AMD-009: persist an ACL reference node into `_keys.{subtreeId}` and
|
|
145
|
+
* apply it to the local `AclManager`. Mirrors `Store.setAcl` for the
|
|
146
|
+
* server role. Connected clients receive the update via the existing
|
|
147
|
+
* `initAclSync` listener on their side.
|
|
148
|
+
*
|
|
149
|
+
* Typically called internally by `grant` / `revoke` /
|
|
150
|
+
* `createOwnedSubtree`. Exposed for advanced integrations that compute
|
|
151
|
+
* a ref node out-of-band (e.g. signed by an external HSM).
|
|
152
|
+
*
|
|
153
|
+
* @req FR-28
|
|
154
|
+
* @req FR-36
|
|
155
|
+
*/
|
|
156
|
+
setAcl(subtreeId: string, refNode: AclReferenceNode): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* AMD-009: create a server-owned subtree with an initial ACL granting
|
|
159
|
+
* only the server admin perms. Persists the ref node into `_keys` and
|
|
160
|
+
* propagates to connected peers.
|
|
161
|
+
*
|
|
162
|
+
* Throws if `aclSigningBackend` was not configured at `createServer`
|
|
163
|
+
* time — no authority to sign with.
|
|
164
|
+
*
|
|
165
|
+
* @req FR-36
|
|
166
|
+
* @req FR-72
|
|
167
|
+
*/
|
|
168
|
+
createOwnedSubtree(subtreeId: string, opts?: {
|
|
169
|
+
encrypted?: boolean;
|
|
170
|
+
userPublicKeys?: Map<string, HybridPublicKey>;
|
|
171
|
+
}): Promise<AclReferenceNode>;
|
|
172
|
+
/**
|
|
173
|
+
* AMD-009: grant permissions on a subtree to a target identity peerId.
|
|
174
|
+
*
|
|
175
|
+
* **`identityPeerId` must be the sietch identity peerId**
|
|
176
|
+
* (`ctx.aclTarget` / `ctx.sietchIdentityPeerId` from `HandshakeHook`),
|
|
177
|
+
* NOT the libp2p `ctx.peerId`. AMD-006 added a runtime WARN for the
|
|
178
|
+
* libp2p-shaped mismatch.
|
|
179
|
+
*
|
|
180
|
+
* If the subtree doesn't exist yet, it is created server-owned and
|
|
181
|
+
* unencrypted before the grant is applied. Subsequent calls add to
|
|
182
|
+
* the existing ACL.
|
|
183
|
+
*
|
|
184
|
+
* @req FR-28
|
|
185
|
+
* @req FR-36
|
|
186
|
+
* @req FR-67
|
|
187
|
+
*/
|
|
188
|
+
grant(subtreeId: string, identityPeerId: string, permissions: AclPermissions): Promise<AclReferenceNode>;
|
|
189
|
+
/**
|
|
190
|
+
* AMD-009: revoke a target identity peerId's permissions on a subtree.
|
|
191
|
+
*
|
|
192
|
+
* Throws if the subtree doesn't exist or the authority isn't configured.
|
|
193
|
+
*
|
|
194
|
+
* @req FR-28
|
|
195
|
+
* @req FR-36
|
|
196
|
+
*/
|
|
197
|
+
revoke(subtreeId: string, identityPeerId: string): Promise<AclReferenceNode>;
|
|
129
198
|
/** Get eviction metrics (requires eviction option). */
|
|
130
199
|
getEvictionMetrics(): Promise<StorageMetrics | null>;
|
|
131
|
-
/** Ensure the query bridge is observing a subtree. */
|
|
132
|
-
private ensureBridged;
|
|
133
200
|
/** Gracefully shut down all subsystems. */
|
|
134
201
|
close(): Promise<void>;
|
|
135
202
|
}
|