@codemem/core 0.29.3 → 0.30.0-alpha.2
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/api-types.d.ts +27 -1
- package/dist/api-types.d.ts.map +1 -1
- package/dist/better-sqlite-coordinator-store.d.ts +10 -1
- package/dist/better-sqlite-coordinator-store.d.ts.map +1 -1
- package/dist/coordinator-actions.d.ts +58 -1
- package/dist/coordinator-actions.d.ts.map +1 -1
- package/dist/{coordinator-api-Dbgsu1O8.js → coordinator-api-D6UhwKON.js} +393 -123
- package/dist/coordinator-api-D6UhwKON.js.map +1 -0
- package/dist/coordinator-api.d.ts.map +1 -1
- package/dist/coordinator-store-contract.d.ts +114 -0
- package/dist/coordinator-store-contract.d.ts.map +1 -1
- package/dist/coordinator-store-test-harness.d.ts.map +1 -1
- package/dist/coordinator-store.d.ts +1 -1
- package/dist/coordinator-store.d.ts.map +1 -1
- package/dist/d1-coordinator-store.d.ts +10 -1
- package/dist/d1-coordinator-store.d.ts.map +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/export-import.d.ts.map +1 -1
- package/dist/index.d.ts +17 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6199 -4306
- package/dist/index.js.map +1 -1
- package/dist/internal/cloudflare-coordinator.js +240 -47
- package/dist/internal/cloudflare-coordinator.js.map +1 -1
- package/dist/schema-bootstrap.d.ts.map +1 -1
- package/dist/schema.d.ts +5166 -2662
- package/dist/schema.d.ts.map +1 -1
- package/dist/scope-backfill.d.ts +78 -0
- package/dist/scope-backfill.d.ts.map +1 -0
- package/dist/scope-membership-cache.d.ts +78 -0
- package/dist/scope-membership-cache.d.ts.map +1 -0
- package/dist/scope-membership-semantics.d.ts +25 -0
- package/dist/scope-membership-semantics.d.ts.map +1 -0
- package/dist/scope-resolution.d.ts +40 -0
- package/dist/scope-resolution.d.ts.map +1 -0
- package/dist/scope-stamping.d.ts +10 -0
- package/dist/scope-stamping.d.ts.map +1 -0
- package/dist/search.d.ts +2 -1
- package/dist/search.d.ts.map +1 -1
- package/dist/store.d.ts +19 -15
- package/dist/store.d.ts.map +1 -1
- package/dist/sync-bootstrap.d.ts +6 -4
- package/dist/sync-bootstrap.d.ts.map +1 -1
- package/dist/sync-capability.d.ts +14 -0
- package/dist/sync-capability.d.ts.map +1 -0
- package/dist/sync-daemon.d.ts +12 -1
- package/dist/sync-daemon.d.ts.map +1 -1
- package/dist/sync-pass.d.ts.map +1 -1
- package/dist/sync-replication.d.ts +94 -11
- package/dist/sync-replication.d.ts.map +1 -1
- package/dist/sync-retention-runner.d.ts +1 -0
- package/dist/sync-retention-runner.d.ts.map +1 -1
- package/dist/sync-scope-protocol.d.ts +32 -0
- package/dist/sync-scope-protocol.d.ts.map +1 -0
- package/dist/test-schema.generated.d.ts +1 -1
- package/dist/test-schema.generated.d.ts.map +1 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vectors.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/coordinator-api-Dbgsu1O8.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as e, t } from "../coordinator-api-
|
|
1
|
+
import { r as e, t } from "../coordinator-api-D6UhwKON.js";
|
|
2
2
|
//#region src/d1-coordinator-store.ts
|
|
3
3
|
function n(e) {
|
|
4
4
|
if (e == null) throw Error("expected row");
|
|
@@ -65,6 +65,94 @@ function u(e) {
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
function d(e) {
|
|
68
|
+
return e?.trim() || null;
|
|
69
|
+
}
|
|
70
|
+
function f(e, t = 0) {
|
|
71
|
+
if (e == null) return t;
|
|
72
|
+
if (!Number.isFinite(e) || e < 0) throw Error("membershipEpoch must be non-negative.");
|
|
73
|
+
return Math.trunc(e);
|
|
74
|
+
}
|
|
75
|
+
function p(e) {
|
|
76
|
+
let t = d(e.scopeId), n = d(e.label);
|
|
77
|
+
if (!t || !n) throw Error("scopeId and label are required.");
|
|
78
|
+
return {
|
|
79
|
+
scopeId: t,
|
|
80
|
+
label: n,
|
|
81
|
+
kind: d(e.kind) ?? "user",
|
|
82
|
+
authorityType: d(e.authorityType) ?? "coordinator",
|
|
83
|
+
coordinatorId: d(e.coordinatorId),
|
|
84
|
+
groupId: d(e.groupId),
|
|
85
|
+
manifestIssuerDeviceId: d(e.manifestIssuerDeviceId),
|
|
86
|
+
membershipEpoch: f(e.membershipEpoch),
|
|
87
|
+
manifestHash: d(e.manifestHash),
|
|
88
|
+
status: d(e.status) ?? "active"
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function m(e, t, n) {
|
|
92
|
+
if (e === void 0) return t;
|
|
93
|
+
let r = d(e);
|
|
94
|
+
if (!r) throw Error(`${n} must not be empty.`);
|
|
95
|
+
return r;
|
|
96
|
+
}
|
|
97
|
+
function h(e, t) {
|
|
98
|
+
return e === void 0 ? t : d(e);
|
|
99
|
+
}
|
|
100
|
+
function g(e, t) {
|
|
101
|
+
let n = d(e.scopeId);
|
|
102
|
+
if (!n) throw Error("scopeId is required.");
|
|
103
|
+
let r = e.membershipEpoch == null ? null : f(e.membershipEpoch);
|
|
104
|
+
if (r != null && r < t.membership_epoch) throw Error("membershipEpoch must not move backwards.");
|
|
105
|
+
return {
|
|
106
|
+
scopeId: n,
|
|
107
|
+
label: m(e.label, t.label, "label"),
|
|
108
|
+
kind: m(e.kind, t.kind, "kind"),
|
|
109
|
+
authorityType: m(e.authorityType, t.authority_type, "authorityType"),
|
|
110
|
+
coordinatorId: h(e.coordinatorId, t.coordinator_id),
|
|
111
|
+
groupId: h(e.groupId, t.group_id),
|
|
112
|
+
manifestIssuerDeviceId: h(e.manifestIssuerDeviceId, t.manifest_issuer_device_id),
|
|
113
|
+
membershipEpoch: r ?? t.membership_epoch,
|
|
114
|
+
manifestHash: h(e.manifestHash, t.manifest_hash),
|
|
115
|
+
status: m(e.status, t.status, "status")
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function _(e, t, n) {
|
|
119
|
+
let r = d(e.scopeId), i = d(e.deviceId);
|
|
120
|
+
if (!r || !i) throw Error("scopeId and deviceId are required.");
|
|
121
|
+
let a = d(e.coordinatorId), o = d(e.groupId);
|
|
122
|
+
if (a && a !== t?.coordinator_id) throw Error("membership coordinatorId must match the scope coordinatorId.");
|
|
123
|
+
if (o && o !== t?.group_id) throw Error("membership groupId must match the scope groupId.");
|
|
124
|
+
let s = e.membershipEpoch == null ? null : f(e.membershipEpoch), c = t?.membership_epoch ?? 0;
|
|
125
|
+
if (s != null && s < c) throw Error("membershipEpoch must not be lower than the scope membershipEpoch.");
|
|
126
|
+
if (s != null && n && s < (n.status === "revoked" ? n.membership_epoch + 1 : n.membership_epoch)) throw Error("membershipEpoch must not move backwards.");
|
|
127
|
+
let l = s ?? (n ? Math.max(c, n.membership_epoch + +(n.status === "revoked")) : c);
|
|
128
|
+
return {
|
|
129
|
+
scopeId: r,
|
|
130
|
+
deviceId: i,
|
|
131
|
+
role: d(e.role) ?? "member",
|
|
132
|
+
membershipEpoch: l,
|
|
133
|
+
coordinatorId: t?.coordinator_id ?? null,
|
|
134
|
+
groupId: t?.group_id ?? null,
|
|
135
|
+
manifestIssuerDeviceId: d(e.manifestIssuerDeviceId) ?? t?.manifest_issuer_device_id ?? null,
|
|
136
|
+
manifestHash: d(e.manifestHash) ?? t?.manifest_hash ?? null,
|
|
137
|
+
signedManifestJson: d(e.signedManifestJson),
|
|
138
|
+
actorType: d(e.actorType),
|
|
139
|
+
actorId: d(e.actorId)
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function v(e) {
|
|
143
|
+
return e == null || !Number.isFinite(e) ? 100 : Math.max(1, Math.min(1e3, Math.trunc(e)));
|
|
144
|
+
}
|
|
145
|
+
function y(e, t) {
|
|
146
|
+
return e.prepare("INSERT INTO coordinator_scope_membership_audit_log(\n action, scope_id, device_id, role, status, membership_epoch,\n previous_role, previous_status, previous_membership_epoch,\n coordinator_id, group_id, actor_type, actor_id, manifest_hash, created_at\n )\n SELECT ?, membership.scope_id, membership.device_id, membership.role, membership.status,\n membership.membership_epoch, ?, ?, ?, membership.coordinator_id, membership.group_id,\n ?, ?, membership.manifest_hash, ?\n FROM (SELECT 1 WHERE changes() > 0) AS required\n LEFT JOIN coordinator_scope_memberships AS membership\n ON membership.scope_id = ?\n AND membership.device_id = ?\n AND membership.status = ?\n AND membership.membership_epoch = ?\n AND membership.updated_at = ?").bind(t.action, t.previous?.role ?? null, t.previous?.status ?? null, t.previous?.membership_epoch ?? null, t.actorType, t.actorId, t.createdAt, t.scopeId, t.deviceId, t.status, t.membershipEpoch, t.updatedAt);
|
|
147
|
+
}
|
|
148
|
+
async function b(e, t) {
|
|
149
|
+
if (!e.batch) throw Error("D1 batch support is required for audited scope membership changes.");
|
|
150
|
+
return await e.batch(t);
|
|
151
|
+
}
|
|
152
|
+
function x(e) {
|
|
153
|
+
return Number(e?.meta?.changes ?? 0);
|
|
154
|
+
}
|
|
155
|
+
function S(e) {
|
|
68
156
|
if (!e) return null;
|
|
69
157
|
let t = String(e.seedDeviceId ?? "").trim(), n = String(e.expiresAt ?? "").trim(), r = String(e.createdBy ?? "").trim() || null;
|
|
70
158
|
if (!t || !n) throw Error("bootstrapGrant.seedDeviceId and expiresAt are required.");
|
|
@@ -76,18 +164,18 @@ function d(e) {
|
|
|
76
164
|
createdBy: r
|
|
77
165
|
};
|
|
78
166
|
}
|
|
79
|
-
async function
|
|
167
|
+
async function C(e) {
|
|
80
168
|
let t = await e.all();
|
|
81
169
|
return Array.isArray(t?.results) ? t.results : [];
|
|
82
170
|
}
|
|
83
|
-
async function
|
|
171
|
+
async function w(e) {
|
|
84
172
|
return await e.first();
|
|
85
173
|
}
|
|
86
|
-
async function
|
|
174
|
+
async function T(e) {
|
|
87
175
|
let t = await e.run();
|
|
88
176
|
return Number(t?.meta?.changes ?? 0);
|
|
89
177
|
}
|
|
90
|
-
var
|
|
178
|
+
var E = class {
|
|
91
179
|
db;
|
|
92
180
|
constructor(e) {
|
|
93
181
|
this.db = e;
|
|
@@ -97,80 +185,80 @@ var h = class {
|
|
|
97
185
|
await this.db.prepare("INSERT OR IGNORE INTO groups(group_id, display_name, archived_at, created_at) VALUES (?, ?, NULL, ?)").bind(e, t ?? null, o()).run();
|
|
98
186
|
}
|
|
99
187
|
async getGroup(e) {
|
|
100
|
-
let t = await
|
|
188
|
+
let t = await w(this.db.prepare("SELECT group_id, display_name, archived_at, created_at FROM groups WHERE group_id = ?").bind(e));
|
|
101
189
|
return t ? n(t) : null;
|
|
102
190
|
}
|
|
103
191
|
async listGroups(e = !1) {
|
|
104
192
|
let t = e ? "" : "WHERE archived_at IS NULL";
|
|
105
|
-
return (await
|
|
193
|
+
return (await C(this.db.prepare(`SELECT group_id, display_name, archived_at, created_at FROM groups ${t} ORDER BY created_at ASC`))).map((e) => n(e));
|
|
106
194
|
}
|
|
107
195
|
async renameGroup(e, t) {
|
|
108
|
-
return await
|
|
196
|
+
return await T(this.db.prepare("UPDATE groups SET display_name = ? WHERE group_id = ?").bind(t, e)) > 0;
|
|
109
197
|
}
|
|
110
198
|
async archiveGroup(e, t = o()) {
|
|
111
|
-
return await
|
|
199
|
+
return await T(this.db.prepare("UPDATE groups SET archived_at = ? WHERE group_id = ? AND archived_at IS NULL").bind(t, e)) > 0;
|
|
112
200
|
}
|
|
113
201
|
async unarchiveGroup(e) {
|
|
114
|
-
return await
|
|
202
|
+
return await T(this.db.prepare("UPDATE groups SET archived_at = NULL WHERE group_id = ? AND archived_at IS NOT NULL").bind(e)) > 0;
|
|
115
203
|
}
|
|
116
204
|
async enrollDevice(e, t) {
|
|
117
205
|
await this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, display_name, enabled, created_at\n ) VALUES (?, ?, ?, ?, ?, 1, ?)\n ON CONFLICT(group_id, device_id) DO UPDATE SET\n public_key = excluded.public_key,\n fingerprint = excluded.fingerprint,\n display_name = excluded.display_name,\n enabled = 1").bind(e, t.deviceId, t.publicKey, t.fingerprint, t.displayName ?? null, o()).run();
|
|
118
206
|
}
|
|
119
207
|
async listEnrolledDevices(e, t) {
|
|
120
208
|
let r = t ? "" : "AND enabled = 1";
|
|
121
|
-
return (await
|
|
209
|
+
return (await C(this.db.prepare(`SELECT group_id, device_id, public_key, fingerprint, display_name, enabled, created_at
|
|
122
210
|
FROM enrolled_devices
|
|
123
211
|
WHERE group_id = ? ${r}
|
|
124
212
|
ORDER BY created_at ASC, device_id ASC`).bind(e))).map((e) => n(e));
|
|
125
213
|
}
|
|
126
214
|
async getEnrollment(e, t) {
|
|
127
|
-
let r = await
|
|
215
|
+
let r = await w(this.db.prepare("SELECT group_id, device_id, public_key, fingerprint, display_name, enabled, created_at\n FROM enrolled_devices\n WHERE group_id = ? AND device_id = ? AND enabled = 1").bind(e, t));
|
|
128
216
|
return r ? n(r) : null;
|
|
129
217
|
}
|
|
130
218
|
async renameDevice(e, t, n) {
|
|
131
|
-
return await
|
|
219
|
+
return await T(this.db.prepare("UPDATE enrolled_devices SET display_name = ?\n WHERE group_id = ? AND device_id = ?").bind(n, e, t)) > 0;
|
|
132
220
|
}
|
|
133
221
|
async setDeviceEnabled(e, t, n) {
|
|
134
|
-
return await
|
|
222
|
+
return await T(this.db.prepare("UPDATE enrolled_devices SET enabled = ?\n WHERE group_id = ? AND device_id = ?").bind(+!!n, e, t)) > 0;
|
|
135
223
|
}
|
|
136
224
|
async removeDevice(e, t) {
|
|
137
|
-
return await this.db.prepare("DELETE FROM presence_records WHERE group_id = ? AND device_id = ?").bind(e, t).run(), await this.db.prepare("DELETE FROM coordinator_reciprocal_approvals WHERE group_id = ? AND (requesting_device_id = ? OR requested_device_id = ?)").bind(e, t, t).run(), await
|
|
225
|
+
return await this.db.prepare("DELETE FROM presence_records WHERE group_id = ? AND device_id = ?").bind(e, t).run(), await this.db.prepare("DELETE FROM coordinator_reciprocal_approvals WHERE group_id = ? AND (requesting_device_id = ? OR requested_device_id = ?)").bind(e, t, t).run(), await T(this.db.prepare("DELETE FROM enrolled_devices WHERE group_id = ? AND device_id = ?").bind(e, t)) > 0;
|
|
138
226
|
}
|
|
139
227
|
async recordNonce(e, t, n) {
|
|
140
|
-
return await
|
|
228
|
+
return await T(this.db.prepare("INSERT OR IGNORE INTO request_nonces(device_id, nonce, created_at) VALUES (?, ?, ?)").bind(e, t, n)) > 0;
|
|
141
229
|
}
|
|
142
230
|
async cleanupNonces(e) {
|
|
143
231
|
await this.db.prepare("DELETE FROM request_nonces WHERE created_at < ?").bind(e).run();
|
|
144
232
|
}
|
|
145
233
|
async createInvite(e) {
|
|
146
234
|
let t = o(), r = l(12), i = l(24), a = await this.getGroup(e.groupId);
|
|
147
|
-
return await this.db.prepare("INSERT INTO coordinator_invites(\n invite_id, group_id, token, policy, expires_at, created_at, created_by, team_name_snapshot, revoked_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)").bind(r, e.groupId, i, e.policy, e.expiresAt, t, e.createdBy ?? null, a?.display_name ?? null).run(), n(await
|
|
235
|
+
return await this.db.prepare("INSERT INTO coordinator_invites(\n invite_id, group_id, token, policy, expires_at, created_at, created_by, team_name_snapshot, revoked_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)").bind(r, e.groupId, i, e.policy, e.expiresAt, t, e.createdBy ?? null, a?.display_name ?? null).run(), n(await w(this.db.prepare("SELECT invite_id, group_id, token, policy, expires_at, created_at, created_by, team_name_snapshot, revoked_at\n FROM coordinator_invites WHERE invite_id = ?").bind(r)));
|
|
148
236
|
}
|
|
149
237
|
async getInviteByToken(e) {
|
|
150
|
-
let t = await
|
|
238
|
+
let t = await w(this.db.prepare("SELECT invite_id, group_id, token, policy, expires_at, created_at, created_by, team_name_snapshot, revoked_at\n FROM coordinator_invites\n WHERE token = ?\n AND revoked_at IS NULL\n AND expires_at > ?").bind(e, o()));
|
|
151
239
|
return t ? n(t) : null;
|
|
152
240
|
}
|
|
153
241
|
async listInvites(e) {
|
|
154
|
-
return (await
|
|
242
|
+
return (await C(this.db.prepare("SELECT invite_id, group_id, token, policy, expires_at, created_at, created_by, team_name_snapshot, revoked_at\n FROM coordinator_invites WHERE group_id = ?\n ORDER BY created_at DESC").bind(e))).map((e) => n(e));
|
|
155
243
|
}
|
|
156
244
|
async createJoinRequest(e) {
|
|
157
245
|
let t = o(), r = l(12);
|
|
158
|
-
return await this.db.prepare("INSERT INTO coordinator_join_requests(\n request_id, group_id, device_id, public_key, fingerprint, display_name, token, status, created_at, reviewed_at, reviewed_by\n ) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?, NULL, NULL)").bind(r, e.groupId, e.deviceId, e.publicKey, e.fingerprint, e.displayName ?? null, e.token, t).run(), n(await
|
|
246
|
+
return await this.db.prepare("INSERT INTO coordinator_join_requests(\n request_id, group_id, device_id, public_key, fingerprint, display_name, token, status, created_at, reviewed_at, reviewed_by\n ) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?, NULL, NULL)").bind(r, e.groupId, e.deviceId, e.publicKey, e.fingerprint, e.displayName ?? null, e.token, t).run(), n(await w(this.db.prepare("SELECT request_id, group_id, device_id, public_key, fingerprint, display_name, token, status, created_at, reviewed_at, reviewed_by\n FROM coordinator_join_requests WHERE request_id = ?").bind(r)));
|
|
159
247
|
}
|
|
160
248
|
async listJoinRequests(e, t) {
|
|
161
249
|
let r = t ?? "pending";
|
|
162
|
-
return (await
|
|
250
|
+
return (await C(this.db.prepare("SELECT request_id, group_id, device_id, public_key, fingerprint, display_name, token, status, created_at, reviewed_at, reviewed_by\n FROM coordinator_join_requests\n WHERE group_id = ? AND status = ?\n ORDER BY created_at ASC, device_id ASC").bind(e, r))).map((e) => n(e));
|
|
163
251
|
}
|
|
164
252
|
async reviewJoinRequest(e) {
|
|
165
|
-
let t = await
|
|
253
|
+
let t = await w(this.db.prepare("SELECT request_id, group_id, device_id, public_key, fingerprint, display_name, token, status,\n created_at, reviewed_at, reviewed_by\n FROM coordinator_join_requests WHERE request_id = ?").bind(e.requestId));
|
|
166
254
|
if (!t) return null;
|
|
167
255
|
if (t.status !== "pending") return {
|
|
168
256
|
...n(t),
|
|
169
257
|
_no_transition: !0
|
|
170
258
|
};
|
|
171
|
-
let r =
|
|
259
|
+
let r = S(e.bootstrapGrant), i = o(), a = e.approved ? "approved" : "denied", s = null, c = null;
|
|
172
260
|
if (e.approved && r) {
|
|
173
|
-
if (!await
|
|
261
|
+
if (!await w(this.db.prepare("SELECT device_id FROM enrolled_devices WHERE group_id = ? AND device_id = ? AND enabled = 1").bind(t.group_id, r.seedDeviceId))) throw Error("bootstrap grant seed device is not enrolled in the group.");
|
|
174
262
|
if (r.seedDeviceId === t.device_id) throw Error("bootstrap grant seed and worker device ids must differ.");
|
|
175
263
|
s = {
|
|
176
264
|
...r,
|
|
@@ -197,67 +285,172 @@ var h = class {
|
|
|
197
285
|
let e = await this.createBootstrapGrant(s);
|
|
198
286
|
r = e.grant_id, c = e.grant_id;
|
|
199
287
|
}
|
|
200
|
-
if (await
|
|
288
|
+
if (await T(this.db.prepare("UPDATE coordinator_join_requests\n SET status = ?, reviewed_at = ?, reviewed_by = ?\n WHERE request_id = ? AND status = 'pending'").bind(a, i, e.reviewedBy ?? null, e.requestId)) === 0) {
|
|
201
289
|
r && await this.revokeBootstrapGrant(r);
|
|
202
|
-
let t = await
|
|
290
|
+
let t = await w(this.db.prepare("SELECT request_id, group_id, device_id, public_key, fingerprint, display_name, token, status, created_at, reviewed_at, reviewed_by\n FROM coordinator_join_requests WHERE request_id = ?").bind(e.requestId));
|
|
203
291
|
return t ? {
|
|
204
292
|
...n(t),
|
|
205
293
|
_no_transition: !0
|
|
206
294
|
} : null;
|
|
207
295
|
}
|
|
208
296
|
}
|
|
209
|
-
let u = await
|
|
297
|
+
let u = await w(this.db.prepare("SELECT request_id, group_id, device_id, public_key, fingerprint, display_name, token, status, created_at, reviewed_at, reviewed_by\n FROM coordinator_join_requests WHERE request_id = ?").bind(e.requestId));
|
|
210
298
|
if (!u) return null;
|
|
211
|
-
let
|
|
299
|
+
let d = s ? c ? await this.getBootstrapGrant(c) : await this.createBootstrapGrant(s) : null;
|
|
212
300
|
return {
|
|
213
301
|
...n(u),
|
|
214
|
-
bootstrap_grant:
|
|
302
|
+
bootstrap_grant: d
|
|
215
303
|
};
|
|
216
304
|
}
|
|
217
305
|
async createReciprocalApproval(e) {
|
|
218
306
|
let t = e.groupId.trim(), r = e.requestingDeviceId.trim(), i = e.requestedDeviceId.trim();
|
|
219
307
|
if (!t || !r || !i) throw Error("groupId, requestingDeviceId, and requestedDeviceId are required.");
|
|
220
308
|
if (r === i) throw Error("requesting and requested device ids must differ.");
|
|
221
|
-
let a = s(r, i), u = await
|
|
309
|
+
let a = s(r, i), u = await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals\n WHERE group_id = ? AND requesting_device_id = ? AND requested_device_id = ? AND status = 'pending'\n ORDER BY created_at DESC LIMIT 1").bind(t, r, i));
|
|
222
310
|
if (u) return n(u);
|
|
223
|
-
let d = await
|
|
311
|
+
let d = await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals\n WHERE group_id = ? AND requesting_device_id = ? AND requested_device_id = ? AND status = 'pending'\n ORDER BY created_at DESC LIMIT 1").bind(t, i, r));
|
|
224
312
|
if (d) {
|
|
225
313
|
let e = o();
|
|
226
|
-
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, d.request_id).run(), n(await
|
|
314
|
+
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, d.request_id).run(), n(await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals WHERE request_id = ?").bind(d.request_id)));
|
|
227
315
|
}
|
|
228
|
-
let f = l(12),
|
|
316
|
+
let f = l(12), p = o();
|
|
229
317
|
try {
|
|
230
|
-
await this.db.prepare("INSERT INTO coordinator_reciprocal_approvals(\n request_id,\n group_id,\n requesting_device_id,\n requested_device_id,\n pending_pair_low_device_id,\n pending_pair_high_device_id,\n status,\n created_at,\n resolved_at\n ) VALUES (?, ?, ?, ?, ?, ?, 'pending', ?, NULL)").bind(f, t, r, i, a.low, a.high,
|
|
318
|
+
await this.db.prepare("INSERT INTO coordinator_reciprocal_approvals(\n request_id,\n group_id,\n requesting_device_id,\n requested_device_id,\n pending_pair_low_device_id,\n pending_pair_high_device_id,\n status,\n created_at,\n resolved_at\n ) VALUES (?, ?, ?, ?, ?, ?, 'pending', ?, NULL)").bind(f, t, r, i, a.low, a.high, p).run();
|
|
231
319
|
} catch (e) {
|
|
232
320
|
if (!c(e)) throw e;
|
|
233
|
-
let a = await
|
|
321
|
+
let a = await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals\n WHERE group_id = ? AND requesting_device_id = ? AND requested_device_id = ? AND status = 'pending'\n ORDER BY created_at DESC LIMIT 1").bind(t, r, i));
|
|
234
322
|
if (a) return n(a);
|
|
235
|
-
let s = await
|
|
323
|
+
let s = await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals\n WHERE group_id = ? AND requesting_device_id = ? AND requested_device_id = ? AND status = 'pending'\n ORDER BY created_at DESC LIMIT 1").bind(t, i, r));
|
|
236
324
|
if (s) {
|
|
237
325
|
let e = o();
|
|
238
|
-
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, s.request_id).run(), n(await
|
|
326
|
+
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, s.request_id).run(), n(await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals WHERE request_id = ?").bind(s.request_id)));
|
|
239
327
|
}
|
|
240
328
|
throw e;
|
|
241
329
|
}
|
|
242
|
-
return n(await
|
|
330
|
+
return n(await w(this.db.prepare("SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at\n FROM coordinator_reciprocal_approvals WHERE request_id = ?").bind(f)));
|
|
243
331
|
}
|
|
244
332
|
async createBootstrapGrant(e) {
|
|
245
333
|
let t = u(e), r = l(12), i = o();
|
|
246
|
-
return await this.db.prepare("INSERT INTO coordinator_bootstrap_grants(\n grant_id, group_id, seed_device_id, worker_device_id, expires_at, created_at, created_by, revoked_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, NULL)").bind(r, t.groupId, t.seedDeviceId, t.workerDeviceId, t.expiresAt, i, t.createdBy).run(), n(await
|
|
334
|
+
return await this.db.prepare("INSERT INTO coordinator_bootstrap_grants(\n grant_id, group_id, seed_device_id, worker_device_id, expires_at, created_at, created_by, revoked_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, NULL)").bind(r, t.groupId, t.seedDeviceId, t.workerDeviceId, t.expiresAt, i, t.createdBy).run(), n(await w(this.db.prepare("SELECT grant_id, group_id, seed_device_id, worker_device_id, expires_at, created_at, created_by, revoked_at\n FROM coordinator_bootstrap_grants WHERE grant_id = ?").bind(r)));
|
|
335
|
+
}
|
|
336
|
+
async getScope(e) {
|
|
337
|
+
let t = await w(this.db.prepare("SELECT scope_id, label, kind, authority_type, coordinator_id, group_id,\n manifest_issuer_device_id, membership_epoch, manifest_hash, status, created_at, updated_at\n FROM coordinator_scopes WHERE scope_id = ?").bind(e));
|
|
338
|
+
return t ? n(t) : null;
|
|
339
|
+
}
|
|
340
|
+
async getScopeMembership(e, t) {
|
|
341
|
+
let r = await w(this.db.prepare("SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,\n manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at\n FROM coordinator_scope_memberships\n WHERE scope_id = ? AND device_id = ?").bind(e, t));
|
|
342
|
+
return r ? n(r) : null;
|
|
343
|
+
}
|
|
344
|
+
async createScope(e) {
|
|
345
|
+
let t = p(e);
|
|
346
|
+
if (await this.getScope(t.scopeId)) throw Error("scopeId already exists.");
|
|
347
|
+
let n = o();
|
|
348
|
+
await this.db.prepare("INSERT INTO coordinator_scopes(\n scope_id, label, kind, authority_type, coordinator_id, group_id,\n manifest_issuer_device_id, membership_epoch, manifest_hash, status, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").bind(t.scopeId, t.label, t.kind, t.authorityType, t.coordinatorId, t.groupId, t.manifestIssuerDeviceId, t.membershipEpoch, t.manifestHash, t.status, n, n).run();
|
|
349
|
+
let r = await this.getScope(t.scopeId);
|
|
350
|
+
if (!r) throw Error("scope insert returned no row");
|
|
351
|
+
return r;
|
|
352
|
+
}
|
|
353
|
+
async updateScope(e) {
|
|
354
|
+
let t = d(e.scopeId), n = t ? await this.getScope(t) : null;
|
|
355
|
+
if (!n) return null;
|
|
356
|
+
let r = g(e, n);
|
|
357
|
+
return await this.db.prepare("UPDATE coordinator_scopes\n SET label = ?,\n kind = ?,\n authority_type = ?,\n coordinator_id = ?,\n group_id = ?,\n manifest_issuer_device_id = ?,\n membership_epoch = ?,\n manifest_hash = ?,\n status = ?,\n updated_at = ?\n WHERE scope_id = ?").bind(r.label, r.kind, r.authorityType, r.coordinatorId, r.groupId, r.manifestIssuerDeviceId, r.membershipEpoch, r.manifestHash, r.status, o(), r.scopeId).run(), await this.getScope(r.scopeId);
|
|
358
|
+
}
|
|
359
|
+
async listScopes(e = {}) {
|
|
360
|
+
let t = [], r = [], i = d(e.coordinatorId), a = d(e.groupId), o = d(e.status);
|
|
361
|
+
i && (t.push("coordinator_id = ?"), r.push(i)), a && (t.push("group_id = ?"), r.push(a)), o ? (t.push("status = ?"), r.push(o)) : e.includeInactive || t.push("status = 'active'");
|
|
362
|
+
let s = t.length ? `WHERE ${t.join(" AND ")}` : "", c = this.db.prepare(`SELECT scope_id, label, kind, authority_type, coordinator_id, group_id,
|
|
363
|
+
manifest_issuer_device_id, membership_epoch, manifest_hash, status, created_at, updated_at
|
|
364
|
+
FROM coordinator_scopes ${s}
|
|
365
|
+
ORDER BY coordinator_id ASC, group_id ASC, scope_id ASC`);
|
|
366
|
+
return (await C(r.length ? c.bind(...r) : c)).map((e) => n(e));
|
|
367
|
+
}
|
|
368
|
+
async grantScopeMembership(e) {
|
|
369
|
+
let t = d(e.scopeId), r = d(e.deviceId), i = t ? await this.getScope(t) : null;
|
|
370
|
+
if (!i) throw Error("scopeId must reference an existing scope.");
|
|
371
|
+
let a = t && r ? await this.getScopeMembership(t, r) : null, s = _(e, i, a);
|
|
372
|
+
if (s.groupId && !await this.getEnrollment(s.groupId, s.deviceId)) throw Error("device must be enrolled and enabled in the scope group.");
|
|
373
|
+
let c = o();
|
|
374
|
+
if (x((await b(this.db, [this.db.prepare("INSERT INTO coordinator_scope_memberships(\n scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,\n manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at\n ) VALUES (?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(scope_id, device_id) DO UPDATE SET\n role = excluded.role,\n status = 'active',\n membership_epoch = excluded.membership_epoch,\n coordinator_id = excluded.coordinator_id,\n group_id = excluded.group_id,\n manifest_issuer_device_id = excluded.manifest_issuer_device_id,\n manifest_hash = excluded.manifest_hash,\n signed_manifest_json = excluded.signed_manifest_json,\n updated_at = excluded.updated_at\n WHERE excluded.membership_epoch > coordinator_scope_memberships.membership_epoch\n OR (\n excluded.membership_epoch = coordinator_scope_memberships.membership_epoch\n AND coordinator_scope_memberships.status != 'revoked'\n )").bind(s.scopeId, s.deviceId, s.role, s.membershipEpoch, s.coordinatorId, s.groupId, s.manifestIssuerDeviceId, s.manifestHash, s.signedManifestJson, c), y(this.db, {
|
|
375
|
+
action: "grant",
|
|
376
|
+
previous: a,
|
|
377
|
+
scopeId: s.scopeId,
|
|
378
|
+
deviceId: s.deviceId,
|
|
379
|
+
status: "active",
|
|
380
|
+
membershipEpoch: s.membershipEpoch,
|
|
381
|
+
updatedAt: c,
|
|
382
|
+
actorType: s.actorType,
|
|
383
|
+
actorId: s.actorId,
|
|
384
|
+
createdAt: c
|
|
385
|
+
})]))[0]) <= 0) throw Error("scope membership grant was not applied.");
|
|
386
|
+
return n(await w(this.db.prepare("SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,\n manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at\n FROM coordinator_scope_memberships\n WHERE scope_id = ? AND device_id = ?").bind(s.scopeId, s.deviceId)));
|
|
387
|
+
}
|
|
388
|
+
async revokeScopeMembership(e) {
|
|
389
|
+
let t = d(e.scopeId), n = d(e.deviceId);
|
|
390
|
+
if (!t || !n) throw Error("scopeId and deviceId are required.");
|
|
391
|
+
let r = e.membershipEpoch == null ? null : f(e.membershipEpoch), i = await this.getScopeMembership(t, n);
|
|
392
|
+
if (!i) return !1;
|
|
393
|
+
if (r != null && i && r <= i.membership_epoch) throw Error("membershipEpoch must increase on revoke.");
|
|
394
|
+
let a = o(), s = r ?? i.membership_epoch + 1, c = this.db.prepare("UPDATE coordinator_scope_memberships\n SET status = 'revoked',\n membership_epoch = CASE WHEN ? IS NULL THEN membership_epoch + 1 ELSE ? END,\n manifest_hash = COALESCE(?, manifest_hash),\n signed_manifest_json = COALESCE(?, signed_manifest_json),\n updated_at = ?\n WHERE scope_id = ? AND device_id = ? AND membership_epoch = ? AND status = ?").bind(r, r, d(e.manifestHash), d(e.signedManifestJson), a, t, n, i.membership_epoch, i.status), l = y(this.db, {
|
|
395
|
+
action: "revoke",
|
|
396
|
+
previous: i,
|
|
397
|
+
scopeId: t,
|
|
398
|
+
deviceId: n,
|
|
399
|
+
status: "revoked",
|
|
400
|
+
membershipEpoch: s,
|
|
401
|
+
updatedAt: a,
|
|
402
|
+
actorType: d(e.actorType),
|
|
403
|
+
actorId: d(e.actorId),
|
|
404
|
+
createdAt: a
|
|
405
|
+
}), u;
|
|
406
|
+
try {
|
|
407
|
+
u = await b(this.db, [c, l]);
|
|
408
|
+
} catch (e) {
|
|
409
|
+
let r = await this.getScopeMembership(t, n);
|
|
410
|
+
if (!r || r.membership_epoch !== i.membership_epoch || r.status !== i.status) return !1;
|
|
411
|
+
throw e;
|
|
412
|
+
}
|
|
413
|
+
return !(x(u[0]) <= 0);
|
|
414
|
+
}
|
|
415
|
+
async listScopeMemberships(e, t = !1) {
|
|
416
|
+
let r = d(e);
|
|
417
|
+
if (!r) throw Error("scopeId is required.");
|
|
418
|
+
let i = t ? "" : "AND status = 'active'";
|
|
419
|
+
return (await C(this.db.prepare(`SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,
|
|
420
|
+
manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at
|
|
421
|
+
FROM coordinator_scope_memberships
|
|
422
|
+
WHERE scope_id = ? ${i}
|
|
423
|
+
ORDER BY device_id ASC`).bind(r))).map((e) => n(e));
|
|
424
|
+
}
|
|
425
|
+
async listScopeMembershipAuditEvents(e) {
|
|
426
|
+
let t = d(e.scopeId);
|
|
427
|
+
if (!t) throw Error("scopeId is required.");
|
|
428
|
+
let r = d(e.deviceId), i = v(e.limit), a = r ? "scope_id = ? AND device_id = ?" : "scope_id = ?", o = r ? [
|
|
429
|
+
t,
|
|
430
|
+
r,
|
|
431
|
+
i
|
|
432
|
+
] : [t, i];
|
|
433
|
+
return (await C(this.db.prepare(`SELECT event_id, action, scope_id, device_id, role, status, membership_epoch,
|
|
434
|
+
previous_role, previous_status, previous_membership_epoch,
|
|
435
|
+
coordinator_id, group_id, actor_type, actor_id, manifest_hash, created_at
|
|
436
|
+
FROM coordinator_scope_membership_audit_log
|
|
437
|
+
WHERE ${a}
|
|
438
|
+
ORDER BY event_id ASC
|
|
439
|
+
LIMIT ?`).bind(...o))).map((e) => n(e));
|
|
247
440
|
}
|
|
248
441
|
async getBootstrapGrant(e) {
|
|
249
|
-
let t = await
|
|
442
|
+
let t = await w(this.db.prepare("SELECT grant_id, group_id, seed_device_id, worker_device_id, expires_at, created_at, created_by, revoked_at\n FROM coordinator_bootstrap_grants WHERE grant_id = ?").bind(e));
|
|
250
443
|
return t ? n(t) : null;
|
|
251
444
|
}
|
|
252
445
|
async listBootstrapGrants(e) {
|
|
253
|
-
return (await
|
|
446
|
+
return (await C(this.db.prepare("SELECT grant_id, group_id, seed_device_id, worker_device_id, expires_at, created_at, created_by, revoked_at\n FROM coordinator_bootstrap_grants WHERE group_id = ?\n ORDER BY created_at DESC, grant_id DESC").bind(e))).map((e) => n(e));
|
|
254
447
|
}
|
|
255
448
|
async revokeBootstrapGrant(e, t = o()) {
|
|
256
|
-
return await
|
|
449
|
+
return await T(this.db.prepare("UPDATE coordinator_bootstrap_grants\n SET revoked_at = COALESCE(revoked_at, ?)\n WHERE grant_id = ?").bind(t, e)) > 0;
|
|
257
450
|
}
|
|
258
451
|
async listReciprocalApprovals(e) {
|
|
259
452
|
let t = e.direction === "incoming" ? "requested_device_id" : "requesting_device_id", r = e.status?.trim() || "pending";
|
|
260
|
-
return (await
|
|
453
|
+
return (await C(this.db.prepare(`SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at
|
|
261
454
|
FROM coordinator_reciprocal_approvals
|
|
262
455
|
WHERE group_id = ? AND ${t} = ? AND status = ?
|
|
263
456
|
ORDER BY created_at ASC, request_id ASC`).bind(e.groupId, e.deviceId, r))).map((e) => n(e));
|
|
@@ -273,7 +466,7 @@ var h = class {
|
|
|
273
466
|
}
|
|
274
467
|
async listGroupPeers(e, t) {
|
|
275
468
|
let n = o();
|
|
276
|
-
return (await
|
|
469
|
+
return (await C(this.db.prepare("SELECT enrolled_devices.device_id, enrolled_devices.public_key, enrolled_devices.fingerprint, enrolled_devices.display_name,\n presence_records.addresses_json, presence_records.last_seen_at, presence_records.expires_at,\n presence_records.capabilities_json\n FROM enrolled_devices\n LEFT JOIN presence_records\n ON presence_records.group_id = enrolled_devices.group_id\n AND presence_records.device_id = enrolled_devices.device_id\n WHERE enrolled_devices.group_id = ?\n AND enrolled_devices.enabled = 1\n AND enrolled_devices.device_id != ?\n ORDER BY enrolled_devices.device_id ASC").bind(e, t))).map((e) => {
|
|
277
470
|
let t = String(e.expires_at ?? "").trim(), r = !0;
|
|
278
471
|
if (t) {
|
|
279
472
|
let e = new Date(t);
|
|
@@ -296,9 +489,9 @@ var h = class {
|
|
|
296
489
|
};
|
|
297
490
|
//#endregion
|
|
298
491
|
//#region src/d1-coordinator-runtime.ts
|
|
299
|
-
function
|
|
492
|
+
function D(e) {
|
|
300
493
|
return t({
|
|
301
|
-
storeFactory: () => new
|
|
494
|
+
storeFactory: () => new E(e.db),
|
|
302
495
|
runtime: {
|
|
303
496
|
adminSecret: () => String(e.adminSecret ?? "").trim() || null,
|
|
304
497
|
now: e.now ?? (() => (/* @__PURE__ */ new Date()).toISOString())
|
|
@@ -307,6 +500,6 @@ function g(e) {
|
|
|
307
500
|
});
|
|
308
501
|
}
|
|
309
502
|
//#endregion
|
|
310
|
-
export {
|
|
503
|
+
export { E as D1CoordinatorStore, e as DEFAULT_TIME_WINDOW_S, D as createD1CoordinatorApp };
|
|
311
504
|
|
|
312
505
|
//# sourceMappingURL=cloudflare-coordinator.js.map
|