@codemem/core 0.45.0-rc.2 → 0.46.0-alpha.1
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 +12 -0
- package/dist/api-types.d.ts.map +1 -1
- package/dist/better-sqlite-coordinator-store.d.ts.map +1 -1
- package/dist/claude-hooks.d.ts +1 -2
- package/dist/claude-hooks.d.ts.map +1 -1
- package/dist/codex-hooks.d.ts.map +1 -1
- package/dist/coordinator-actions.d.ts.map +1 -1
- package/dist/{coordinator-api-C2ckGC2b.js → coordinator-api-BToPmSNg.js} +756 -495
- package/dist/coordinator-api-BToPmSNg.js.map +1 -0
- package/dist/coordinator-runtime.d.ts +2 -32
- package/dist/coordinator-runtime.d.ts.map +1 -1
- package/dist/coordinator-store-input-rules.d.ts +53 -0
- package/dist/coordinator-store-input-rules.d.ts.map +1 -0
- package/dist/coordinator-sync-config.d.ts +33 -0
- package/dist/coordinator-sync-config.d.ts.map +1 -0
- package/dist/d1-coordinator-store.d.ts.map +1 -1
- package/dist/database-runtime-primitives.d.ts +13 -0
- package/dist/database-runtime-primitives.d.ts.map +1 -0
- package/dist/db.d.ts +1 -21
- package/dist/db.d.ts.map +1 -1
- package/dist/extraction-tier-routing.d.ts.map +1 -1
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20445 -14796
- package/dist/index.js.map +1 -1
- package/dist/ingest-pipeline.d.ts +6 -12
- package/dist/ingest-pipeline.d.ts.map +1 -1
- package/dist/internal/cloudflare-coordinator.js +249 -467
- package/dist/internal/cloudflare-coordinator.js.map +1 -1
- package/dist/legacy-project-identity.d.ts +3 -0
- package/dist/legacy-project-identity.d.ts.map +1 -0
- package/dist/legacy-recipient-policy-projection.d.ts +1 -1
- package/dist/legacy-recipient-policy-projection.d.ts.map +1 -1
- package/dist/legacy-team-project-policy.d.ts +1 -1
- package/dist/legacy-team-project-policy.d.ts.map +1 -1
- package/dist/maintenance/ai-structured.d.ts.map +1 -1
- package/dist/managed-project-scope.d.ts +2 -0
- package/dist/managed-project-scope.d.ts.map +1 -0
- package/dist/observer-auth.d.ts +6 -1
- package/dist/observer-auth.d.ts.map +1 -1
- package/dist/observer-client.d.ts +48 -2
- package/dist/observer-client.d.ts.map +1 -1
- package/dist/observer-config.d.ts +69 -1
- package/dist/observer-config.d.ts.map +1 -1
- package/dist/observer-forced-tool.d.ts +3 -1
- package/dist/observer-forced-tool.d.ts.map +1 -1
- package/dist/observer-output-schema.d.ts +87 -29
- package/dist/observer-output-schema.d.ts.map +1 -1
- package/dist/observer-output.d.ts +10 -4
- package/dist/observer-output.d.ts.map +1 -1
- package/dist/observer-sse.d.ts +6 -0
- package/dist/observer-sse.d.ts.map +1 -0
- package/dist/pack.d.ts.map +1 -1
- package/dist/pi-hooks.d.ts.map +1 -1
- package/dist/pi-observer-config.d.ts +63 -0
- package/dist/pi-observer-config.d.ts.map +1 -0
- package/dist/project-label.d.ts +3 -0
- package/dist/project-label.d.ts.map +1 -0
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/raw-event-flush.d.ts.map +1 -1
- package/dist/raw-event-ingest.d.ts +5 -0
- package/dist/raw-event-ingest.d.ts.map +1 -1
- package/dist/recipient-policy-contract.d.ts +88 -0
- package/dist/recipient-policy-contract.d.ts.map +1 -1
- package/dist/recipient-policy-contract.js +24 -0
- package/dist/recipient-policy-contract.js.map +1 -0
- package/dist/recipient-policy-edges.d.ts +2 -72
- package/dist/recipient-policy-edges.d.ts.map +1 -1
- package/dist/recipient-policy-onboarding.d.ts.map +1 -1
- package/dist/recipient-policy-reconciler.d.ts.map +1 -1
- package/dist/recipient-policy-review.d.ts +1 -1
- package/dist/recipient-policy-review.d.ts.map +1 -1
- package/dist/recipient-policy-team-metadata.d.ts +2 -9
- package/dist/recipient-policy-team-metadata.d.ts.map +1 -1
- package/dist/schema-bootstrap.d.ts +1 -1
- package/dist/schema-bootstrap.d.ts.map +1 -1
- package/dist/scope-membership-cache.d.ts +1 -1
- package/dist/scope-membership-cache.d.ts.map +1 -1
- package/dist/scope-resolution.d.ts.map +1 -1
- package/dist/search.d.ts +13 -1
- package/dist/search.d.ts.map +1 -1
- package/dist/share-operation.d.ts +1 -1
- package/dist/share-operation.d.ts.map +1 -1
- package/dist/store.d.ts +11 -8
- package/dist/store.d.ts.map +1 -1
- package/dist/sync-discovery.d.ts +1 -16
- package/dist/sync-discovery.d.ts.map +1 -1
- package/dist/sync-pass.d.ts.map +1 -1
- package/dist/sync-peer-addresses.d.ts +9 -0
- package/dist/sync-peer-addresses.d.ts.map +1 -0
- package/dist/types.d.ts +17 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -5
- package/dist/coordinator-api-C2ckGC2b.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { $ as e,
|
|
1
|
+
import { $ as e, A as t, C as n, D as r, E as i, J as a, O as o, Q as s, S as c, T as l, W as u, X as d, Y as f, Z as p, at as m, b as h, ct as g, dt as _, et as v, ft as y, ht as b, it as x, k as S, lt as C, mt as w, n as T, nt as E, ot as ee, q as D, rt as te, st as O, t as k, tt as A, ut as j, w as M, x as N, y as P } from "../coordinator-api-BToPmSNg.js";
|
|
2
2
|
//#region src/d1-coordinator-store.ts
|
|
3
|
-
function
|
|
3
|
+
function F(e) {
|
|
4
4
|
if (e == null) throw Error("expected row");
|
|
5
5
|
return e;
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
let { presence_capabilities_json: t, presence_expires_at: n, ...r } =
|
|
7
|
+
function I(e) {
|
|
8
|
+
let { presence_capabilities_json: t, presence_expires_at: n, ...r } = F(e);
|
|
9
9
|
if (typeof n != "string" || typeof t != "string") return r;
|
|
10
10
|
try {
|
|
11
11
|
let e = JSON.parse(t);
|
|
@@ -23,37 +23,10 @@ function k(e) {
|
|
|
23
23
|
return r;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
let t = e.trim();
|
|
28
|
-
if (!t) return "";
|
|
29
|
-
let n = t.includes("://") ? t : `http://${t}`;
|
|
30
|
-
try {
|
|
31
|
-
let e = new URL(n);
|
|
32
|
-
return !e.hostname || e.port && (Number(e.port) <= 0 || Number(e.port) > 65535) ? "" : e.origin + e.pathname.replace(/\/+$/, "");
|
|
33
|
-
} catch {
|
|
34
|
-
return "";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function ne(e) {
|
|
38
|
-
if (!e) return "";
|
|
39
|
-
try {
|
|
40
|
-
let t = new URL(e), n = t.hostname.toLowerCase();
|
|
41
|
-
if ((t.protocol === "http:" || t.protocol === "") && n && t.port && t.pathname === "/") return `${n}:${t.port}`;
|
|
42
|
-
} catch {}
|
|
43
|
-
return e;
|
|
44
|
-
}
|
|
45
|
-
function j(e, t) {
|
|
46
|
-
let n = [], r = /* @__PURE__ */ new Set();
|
|
47
|
-
for (let i of [...e, ...t]) {
|
|
48
|
-
let e = A(i), t = ne(e);
|
|
49
|
-
!e || r.has(t) || (r.add(t), n.push(e));
|
|
50
|
-
}
|
|
51
|
-
return n;
|
|
52
|
-
}
|
|
53
|
-
function M() {
|
|
26
|
+
function L() {
|
|
54
27
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
55
28
|
}
|
|
56
|
-
function
|
|
29
|
+
function R(e, t) {
|
|
57
30
|
return e <= t ? {
|
|
58
31
|
low: e,
|
|
59
32
|
high: t
|
|
@@ -62,230 +35,39 @@ function re(e, t) {
|
|
|
62
35
|
high: e
|
|
63
36
|
};
|
|
64
37
|
}
|
|
65
|
-
function
|
|
38
|
+
function z(e) {
|
|
66
39
|
return e instanceof Error && /unique|constraint/i.test(e.message);
|
|
67
40
|
}
|
|
68
|
-
function
|
|
41
|
+
function B(e) {
|
|
69
42
|
let t = new Uint8Array(e);
|
|
70
43
|
globalThis.crypto.getRandomValues(t);
|
|
71
44
|
let n = [];
|
|
72
45
|
for (let e of t) n.push("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"[e % 64] ?? "A");
|
|
73
46
|
return n.join("");
|
|
74
47
|
}
|
|
75
|
-
async function
|
|
48
|
+
async function V(e) {
|
|
76
49
|
let t = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
|
|
77
50
|
return Array.from(new Uint8Array(t), (e) => e.toString(16).padStart(2, "0")).join("");
|
|
78
51
|
}
|
|
79
|
-
var
|
|
80
|
-
function oe(e) {
|
|
81
|
-
let t = String(e.groupId ?? "").trim(), n = String(e.seedDeviceId ?? "").trim(), r = String(e.workerDeviceId ?? "").trim(), i = String(e.expiresAt ?? "").trim(), a = String(e.createdBy ?? "").trim() || null;
|
|
82
|
-
if (!t || !n || !r || !i) throw Error("groupId, seedDeviceId, workerDeviceId, and expiresAt are required.");
|
|
83
|
-
return {
|
|
84
|
-
groupId: t,
|
|
85
|
-
seedDeviceId: n,
|
|
86
|
-
workerDeviceId: r,
|
|
87
|
-
expiresAt: i,
|
|
88
|
-
createdBy: a
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
function L(e) {
|
|
92
|
-
return e?.trim() || null;
|
|
93
|
-
}
|
|
94
|
-
async function se(e) {
|
|
95
|
-
let t = e.inviteKind ?? (L(e.operationId) ? "project_share" : "legacy_enrollment"), r = L(e.policyTeamId), i = L(e.targetIdentityId), a = L(e.reviewedPreviewDigest);
|
|
96
|
-
if (![
|
|
97
|
-
"legacy_enrollment",
|
|
98
|
-
"project_share",
|
|
99
|
-
"team_member",
|
|
100
|
-
"add_device"
|
|
101
|
-
].includes(t)) throw Error("inviteKind is invalid.");
|
|
102
|
-
if ([r, i].filter((e) => !!e).some((e) => e.length > 256 || /[\p{Cc}\p{Cf}]/u.test(e))) throw Error("recipient invite identifier is invalid.");
|
|
103
|
-
if (a && !/^[a-f0-9]{64}$/u.test(a)) throw Error("reviewedPreviewDigest must be a SHA-256 digest.");
|
|
104
|
-
if (t === "project_share") {
|
|
105
|
-
if (!L(e.operationId)) throw Error("project_share invite requires operationId.");
|
|
106
|
-
if (r || i || a) throw Error("recipient invite metadata requires a recipient invite kind.");
|
|
107
|
-
} else if (t === "legacy_enrollment") {
|
|
108
|
-
if (L(e.operationId)) throw Error("legacy_enrollment invite cannot reference an operation.");
|
|
109
|
-
if (r || i || a) throw Error("recipient invite metadata requires a recipient invite kind.");
|
|
110
|
-
} else if (t === "team_member") {
|
|
111
|
-
if (!r || !a || i || L(e.operationId)) throw Error("team_member invite metadata is invalid.");
|
|
112
|
-
} else if (t === "add_device" && (!i || !a || r || L(e.operationId))) throw Error("add_device invite metadata is invalid.");
|
|
113
|
-
if (e.reviewedIntent === void 0 || e.reviewedIntent === null) {
|
|
114
|
-
if (t === "team_member" || t === "add_device") throw Error("recipient_invite_review_unavailable");
|
|
115
|
-
return {
|
|
116
|
-
inviteKind: t,
|
|
117
|
-
policyTeamId: r,
|
|
118
|
-
targetIdentityId: i,
|
|
119
|
-
reviewedPreviewDigest: a,
|
|
120
|
-
reviewedIntentJson: null
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
let o;
|
|
124
|
-
if (t === "team_member" && r && a) o = {
|
|
125
|
-
kind: "team_member",
|
|
126
|
-
policyTeamId: r
|
|
127
|
-
};
|
|
128
|
-
else if (t === "add_device" && i && a) o = {
|
|
129
|
-
kind: "add_device",
|
|
130
|
-
targetIdentityId: i
|
|
131
|
-
};
|
|
132
|
-
else throw Error("recipient invite metadata requires a recipient invite kind.");
|
|
133
|
-
return await n(e.reviewedIntent, {
|
|
134
|
-
target: o,
|
|
135
|
-
digest: a
|
|
136
|
-
}), {
|
|
137
|
-
inviteKind: t,
|
|
138
|
-
policyTeamId: r,
|
|
139
|
-
targetIdentityId: i,
|
|
140
|
-
reviewedPreviewDigest: a,
|
|
141
|
-
reviewedIntentJson: p(e.reviewedIntent, o)
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
async function R(e) {
|
|
145
|
-
if (e.invite_kind === "team_member") {
|
|
146
|
-
if (!e.policy_team_id || !r(e.assigned_identity_id) || !e.reviewed_preview_digest) throw Error("invite_invalid");
|
|
147
|
-
let t = await T(e.reviewed_intent_json, {
|
|
148
|
-
target: {
|
|
149
|
-
kind: "team_member",
|
|
150
|
-
policyTeamId: e.policy_team_id
|
|
151
|
-
},
|
|
152
|
-
digest: e.reviewed_preview_digest
|
|
153
|
-
});
|
|
154
|
-
return {
|
|
155
|
-
kind: "team_member",
|
|
156
|
-
invite: e,
|
|
157
|
-
policy_team_id: e.policy_team_id,
|
|
158
|
-
assigned_identity_id: e.assigned_identity_id,
|
|
159
|
-
reviewed_preview_digest: e.reviewed_preview_digest,
|
|
160
|
-
reviewed_intent: t,
|
|
161
|
-
bound: !!e.consumed_at
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
if (e.invite_kind === "add_device") {
|
|
165
|
-
if (!e.target_identity_id || !e.reviewed_preview_digest) throw Error("invite_invalid");
|
|
166
|
-
let t = await T(e.reviewed_intent_json, {
|
|
167
|
-
target: {
|
|
168
|
-
kind: "add_device",
|
|
169
|
-
targetIdentityId: e.target_identity_id
|
|
170
|
-
},
|
|
171
|
-
digest: e.reviewed_preview_digest
|
|
172
|
-
});
|
|
173
|
-
return {
|
|
174
|
-
kind: "add_device",
|
|
175
|
-
invite: e,
|
|
176
|
-
target_identity_id: e.target_identity_id,
|
|
177
|
-
reviewed_preview_digest: e.reviewed_preview_digest,
|
|
178
|
-
reviewed_intent: t,
|
|
179
|
-
bound: !!e.consumed_at
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
function z(e, t = 0) {
|
|
185
|
-
if (e == null) return t;
|
|
186
|
-
if (!Number.isFinite(e) || e < 0) throw Error("membershipEpoch must be non-negative.");
|
|
187
|
-
return Math.trunc(e);
|
|
188
|
-
}
|
|
189
|
-
function ce(e) {
|
|
190
|
-
let t = L(e.scopeId), n = L(e.label);
|
|
191
|
-
if (!t || !n) throw Error("scopeId and label are required.");
|
|
192
|
-
return {
|
|
193
|
-
scopeId: t,
|
|
194
|
-
label: n,
|
|
195
|
-
kind: L(e.kind) ?? "user",
|
|
196
|
-
authorityType: L(e.authorityType) ?? "coordinator",
|
|
197
|
-
coordinatorId: L(e.coordinatorId),
|
|
198
|
-
groupId: L(e.groupId),
|
|
199
|
-
manifestIssuerDeviceId: L(e.manifestIssuerDeviceId),
|
|
200
|
-
membershipEpoch: z(e.membershipEpoch),
|
|
201
|
-
manifestHash: L(e.manifestHash),
|
|
202
|
-
status: L(e.status) ?? "active"
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
function B(e, t, n) {
|
|
206
|
-
if (e === void 0) return t;
|
|
207
|
-
let r = L(e);
|
|
208
|
-
if (!r) throw Error(`${n} must not be empty.`);
|
|
209
|
-
return r;
|
|
210
|
-
}
|
|
211
|
-
function V(e, t) {
|
|
212
|
-
return e === void 0 ? t : L(e);
|
|
213
|
-
}
|
|
214
|
-
function H(e, t) {
|
|
215
|
-
let n = L(e.scopeId);
|
|
216
|
-
if (!n) throw Error("scopeId is required.");
|
|
217
|
-
let r = e.membershipEpoch == null ? null : z(e.membershipEpoch);
|
|
218
|
-
if (r != null && r < t.membership_epoch) throw Error("membershipEpoch must not move backwards.");
|
|
219
|
-
return {
|
|
220
|
-
scopeId: n,
|
|
221
|
-
label: B(e.label, t.label, "label"),
|
|
222
|
-
kind: B(e.kind, t.kind, "kind"),
|
|
223
|
-
authorityType: B(e.authorityType, t.authority_type, "authorityType"),
|
|
224
|
-
coordinatorId: V(e.coordinatorId, t.coordinator_id),
|
|
225
|
-
groupId: V(e.groupId, t.group_id),
|
|
226
|
-
manifestIssuerDeviceId: V(e.manifestIssuerDeviceId, t.manifest_issuer_device_id),
|
|
227
|
-
membershipEpoch: r ?? t.membership_epoch,
|
|
228
|
-
manifestHash: V(e.manifestHash, t.manifest_hash),
|
|
229
|
-
status: B(e.status, t.status, "status")
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
function U(e, t, n) {
|
|
233
|
-
let r = L(e.scopeId), i = L(e.deviceId);
|
|
234
|
-
if (!r || !i) throw Error("scopeId and deviceId are required.");
|
|
235
|
-
let a = L(e.coordinatorId), o = L(e.groupId);
|
|
236
|
-
if (a && a !== t?.coordinator_id) throw Error("membership coordinatorId must match the scope coordinatorId.");
|
|
237
|
-
if (o && o !== t?.group_id) throw new f("scope_group_mismatch");
|
|
238
|
-
let s = e.membershipEpoch == null ? null : z(e.membershipEpoch), c = t?.membership_epoch ?? 0;
|
|
239
|
-
if (s != null && s < c) throw Error("membershipEpoch must not be lower than the scope membershipEpoch.");
|
|
240
|
-
if (s != null && n && s < (n.status === "revoked" ? n.membership_epoch + 1 : n.membership_epoch)) throw Error("membershipEpoch must not move backwards.");
|
|
241
|
-
let l = s ?? (n ? Math.max(c, n.membership_epoch + +(n.status === "revoked")) : c);
|
|
242
|
-
return {
|
|
243
|
-
scopeId: r,
|
|
244
|
-
deviceId: i,
|
|
245
|
-
role: L(e.role) ?? "member",
|
|
246
|
-
membershipEpoch: l,
|
|
247
|
-
coordinatorId: t?.coordinator_id ?? null,
|
|
248
|
-
groupId: t?.group_id ?? null,
|
|
249
|
-
manifestIssuerDeviceId: L(e.manifestIssuerDeviceId) ?? t?.manifest_issuer_device_id ?? null,
|
|
250
|
-
manifestHash: L(e.manifestHash) ?? t?.manifest_hash ?? null,
|
|
251
|
-
signedManifestJson: L(e.signedManifestJson),
|
|
252
|
-
actorType: L(e.actorType),
|
|
253
|
-
actorId: L(e.actorId)
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
function W(e) {
|
|
257
|
-
return e == null || !Number.isFinite(e) ? 100 : Math.max(1, Math.min(1e3, Math.trunc(e)));
|
|
258
|
-
}
|
|
52
|
+
var H = "invite_id, group_id, token, policy, expires_at, created_at, created_by,\n team_name_snapshot, revoked_at, operation_id, reviewed_project_set_digest, token_digest,\n inviter_actor_id, inviter_display_name, inviter_device_id, pending_person_id,\n project_summaries_json, project_intent_json, consumed_at, bound_device_id, bound_public_key, bound_fingerprint,\n recipient_actor_id, recipient_display_name, recipient_device_display_name, trust_state,\n bootstrap_grant_id, invite_kind, policy_team_id, target_identity_id, assigned_identity_id,\n reviewed_preview_digest, reviewed_intent_json", U = "group_id, device_id, public_key, fingerprint, identity_id, display_name, enabled, created_at", W = "enrolled_devices.group_id, enrolled_devices.device_id,\n enrolled_devices.public_key, enrolled_devices.fingerprint, enrolled_devices.identity_id,\n enrolled_devices.display_name, enrolled_devices.enabled, enrolled_devices.created_at,\n presence_records.expires_at AS presence_expires_at,\n presence_records.capabilities_json AS presence_capabilities_json";
|
|
259
53
|
function G(e, t) {
|
|
260
54
|
return e.prepare("INSERT INTO coordinator_scope_membership_audit_log(\n effect_id, 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 receipt.effect_id, ?, 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 JOIN coordinator_scope_membership_effect_receipts AS receipt\n ON receipt.effect_id = ? AND receipt.action = ? AND receipt.request_json = ?\n AND receipt.outcome_applied = 1\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.effectId, t.action, t.requestJson, t.scopeId, t.deviceId, t.status, t.membershipEpoch, t.updatedAt);
|
|
261
55
|
}
|
|
262
56
|
async function K(e, t) {
|
|
263
57
|
return await Z(e.prepare("SELECT effect_id, action, request_json, outcome_applied, scope_id, device_id,\n role, status, membership_epoch, coordinator_id, group_id, manifest_issuer_device_id,\n manifest_hash, signed_manifest_json, updated_at, created_at\n FROM coordinator_scope_membership_effect_receipts WHERE effect_id = ?").bind(t));
|
|
264
58
|
}
|
|
265
|
-
function
|
|
59
|
+
function q(e, t) {
|
|
266
60
|
return e.prepare("INSERT INTO coordinator_scope_membership_effect_receipts(\n effect_id, action, request_json, outcome_applied, scope_id, device_id,\n role, status, membership_epoch, coordinator_id, group_id, manifest_issuer_device_id,\n manifest_hash, signed_manifest_json, updated_at, created_at\n )\n SELECT ?, 'grant', ?, 1, membership.scope_id, membership.device_id,\n membership.role, membership.status, membership.membership_epoch,\n membership.coordinator_id, membership.group_id, membership.manifest_issuer_device_id,\n membership.manifest_hash, membership.signed_manifest_json, membership.updated_at, ?\n FROM coordinator_scope_memberships AS membership\n WHERE changes() > 0 AND membership.scope_id = ? AND membership.device_id = ?").bind(t.effectId, t.requestJson, t.createdAt, t.scopeId, t.deviceId);
|
|
267
61
|
}
|
|
268
|
-
function
|
|
62
|
+
function ne(e, t) {
|
|
269
63
|
return e.prepare("INSERT INTO coordinator_scope_membership_effect_receipts(\n effect_id, action, request_json, outcome_applied, scope_id, device_id,\n role, status, membership_epoch, coordinator_id, group_id, manifest_issuer_device_id,\n manifest_hash, signed_manifest_json, updated_at, created_at\n )\n SELECT ?, 'revoke', ?, changed.applied, ?, ?, membership.role, membership.status,\n membership.membership_epoch, membership.coordinator_id, membership.group_id,\n membership.manifest_issuer_device_id, membership.manifest_hash,\n membership.signed_manifest_json, membership.updated_at, ?\n FROM (SELECT CASE WHEN changes() > 0 THEN 1 ELSE 0 END AS applied) AS changed\n LEFT JOIN coordinator_scope_memberships AS membership\n ON changed.applied = 1 AND membership.scope_id = ? AND membership.device_id = ?\n WHERE NOT EXISTS (\n SELECT 1 FROM coordinator_scope_membership_effect_receipts WHERE effect_id = ?\n )").bind(t.effectId, t.requestJson, t.scopeId, t.deviceId, t.createdAt, t.scopeId, t.deviceId, t.effectId);
|
|
270
64
|
}
|
|
271
|
-
async function
|
|
65
|
+
async function J(e, t) {
|
|
272
66
|
if (!e.batch) throw Error("D1 batch support is required for audited scope membership changes.");
|
|
273
67
|
return await e.batch(t);
|
|
274
68
|
}
|
|
275
|
-
function J(e) {
|
|
276
|
-
return Number(e?.meta?.changes ?? 0);
|
|
277
|
-
}
|
|
278
69
|
function Y(e) {
|
|
279
|
-
|
|
280
|
-
let t = String(e.seedDeviceId ?? "").trim(), n = String(e.expiresAt ?? "").trim(), r = String(e.createdBy ?? "").trim() || null;
|
|
281
|
-
if (!t || !n) throw Error("bootstrapGrant.seedDeviceId and expiresAt are required.");
|
|
282
|
-
return {
|
|
283
|
-
groupId: "",
|
|
284
|
-
seedDeviceId: t,
|
|
285
|
-
workerDeviceId: "",
|
|
286
|
-
expiresAt: n,
|
|
287
|
-
createdBy: r
|
|
288
|
-
};
|
|
70
|
+
return Number(e?.meta?.changes ?? 0);
|
|
289
71
|
}
|
|
290
72
|
async function X(e) {
|
|
291
73
|
let t = await e.all();
|
|
@@ -305,43 +87,43 @@ var $ = class {
|
|
|
305
87
|
}
|
|
306
88
|
async close() {}
|
|
307
89
|
async createGroup(e, t) {
|
|
308
|
-
await this.db.prepare("INSERT OR IGNORE INTO groups(group_id, display_name, archived_at, created_at) VALUES (?, ?, NULL, ?)").bind(e, t ?? null,
|
|
90
|
+
await this.db.prepare("INSERT OR IGNORE INTO groups(group_id, display_name, archived_at, created_at) VALUES (?, ?, NULL, ?)").bind(e, t ?? null, L()).run();
|
|
309
91
|
}
|
|
310
92
|
async getGroup(e) {
|
|
311
93
|
let t = await Z(this.db.prepare("SELECT group_id, display_name, archived_at, created_at FROM groups WHERE group_id = ?").bind(e));
|
|
312
|
-
return t ?
|
|
94
|
+
return t ? F(t) : null;
|
|
313
95
|
}
|
|
314
96
|
async listGroups(e = !1) {
|
|
315
97
|
let t = e ? "" : "WHERE archived_at IS NULL";
|
|
316
|
-
return (await X(this.db.prepare(`SELECT group_id, display_name, archived_at, created_at FROM groups ${t} ORDER BY created_at ASC`))).map((e) =>
|
|
98
|
+
return (await X(this.db.prepare(`SELECT group_id, display_name, archived_at, created_at FROM groups ${t} ORDER BY created_at ASC`))).map((e) => F(e));
|
|
317
99
|
}
|
|
318
100
|
async renameGroup(e, t) {
|
|
319
101
|
return await Q(this.db.prepare("UPDATE groups SET display_name = ? WHERE group_id = ?").bind(t, e)) > 0;
|
|
320
102
|
}
|
|
321
|
-
async archiveGroup(e, t =
|
|
103
|
+
async archiveGroup(e, t = L()) {
|
|
322
104
|
return await Q(this.db.prepare("UPDATE groups SET archived_at = ? WHERE group_id = ? AND archived_at IS NULL").bind(t, e)) > 0;
|
|
323
105
|
}
|
|
324
106
|
async unarchiveGroup(e) {
|
|
325
107
|
return await Q(this.db.prepare("UPDATE groups SET archived_at = NULL WHERE group_id = ? AND archived_at IS NOT NULL").bind(e)) > 0;
|
|
326
108
|
}
|
|
327
109
|
async enrollDevice(e, t) {
|
|
328
|
-
if (await Q(this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, identity_id, 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 identity_id = COALESCE(enrolled_devices.identity_id, excluded.identity_id),\n display_name = excluded.display_name,\n enabled = 1\n WHERE excluded.identity_id IS NULL\n OR enrolled_devices.identity_id IS NULL\n OR enrolled_devices.identity_id = excluded.identity_id").bind(e, t.deviceId, t.publicKey, t.fingerprint, t.identityId ?? null, t.displayName ?? null,
|
|
110
|
+
if (await Q(this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, identity_id, 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 identity_id = COALESCE(enrolled_devices.identity_id, excluded.identity_id),\n display_name = excluded.display_name,\n enabled = 1\n WHERE excluded.identity_id IS NULL\n OR enrolled_devices.identity_id IS NULL\n OR enrolled_devices.identity_id = excluded.identity_id").bind(e, t.deviceId, t.publicKey, t.fingerprint, t.identityId ?? null, t.displayName ?? null, L())) === 0) throw Error("invite_identity_conflict");
|
|
329
111
|
}
|
|
330
112
|
async listEnrolledDevices(e, t) {
|
|
331
113
|
let n = t ? "" : "AND enrolled_devices.enabled = 1";
|
|
332
|
-
return (await X(this.db.prepare(`SELECT ${
|
|
114
|
+
return (await X(this.db.prepare(`SELECT ${W}
|
|
333
115
|
FROM enrolled_devices
|
|
334
116
|
LEFT JOIN presence_records
|
|
335
117
|
ON presence_records.group_id = enrolled_devices.group_id
|
|
336
118
|
AND presence_records.device_id = enrolled_devices.device_id
|
|
337
119
|
WHERE enrolled_devices.group_id = ? ${n}
|
|
338
|
-
ORDER BY enrolled_devices.created_at ASC, enrolled_devices.device_id ASC`).bind(e))).map(
|
|
120
|
+
ORDER BY enrolled_devices.created_at ASC, enrolled_devices.device_id ASC`).bind(e))).map(I);
|
|
339
121
|
}
|
|
340
122
|
async getEnrollment(e, t, n = !1) {
|
|
341
|
-
let r = n ? "" : "AND enabled = 1", i = await Z(this.db.prepare(`SELECT ${
|
|
123
|
+
let r = n ? "" : "AND enabled = 1", i = await Z(this.db.prepare(`SELECT ${U}
|
|
342
124
|
FROM enrolled_devices
|
|
343
125
|
WHERE group_id = ? AND device_id = ? ${r}`).bind(e, t));
|
|
344
|
-
return i ?
|
|
126
|
+
return i ? F(i) : null;
|
|
345
127
|
}
|
|
346
128
|
async renameDevice(e, t, n) {
|
|
347
129
|
return await Q(this.db.prepare("UPDATE enrolled_devices SET display_name = ?\n WHERE group_id = ? AND device_id = ?").bind(n, e, t)) > 0;
|
|
@@ -351,7 +133,7 @@ var $ = class {
|
|
|
351
133
|
}
|
|
352
134
|
async removeDevice(e, t) {
|
|
353
135
|
if (!this.db.batch) throw Error("D1 batch support is required for atomic device removal.");
|
|
354
|
-
return
|
|
136
|
+
return Y((await this.db.batch([
|
|
355
137
|
this.db.prepare("DELETE FROM presence_records WHERE group_id = ? AND device_id = ?").bind(e, t),
|
|
356
138
|
this.db.prepare("DELETE FROM coordinator_reciprocal_approvals WHERE group_id = ? AND (requesting_device_id = ? OR requested_device_id = ?)").bind(e, t, t),
|
|
357
139
|
this.db.prepare("DELETE FROM enrolled_devices WHERE group_id = ? AND device_id = ?").bind(e, t)
|
|
@@ -364,15 +146,15 @@ var $ = class {
|
|
|
364
146
|
await this.db.prepare("DELETE FROM request_nonces WHERE created_at < ?").bind(e).run();
|
|
365
147
|
}
|
|
366
148
|
async createInvite(e) {
|
|
367
|
-
let t =
|
|
149
|
+
let t = L(), n = B(12), r = B(24), i = await V(r), a = D(e.expiresAt), s = await this.getGroup(e.groupId), c = String(e.operationId ?? "").trim() || null, l = String(e.reviewedProjectSetDigest ?? "").trim() || null, u = await o(e), d = u.inviteKind === "team_member" ? `identity:${B(18)}` : null;
|
|
368
150
|
if (!!c != !!l) throw Error("operationId and reviewedProjectSetDigest must be provided together.");
|
|
369
151
|
let f = async () => {
|
|
370
152
|
if (!c) return null;
|
|
371
|
-
let t = await Z(this.db.prepare(`SELECT ${
|
|
153
|
+
let t = await Z(this.db.prepare(`SELECT ${H} FROM coordinator_invites WHERE operation_id = ?`).bind(c));
|
|
372
154
|
if (!t) return null;
|
|
373
155
|
if (t.consumed_at) throw Error("invite_already_bound");
|
|
374
156
|
if (t.group_id !== e.groupId || t.policy !== e.policy || t.invite_kind !== u.inviteKind || t.reviewed_project_set_digest !== l || t.inviter_actor_id !== (String(e.inviterActorId ?? "").trim() || null) || t.inviter_display_name !== (String(e.inviterDisplayName ?? "").trim() || null) || t.inviter_device_id !== (String(e.inviterDeviceId ?? "").trim() || null) || t.pending_person_id !== (String(e.pendingPersonId ?? "").trim() || null) || t.project_summaries_json !== (e.projectSummaries ? JSON.stringify(e.projectSummaries) : null) || t.project_intent_json !== (e.projectIntent ? JSON.stringify(e.projectIntent) : null) || t.policy_team_id !== u.policyTeamId || t.target_identity_id !== u.targetIdentityId || t.reviewed_preview_digest !== u.reviewedPreviewDigest || t.reviewed_intent_json !== u.reviewedIntentJson) throw Error("invite_operation_intent_conflict");
|
|
375
|
-
return
|
|
157
|
+
return F(t);
|
|
376
158
|
}, p = async (n) => {
|
|
377
159
|
if (!n.revoked_at && n.expires_at > t) return n;
|
|
378
160
|
await Q(this.db.prepare("UPDATE coordinator_invites\n SET token = ?, token_digest = ?, expires_at = ?, created_at = ?, created_by = ?,\n team_name_snapshot = ?, revoked_at = NULL\n WHERE operation_id = ? AND token = ?\n AND (revoked_at IS NOT NULL OR expires_at <= ?)").bind(r, i, a, t, e.createdBy ?? null, s?.display_name ?? null, c, n.token, t));
|
|
@@ -393,156 +175,156 @@ var $ = class {
|
|
|
393
175
|
}
|
|
394
176
|
throw e;
|
|
395
177
|
}
|
|
396
|
-
return
|
|
178
|
+
return F(await Z(this.db.prepare(`SELECT ${H} FROM coordinator_invites WHERE invite_id = ?`).bind(n)));
|
|
397
179
|
}
|
|
398
180
|
async getInviteByToken(e) {
|
|
399
|
-
let t = await
|
|
181
|
+
let t = await V(e), n = await Z(this.db.prepare(`SELECT ${H}
|
|
400
182
|
FROM coordinator_invites
|
|
401
183
|
WHERE (token_digest = ? OR token = ?)
|
|
402
184
|
AND revoked_at IS NULL
|
|
403
|
-
AND expires_at > ?`).bind(t, e,
|
|
404
|
-
return n ?
|
|
185
|
+
AND expires_at > ?`).bind(t, e, L()));
|
|
186
|
+
return n ? F(n) : null;
|
|
405
187
|
}
|
|
406
188
|
async getInviteByTokenForInspection(e) {
|
|
407
|
-
let t = await
|
|
408
|
-
return n ?
|
|
189
|
+
let t = await V(e), n = await Z(this.db.prepare(`SELECT ${H} FROM coordinator_invites WHERE token_digest = ? OR token = ?`).bind(t, e));
|
|
190
|
+
return n ? F(n) : null;
|
|
409
191
|
}
|
|
410
192
|
async inspectRecipientInvite(e) {
|
|
411
193
|
let t = await this.getInviteByTokenForInspection(e.token);
|
|
412
194
|
if (!t) return null;
|
|
413
|
-
let n = await
|
|
195
|
+
let n = await N(t);
|
|
414
196
|
if (!n) return null;
|
|
415
197
|
if (t.revoked_at) throw Error("invite_invalid");
|
|
416
|
-
if (!t.consumed_at && new Date(t.expires_at) <= new Date(
|
|
198
|
+
if (!t.consumed_at && new Date(t.expires_at) <= new Date(D(e.now))) throw Error("invite_expired");
|
|
417
199
|
let r = await this.getGroup(t.group_id);
|
|
418
200
|
if (!r) throw Error("group_not_found");
|
|
419
201
|
if (r.archived_at) throw Error("group_archived");
|
|
420
202
|
return n;
|
|
421
203
|
}
|
|
422
204
|
async consumeRecipientInvite(e) {
|
|
423
|
-
let t =
|
|
205
|
+
let t = D(e.now), n = e.recipientDisplayName ?? null, r = e.deviceDisplayName ?? null;
|
|
424
206
|
if (!e.identityId || !e.deviceId || !e.publicKey || !e.fingerprint || e.identityId !== e.identityId.trim() || e.deviceId !== e.deviceId.trim() || e.identityId.length > 256 || e.deviceId.length > 256 || /[\p{Cc}\p{Cf}]/u.test(e.identityId) || /[\p{Cc}\p{Cf}]/u.test(e.deviceId)) throw Error("invite_identity_conflict");
|
|
425
|
-
let i = await
|
|
426
|
-
if (!
|
|
427
|
-
let c = await this.getGroup(
|
|
207
|
+
let i = await V(e.token), o = await this.getInviteByTokenForInspection(e.token), s = o ? await N(o) : null;
|
|
208
|
+
if (!o || !s || s.kind !== e.inviteKind || o.revoked_at) throw Error("invite_invalid");
|
|
209
|
+
let c = await this.getGroup(o.group_id);
|
|
428
210
|
if (!c) throw Error("group_not_found");
|
|
429
211
|
if (c.archived_at) throw Error("group_archived");
|
|
430
|
-
if (!
|
|
431
|
-
if (
|
|
432
|
-
let
|
|
433
|
-
if (
|
|
434
|
-
let
|
|
435
|
-
if (
|
|
436
|
-
if (
|
|
437
|
-
let
|
|
438
|
-
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(
|
|
439
|
-
if (
|
|
440
|
-
let
|
|
441
|
-
if (!
|
|
212
|
+
if (!o.consumed_at && new Date(o.expires_at) <= new Date(t)) throw Error("invite_expired");
|
|
213
|
+
if (P(e.publicKey) !== e.fingerprint) throw Error("fingerprint_mismatch");
|
|
214
|
+
let l = a(s);
|
|
215
|
+
if (l !== e.identityId) throw Error("invite_identity_conflict");
|
|
216
|
+
let u = o.bound_device_id === e.deviceId && o.bound_public_key === e.publicKey && o.bound_fingerprint === e.fingerprint;
|
|
217
|
+
if (o.consumed_at && !u) throw Error("invite_already_bound");
|
|
218
|
+
if (o.consumed_at && o.recipient_actor_id !== l) throw Error("invite_identity_conflict");
|
|
219
|
+
let d = await Z(this.db.prepare(`SELECT ${U}
|
|
220
|
+
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(o.group_id, e.deviceId));
|
|
221
|
+
if (d && (d.public_key !== e.publicKey || d.fingerprint !== e.fingerprint || d.identity_id !== null && d.identity_id !== l)) throw Error("invite_identity_conflict");
|
|
222
|
+
let f = 0, p = B(12);
|
|
223
|
+
if (!o.consumed_at) {
|
|
442
224
|
if (!this.db.batch) throw Error("D1 batch support is required for atomic invite consume.");
|
|
443
|
-
|
|
444
|
-
this.db.prepare("UPDATE coordinator_invites SET token = ?, consumed_at = ?, bound_device_id = ?,\n bound_public_key = ?, bound_fingerprint = ?, recipient_actor_id = ?,\n recipient_display_name = ?, recipient_device_display_name = ?\n WHERE (token_digest = ? OR token = ?) AND consumed_at IS NULL\n AND revoked_at IS NULL AND expires_at > ? AND invite_kind = ?\n AND reviewed_intent_json = ? AND reviewed_preview_digest = ?\n AND ((invite_kind = 'team_member' AND assigned_identity_id = ?)\n OR (invite_kind = 'add_device' AND target_identity_id = ?))\n AND NOT EXISTS (\n SELECT 1 FROM enrolled_devices e\n WHERE e.group_id = coordinator_invites.group_id AND e.device_id = ?\n AND (e.public_key <> ? OR e.fingerprint <> ?\n OR (e.identity_id IS NOT NULL AND e.identity_id <> ?))\n )\n AND EXISTS (SELECT 1 FROM groups g WHERE g.group_id = coordinator_invites.group_id\n AND g.archived_at IS NULL)").bind(`consumed:${
|
|
445
|
-
this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, identity_id, display_name, enabled, created_at\n ) SELECT i.group_id, i.bound_device_id, i.bound_public_key, i.bound_fingerprint,\n i.recipient_actor_id, i.recipient_device_display_name, 1, ? FROM coordinator_invites i\n JOIN groups g ON g.group_id = i.group_id AND g.archived_at IS NULL\n WHERE (i.token_digest = ? OR i.token = ?) AND i.bound_device_id = ?\n AND i.bound_public_key = ? AND i.bound_fingerprint = ?\n AND i.recipient_actor_id = ?\n ON CONFLICT(group_id, device_id) DO UPDATE SET\n identity_id = COALESCE(enrolled_devices.identity_id, excluded.identity_id),\n display_name = COALESCE(enrolled_devices.display_name, excluded.display_name),\n enabled = 1\n WHERE enrolled_devices.identity_id IS NULL\n OR enrolled_devices.identity_id = excluded.identity_id").bind(t, i, e.token, e.deviceId, e.publicKey, e.fingerprint,
|
|
446
|
-
this.db.prepare("UPDATE coordinator_invites SET bootstrap_grant_id = ?,\n trust_state = 'bootstrap_grant_created'\n WHERE (token_digest = ? OR token = ?) AND invite_kind = 'add_device'\n AND bootstrap_grant_id IS NULL AND inviter_device_id IS NOT NULL\n AND expires_at > ?\n AND EXISTS (SELECT 1 FROM enrolled_devices e\n WHERE e.group_id = coordinator_invites.group_id\n AND e.device_id = coordinator_invites.inviter_device_id AND e.enabled = 1)").bind(
|
|
225
|
+
f = Y((await this.db.batch([
|
|
226
|
+
this.db.prepare("UPDATE coordinator_invites SET token = ?, consumed_at = ?, bound_device_id = ?,\n bound_public_key = ?, bound_fingerprint = ?, recipient_actor_id = ?,\n recipient_display_name = ?, recipient_device_display_name = ?\n WHERE (token_digest = ? OR token = ?) AND consumed_at IS NULL\n AND revoked_at IS NULL AND expires_at > ? AND invite_kind = ?\n AND reviewed_intent_json = ? AND reviewed_preview_digest = ?\n AND ((invite_kind = 'team_member' AND assigned_identity_id = ?)\n OR (invite_kind = 'add_device' AND target_identity_id = ?))\n AND NOT EXISTS (\n SELECT 1 FROM enrolled_devices e\n WHERE e.group_id = coordinator_invites.group_id AND e.device_id = ?\n AND (e.public_key <> ? OR e.fingerprint <> ?\n OR (e.identity_id IS NOT NULL AND e.identity_id <> ?))\n )\n AND EXISTS (SELECT 1 FROM groups g WHERE g.group_id = coordinator_invites.group_id\n AND g.archived_at IS NULL)").bind(`consumed:${o.invite_id}`, t, e.deviceId, e.publicKey, e.fingerprint, l, n, r, i, e.token, t, e.inviteKind, o.reviewed_intent_json, o.reviewed_preview_digest, l, l, e.deviceId, e.publicKey, e.fingerprint, l),
|
|
227
|
+
this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, identity_id, display_name, enabled, created_at\n ) SELECT i.group_id, i.bound_device_id, i.bound_public_key, i.bound_fingerprint,\n i.recipient_actor_id, i.recipient_device_display_name, 1, ? FROM coordinator_invites i\n JOIN groups g ON g.group_id = i.group_id AND g.archived_at IS NULL\n WHERE (i.token_digest = ? OR i.token = ?) AND i.bound_device_id = ?\n AND i.bound_public_key = ? AND i.bound_fingerprint = ?\n AND i.recipient_actor_id = ?\n ON CONFLICT(group_id, device_id) DO UPDATE SET\n identity_id = COALESCE(enrolled_devices.identity_id, excluded.identity_id),\n display_name = COALESCE(enrolled_devices.display_name, excluded.display_name),\n enabled = 1\n WHERE enrolled_devices.identity_id IS NULL\n OR enrolled_devices.identity_id = excluded.identity_id").bind(t, i, e.token, e.deviceId, e.publicKey, e.fingerprint, l),
|
|
228
|
+
this.db.prepare("UPDATE coordinator_invites SET bootstrap_grant_id = ?,\n trust_state = 'bootstrap_grant_created'\n WHERE (token_digest = ? OR token = ?) AND invite_kind = 'add_device'\n AND bootstrap_grant_id IS NULL AND inviter_device_id IS NOT NULL\n AND expires_at > ?\n AND EXISTS (SELECT 1 FROM enrolled_devices e\n WHERE e.group_id = coordinator_invites.group_id\n AND e.device_id = coordinator_invites.inviter_device_id AND e.enabled = 1)").bind(p, i, e.token, t),
|
|
447
229
|
this.db.prepare("INSERT OR IGNORE INTO coordinator_bootstrap_grants(\n grant_id, group_id, seed_device_id, worker_device_id, expires_at,\n created_at, created_by, revoked_at\n ) SELECT i.bootstrap_grant_id, i.group_id, i.inviter_device_id, i.bound_device_id,\n i.expires_at, ?, i.recipient_actor_id, NULL FROM coordinator_invites i\n JOIN enrolled_devices e ON e.group_id = i.group_id\n AND e.device_id = i.inviter_device_id AND e.enabled = 1\n WHERE (i.token_digest = ? OR i.token = ?) AND i.invite_kind = 'add_device'\n AND i.bootstrap_grant_id IS NOT NULL AND i.bound_device_id = ?").bind(t, i, e.token, e.deviceId)
|
|
448
230
|
]))[0]);
|
|
449
231
|
}
|
|
450
|
-
let
|
|
451
|
-
if (!
|
|
452
|
-
if (
|
|
453
|
-
let
|
|
454
|
-
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(
|
|
455
|
-
if (
|
|
456
|
-
let
|
|
457
|
-
if (!
|
|
458
|
-
let
|
|
459
|
-
if (!
|
|
460
|
-
if (
|
|
461
|
-
if (
|
|
462
|
-
if (
|
|
463
|
-
await this.db.prepare("UPDATE enrolled_devices SET identity_id = ?\n WHERE group_id = ? AND device_id = ? AND identity_id IS NULL\n AND public_key = ? AND fingerprint = ?").bind(
|
|
464
|
-
let
|
|
465
|
-
if (!
|
|
466
|
-
if (
|
|
467
|
-
let
|
|
468
|
-
if (
|
|
232
|
+
let m = await this.getGroup(o.group_id);
|
|
233
|
+
if (!m) throw Error("group_not_found");
|
|
234
|
+
if (m.archived_at) throw Error("group_archived");
|
|
235
|
+
let h = await Z(this.db.prepare(`SELECT ${U}
|
|
236
|
+
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(o.group_id, e.deviceId));
|
|
237
|
+
if (h && (h.public_key !== e.publicKey || h.fingerprint !== e.fingerprint || h.identity_id !== null && h.identity_id !== l)) throw Error("invite_identity_conflict");
|
|
238
|
+
let g = await this.getInviteByTokenForInspection(e.token);
|
|
239
|
+
if (!g || g.revoked_at || !g.consumed_at && new Date(g.expires_at) <= new Date(t)) throw Error("invite_invalid");
|
|
240
|
+
let _ = await N(g);
|
|
241
|
+
if (!_ || _.kind !== e.inviteKind) throw Error("invite_invalid");
|
|
242
|
+
if (a(_) !== l) throw Error("invite_identity_conflict");
|
|
243
|
+
if (g.bound_device_id !== e.deviceId || g.bound_public_key !== e.publicKey || g.bound_fingerprint !== e.fingerprint) throw Error("invite_already_bound");
|
|
244
|
+
if (g.recipient_actor_id !== l) throw Error("invite_identity_conflict");
|
|
245
|
+
await this.db.prepare("UPDATE enrolled_devices SET identity_id = ?\n WHERE group_id = ? AND device_id = ? AND identity_id IS NULL\n AND public_key = ? AND fingerprint = ?").bind(l, g.group_id, e.deviceId, e.publicKey, e.fingerprint).run();
|
|
246
|
+
let v = await this.getEnrollment(g.group_id, e.deviceId);
|
|
247
|
+
if (!v) throw Error("invite_acceptance_incomplete");
|
|
248
|
+
if (v.public_key !== e.publicKey || v.fingerprint !== e.fingerprint || v.identity_id !== l) throw Error("invite_identity_conflict");
|
|
249
|
+
let y = g;
|
|
250
|
+
if (_.kind === "add_device" && g.inviter_device_id && !g.bootstrap_grant_id && new Date(g.expires_at) > new Date(t)) {
|
|
469
251
|
if (!this.db.batch) throw Error("D1 batch support is required for atomic bootstrap grant recovery.");
|
|
470
|
-
let n =
|
|
471
|
-
await this.db.batch([this.db.prepare("UPDATE coordinator_invites SET bootstrap_grant_id = ?,\n trust_state = 'bootstrap_grant_created'\n WHERE invite_id = ? AND invite_kind = 'add_device'\n AND bootstrap_grant_id IS NULL AND inviter_device_id IS NOT NULL\n AND bound_device_id = ? AND recipient_actor_id = ? AND expires_at > ?\n AND EXISTS (SELECT 1 FROM enrolled_devices e\n WHERE e.group_id = coordinator_invites.group_id\n AND e.device_id = coordinator_invites.inviter_device_id AND e.enabled = 1)").bind(n,
|
|
252
|
+
let n = B(12);
|
|
253
|
+
await this.db.batch([this.db.prepare("UPDATE coordinator_invites SET bootstrap_grant_id = ?,\n trust_state = 'bootstrap_grant_created'\n WHERE invite_id = ? AND invite_kind = 'add_device'\n AND bootstrap_grant_id IS NULL AND inviter_device_id IS NOT NULL\n AND bound_device_id = ? AND recipient_actor_id = ? AND expires_at > ?\n AND EXISTS (SELECT 1 FROM enrolled_devices e\n WHERE e.group_id = coordinator_invites.group_id\n AND e.device_id = coordinator_invites.inviter_device_id AND e.enabled = 1)").bind(n, g.invite_id, e.deviceId, l, t), this.db.prepare("INSERT OR IGNORE INTO coordinator_bootstrap_grants(\n grant_id, group_id, seed_device_id, worker_device_id, expires_at,\n created_at, created_by, revoked_at\n ) SELECT i.bootstrap_grant_id, i.group_id, i.inviter_device_id, i.bound_device_id,\n i.expires_at, ?, i.recipient_actor_id, NULL FROM coordinator_invites i\n JOIN enrolled_devices e ON e.group_id = i.group_id\n AND e.device_id = i.inviter_device_id AND e.enabled = 1\n WHERE i.invite_id = ? AND i.invite_kind = 'add_device'\n AND i.bootstrap_grant_id IS NOT NULL AND i.bound_device_id = ?").bind(t, g.invite_id, e.deviceId)]);
|
|
472
254
|
let r = await this.getInviteByTokenForInspection(e.token);
|
|
473
255
|
if (!r) throw Error("invite_invalid");
|
|
474
|
-
|
|
256
|
+
y = r;
|
|
475
257
|
}
|
|
476
|
-
let
|
|
258
|
+
let b = y.bootstrap_grant_id ? await this.getBootstrapGrant(y.bootstrap_grant_id) : null;
|
|
477
259
|
return {
|
|
478
|
-
status:
|
|
479
|
-
invite:
|
|
480
|
-
reviewed_intent:
|
|
481
|
-
bootstrap_grant:
|
|
260
|
+
status: f === 1 ? "accepted" : "existing",
|
|
261
|
+
invite: y,
|
|
262
|
+
reviewed_intent: _.reviewed_intent,
|
|
263
|
+
bootstrap_grant: b
|
|
482
264
|
};
|
|
483
265
|
}
|
|
484
266
|
async consumeProjectInvite(e) {
|
|
485
267
|
if (!this.db.batch) throw Error("D1 batch support is required for atomic invite consume.");
|
|
486
|
-
let t =
|
|
268
|
+
let t = D(e.now), n = await V(e.token), r = await this.getInviteByTokenForInspection(e.token);
|
|
487
269
|
if (!r?.operation_id || !r.project_intent_json || r.revoked_at) throw Error("invite_invalid");
|
|
488
270
|
let i = await this.getGroup(r.group_id);
|
|
489
271
|
if (!i) throw Error("group_not_found");
|
|
490
272
|
if (i.archived_at) throw Error("group_archived");
|
|
491
273
|
if (r.operation_id !== e.operationId) throw Error("invite_invalid");
|
|
492
|
-
if (
|
|
274
|
+
if (P(e.publicKey) !== e.fingerprint) throw Error("fingerprint_mismatch");
|
|
493
275
|
if (!r.consumed_at && new Date(r.expires_at) <= new Date(t)) throw Error("invite_expired");
|
|
494
276
|
let a = r.bound_device_id === e.deviceId && r.bound_public_key === e.publicKey && r.bound_fingerprint === e.fingerprint;
|
|
495
277
|
if (r.consumed_at && !a) throw Error("invite_already_bound");
|
|
496
278
|
if (r.consumed_at && (r.recipient_actor_id !== e.recipientActorId || r.recipient_display_name !== e.recipientDisplayName || r.recipient_device_display_name !== e.deviceDisplayName)) throw Error("invite_identity_conflict");
|
|
497
|
-
let
|
|
279
|
+
let o = await Z(this.db.prepare(`SELECT ${U}
|
|
498
280
|
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(r.group_id, e.deviceId));
|
|
499
|
-
if (
|
|
500
|
-
let
|
|
281
|
+
if (o && (o.public_key !== e.publicKey || o.fingerprint !== e.fingerprint || o.identity_id != null && o.identity_id !== e.recipientActorId)) throw Error("invite_identity_conflict");
|
|
282
|
+
let s = B(12), c = Y((await this.db.batch([
|
|
501
283
|
this.db.prepare("UPDATE coordinator_invites SET token = ?, consumed_at = ?, bound_device_id = ?,\n bound_public_key = ?, bound_fingerprint = ?, recipient_actor_id = ?,\n recipient_display_name = ?, recipient_device_display_name = ?,\n trust_state = 'pending_inviter_device'\n WHERE (token_digest = ? OR token = ?) AND consumed_at IS NULL\n AND EXISTS (SELECT 1 FROM groups g WHERE g.group_id = coordinator_invites.group_id\n AND g.archived_at IS NULL)").bind(`consumed:${r.invite_id}`, t, e.deviceId, e.publicKey, e.fingerprint, e.recipientActorId, e.recipientDisplayName, e.deviceDisplayName, n, e.token),
|
|
502
284
|
this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, identity_id, display_name, enabled, created_at\n ) SELECT i.group_id, i.bound_device_id, i.bound_public_key, i.bound_fingerprint,\n i.recipient_actor_id, i.recipient_device_display_name, 1, ? FROM coordinator_invites i\n JOIN groups g ON g.group_id = i.group_id AND g.archived_at IS NULL\n WHERE (i.token_digest = ? OR i.token = ?) AND i.bound_device_id = ? AND ? = 1\n ON CONFLICT(group_id, device_id) DO UPDATE SET\n identity_id = COALESCE(enrolled_devices.identity_id, excluded.identity_id),\n display_name = excluded.display_name, enabled = 1\n WHERE enrolled_devices.identity_id IS NULL\n OR enrolled_devices.identity_id = excluded.identity_id").bind(t, n, e.token, e.deviceId, +!r.consumed_at),
|
|
503
|
-
this.db.prepare("UPDATE coordinator_invites SET bootstrap_grant_id = ?,\n trust_state = 'bootstrap_grant_created'\n WHERE (token_digest = ? OR token = ?) AND bootstrap_grant_id IS NULL\n AND bound_device_id = ?\n AND EXISTS (SELECT 1 FROM groups g WHERE g.group_id = coordinator_invites.group_id\n AND g.archived_at IS NULL)\n AND expires_at > ?\n AND EXISTS (SELECT 1 FROM enrolled_devices e WHERE e.group_id = coordinator_invites.group_id\n AND e.device_id = coordinator_invites.inviter_device_id AND e.enabled = 1)").bind(
|
|
285
|
+
this.db.prepare("UPDATE coordinator_invites SET bootstrap_grant_id = ?,\n trust_state = 'bootstrap_grant_created'\n WHERE (token_digest = ? OR token = ?) AND bootstrap_grant_id IS NULL\n AND bound_device_id = ?\n AND EXISTS (SELECT 1 FROM groups g WHERE g.group_id = coordinator_invites.group_id\n AND g.archived_at IS NULL)\n AND expires_at > ?\n AND EXISTS (SELECT 1 FROM enrolled_devices e WHERE e.group_id = coordinator_invites.group_id\n AND e.device_id = coordinator_invites.inviter_device_id AND e.enabled = 1)").bind(s, n, e.token, e.deviceId, t),
|
|
504
286
|
this.db.prepare("INSERT OR IGNORE INTO coordinator_bootstrap_grants(\n grant_id, group_id, seed_device_id, worker_device_id, expires_at, created_at,\n created_by, revoked_at\n ) SELECT i.bootstrap_grant_id, i.group_id, i.inviter_device_id, i.bound_device_id,\n i.expires_at, ?, i.inviter_actor_id, NULL FROM coordinator_invites i\n JOIN groups g ON g.group_id = i.group_id AND g.archived_at IS NULL\n JOIN enrolled_devices e ON e.group_id = i.group_id AND e.device_id = i.inviter_device_id\n WHERE (i.token_digest = ? OR i.token = ?) AND i.bootstrap_grant_id IS NOT NULL\n AND i.bound_device_id = ? AND e.enabled = 1").bind(t, n, e.token, e.deviceId)
|
|
505
|
-
]))[0]) === 1,
|
|
506
|
-
if (!
|
|
507
|
-
if (
|
|
508
|
-
let
|
|
509
|
-
if (!
|
|
510
|
-
if (
|
|
511
|
-
if (
|
|
512
|
-
|
|
513
|
-
let
|
|
514
|
-
if (!
|
|
515
|
-
if (
|
|
516
|
-
let
|
|
287
|
+
]))[0]) === 1, l = await this.getGroup(r.group_id);
|
|
288
|
+
if (!l) throw Error("group_not_found");
|
|
289
|
+
if (l.archived_at) throw Error("group_archived");
|
|
290
|
+
let u = await this.getInviteByTokenForInspection(e.token);
|
|
291
|
+
if (!u) throw Error("invite_invalid");
|
|
292
|
+
if (u.bound_device_id !== e.deviceId || u.bound_public_key !== e.publicKey || u.bound_fingerprint !== e.fingerprint) throw Error("invite_already_bound");
|
|
293
|
+
if (u.recipient_actor_id !== e.recipientActorId || u.recipient_display_name !== e.recipientDisplayName || u.recipient_device_display_name !== e.deviceDisplayName) throw Error("invite_identity_conflict");
|
|
294
|
+
c || await this.db.prepare("UPDATE enrolled_devices SET identity_id = ?\n WHERE group_id = ? AND device_id = ? AND identity_id IS NULL AND enabled = 1\n AND public_key = ? AND fingerprint = ?").bind(e.recipientActorId, u.group_id, e.deviceId, e.publicKey, e.fingerprint).run();
|
|
295
|
+
let d = await this.getEnrollment(u.group_id, e.deviceId);
|
|
296
|
+
if (!d) throw Error("invite_acceptance_incomplete");
|
|
297
|
+
if (d.identity_id !== e.recipientActorId) throw Error("invite_identity_conflict");
|
|
298
|
+
let f = u.inviter_device_id ? await this.getEnrollment(u.group_id, u.inviter_device_id) : null, p = u.bootstrap_grant_id ? await this.getBootstrapGrant(u.bootstrap_grant_id) : null;
|
|
517
299
|
return {
|
|
518
|
-
status:
|
|
519
|
-
invite:
|
|
520
|
-
enrollment:
|
|
521
|
-
seed_enrollment:
|
|
522
|
-
bootstrap_grant:
|
|
300
|
+
status: c ? "accepted" : "existing",
|
|
301
|
+
invite: u,
|
|
302
|
+
enrollment: d,
|
|
303
|
+
seed_enrollment: f,
|
|
304
|
+
bootstrap_grant: p
|
|
523
305
|
};
|
|
524
306
|
}
|
|
525
307
|
async listInvites(e) {
|
|
526
|
-
return (await X(this.db.prepare(`SELECT ${
|
|
308
|
+
return (await X(this.db.prepare(`SELECT ${H}
|
|
527
309
|
FROM coordinator_invites WHERE group_id = ?
|
|
528
|
-
ORDER BY created_at DESC`).bind(e))).map((e) =>
|
|
310
|
+
ORDER BY created_at DESC`).bind(e))).map((e) => F(e));
|
|
529
311
|
}
|
|
530
312
|
async createJoinRequest(e) {
|
|
531
|
-
let t =
|
|
532
|
-
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(n, e.groupId, e.deviceId, e.publicKey, e.fingerprint, e.displayName ?? null, e.token, t).run(),
|
|
313
|
+
let t = L(), n = B(12);
|
|
314
|
+
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(n, e.groupId, e.deviceId, e.publicKey, e.fingerprint, e.displayName ?? null, e.token, t).run(), F(await Z(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(n)));
|
|
533
315
|
}
|
|
534
316
|
async listJoinRequests(e, t) {
|
|
535
317
|
let n = t ?? "pending";
|
|
536
|
-
return (await X(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, n))).map((e) =>
|
|
318
|
+
return (await X(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, n))).map((e) => F(e));
|
|
537
319
|
}
|
|
538
320
|
async reviewJoinRequest(e) {
|
|
539
321
|
let t = await Z(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));
|
|
540
322
|
if (!t) return null;
|
|
541
323
|
if (t.status !== "pending") return {
|
|
542
|
-
...
|
|
324
|
+
...F(t),
|
|
543
325
|
_no_transition: !0
|
|
544
326
|
};
|
|
545
|
-
let n =
|
|
327
|
+
let n = l(e.bootstrapGrant), r = L(), i = e.approved ? "approved" : "denied", a = null, o = null;
|
|
546
328
|
if (e.approved && n) {
|
|
547
329
|
if (!await Z(this.db.prepare("SELECT device_id FROM enrolled_devices WHERE group_id = ? AND device_id = ? AND enabled = 1").bind(t.group_id, n.seedDeviceId))) throw Error("bootstrap grant seed device is not enrolled in the group.");
|
|
548
330
|
if (n.seedDeviceId === t.device_id) throw Error("bootstrap grant seed and worker device ids must differ.");
|
|
@@ -554,9 +336,9 @@ var $ = class {
|
|
|
554
336
|
}
|
|
555
337
|
if (this.db.batch) {
|
|
556
338
|
let t = [];
|
|
557
|
-
if (t.push(this.db.prepare("UPDATE coordinator_join_requests\n SET status = ?, reviewed_at = ?, reviewed_by = ?\n WHERE request_id = ? AND status = 'pending'").bind(i, r, e.reviewedBy ?? null, e.requestId)), e.approved && (t.push(this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, display_name, enabled, created_at\n )\n SELECT group_id, device_id, public_key, fingerprint, display_name, 1, ?\n FROM coordinator_join_requests\n WHERE request_id = ?\n AND status = 'approved'\n AND reviewed_at = ?\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(
|
|
558
|
-
o =
|
|
559
|
-
let n =
|
|
339
|
+
if (t.push(this.db.prepare("UPDATE coordinator_join_requests\n SET status = ?, reviewed_at = ?, reviewed_by = ?\n WHERE request_id = ? AND status = 'pending'").bind(i, r, e.reviewedBy ?? null, e.requestId)), e.approved && (t.push(this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, display_name, enabled, created_at\n )\n SELECT group_id, device_id, public_key, fingerprint, display_name, 1, ?\n FROM coordinator_join_requests\n WHERE request_id = ?\n AND status = 'approved'\n AND reviewed_at = ?\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(L(), e.requestId, r)), a)) {
|
|
340
|
+
o = B(12);
|
|
341
|
+
let n = L();
|
|
560
342
|
t.push(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 ) SELECT ?, ?, ?, ?, ?, ?, ?, NULL\n WHERE EXISTS (\n SELECT 1 FROM coordinator_join_requests\n WHERE request_id = ? AND status = 'approved' AND reviewed_at = ?\n )").bind(o, a.groupId, a.seedDeviceId, a.workerDeviceId, a.expiresAt, n, a.createdBy ?? null, e.requestId, r));
|
|
561
343
|
}
|
|
562
344
|
await this.db.batch(t);
|
|
@@ -575,7 +357,7 @@ var $ = class {
|
|
|
575
357
|
n && await this.revokeBootstrapGrant(n);
|
|
576
358
|
let t = await Z(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));
|
|
577
359
|
return t ? {
|
|
578
|
-
...
|
|
360
|
+
...F(t),
|
|
579
361
|
_no_transition: !0
|
|
580
362
|
} : null;
|
|
581
363
|
}
|
|
@@ -584,7 +366,7 @@ var $ = class {
|
|
|
584
366
|
if (!s) return null;
|
|
585
367
|
let c = a ? o ? await this.getBootstrapGrant(o) : await this.createBootstrapGrant(a) : null;
|
|
586
368
|
return {
|
|
587
|
-
...
|
|
369
|
+
...F(s),
|
|
588
370
|
bootstrap_grant: c
|
|
589
371
|
};
|
|
590
372
|
}
|
|
@@ -593,194 +375,194 @@ var $ = class {
|
|
|
593
375
|
if (!t || !n || !r) throw Error("groupId, requestingDeviceId, and requestedDeviceId are required.");
|
|
594
376
|
if (n === r) throw Error("requesting and requested device ids must differ.");
|
|
595
377
|
if (i) {
|
|
596
|
-
let e =
|
|
378
|
+
let e = L();
|
|
597
379
|
if (await Q(this.db.prepare("UPDATE coordinator_reciprocal_approvals\n SET status = 'completed', resolved_at = ?\n WHERE request_id = ?\n AND group_id = ?\n AND requesting_device_id = ?\n AND requested_device_id = ?\n AND status = 'pending'").bind(e, a, t, r, n)) !== 1) throw new u();
|
|
598
|
-
return
|
|
380
|
+
return F(await Z(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(a)));
|
|
599
381
|
}
|
|
600
|
-
let o =
|
|
601
|
-
if (s) return
|
|
382
|
+
let o = R(n, r), s = await Z(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, n, r));
|
|
383
|
+
if (s) return F(s);
|
|
602
384
|
let c = await Z(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, n));
|
|
603
385
|
if (c) {
|
|
604
|
-
let e =
|
|
605
|
-
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, c.request_id).run(),
|
|
386
|
+
let e = L();
|
|
387
|
+
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, c.request_id).run(), F(await Z(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(c.request_id)));
|
|
606
388
|
}
|
|
607
|
-
let l =
|
|
389
|
+
let l = B(12), d = L();
|
|
608
390
|
try {
|
|
609
391
|
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(l, t, n, r, o.low, o.high, d).run();
|
|
610
392
|
} catch (e) {
|
|
611
|
-
if (!
|
|
393
|
+
if (!z(e)) throw e;
|
|
612
394
|
let i = await Z(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, n, r));
|
|
613
|
-
if (i) return
|
|
395
|
+
if (i) return F(i);
|
|
614
396
|
let a = await Z(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, n));
|
|
615
397
|
if (a) {
|
|
616
|
-
let e =
|
|
617
|
-
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, a.request_id).run(),
|
|
398
|
+
let e = L();
|
|
399
|
+
return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, a.request_id).run(), F(await Z(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(a.request_id)));
|
|
618
400
|
}
|
|
619
401
|
throw e;
|
|
620
402
|
}
|
|
621
|
-
return
|
|
403
|
+
return F(await Z(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(l)));
|
|
622
404
|
}
|
|
623
405
|
async createBootstrapGrant(e) {
|
|
624
|
-
let t =
|
|
625
|
-
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(n, t.groupId, t.seedDeviceId, t.workerDeviceId, t.expiresAt, r, t.createdBy).run(),
|
|
406
|
+
let t = M(e), n = B(12), r = L();
|
|
407
|
+
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(n, t.groupId, t.seedDeviceId, t.workerDeviceId, t.expiresAt, r, t.createdBy).run(), F(await Z(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(n)));
|
|
626
408
|
}
|
|
627
409
|
async getScope(e) {
|
|
628
410
|
let t = await Z(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));
|
|
629
|
-
return t ?
|
|
411
|
+
return t ? F(t) : null;
|
|
630
412
|
}
|
|
631
413
|
async getScopeMembership(e, t) {
|
|
632
414
|
let n = await Z(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));
|
|
633
|
-
return n ?
|
|
415
|
+
return n ? F(n) : null;
|
|
634
416
|
}
|
|
635
417
|
async createScope(e) {
|
|
636
|
-
let t =
|
|
418
|
+
let t = i(e);
|
|
637
419
|
if (await this.getScope(t.scopeId)) throw Error("scopeId already exists.");
|
|
638
|
-
let n =
|
|
420
|
+
let n = L();
|
|
639
421
|
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();
|
|
640
422
|
let r = await this.getScope(t.scopeId);
|
|
641
423
|
if (!r) throw Error("scope insert returned no row");
|
|
642
424
|
return r;
|
|
643
425
|
}
|
|
644
426
|
async updateScope(e) {
|
|
645
|
-
let t =
|
|
427
|
+
let t = h(e.scopeId), n = t ? await this.getScope(t) : null;
|
|
646
428
|
if (!n) return null;
|
|
647
|
-
let r =
|
|
648
|
-
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,
|
|
429
|
+
let r = S(e, n);
|
|
430
|
+
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, L(), r.scopeId).run(), await this.getScope(r.scopeId);
|
|
649
431
|
}
|
|
650
432
|
async listScopes(e = {}) {
|
|
651
|
-
let t = [], n = [], r =
|
|
433
|
+
let t = [], n = [], r = h(e.coordinatorId), i = h(e.groupId), a = h(e.status);
|
|
652
434
|
r && (t.push("coordinator_id = ?"), n.push(r)), i && (t.push("group_id = ?"), n.push(i)), a ? (t.push("status = ?"), n.push(a)) : e.includeInactive || t.push("status = 'active'");
|
|
653
435
|
let o = t.length ? `WHERE ${t.join(" AND ")}` : "", s = this.db.prepare(`SELECT scope_id, label, kind, authority_type, coordinator_id, group_id,
|
|
654
436
|
manifest_issuer_device_id, membership_epoch, manifest_hash, status, created_at, updated_at
|
|
655
437
|
FROM coordinator_scopes ${o}
|
|
656
438
|
ORDER BY coordinator_id ASC, group_id ASC, scope_id ASC`);
|
|
657
|
-
return (await X(n.length ? s.bind(...n) : s)).map((e) =>
|
|
658
|
-
}
|
|
659
|
-
async grantScopeMembership(
|
|
660
|
-
let n =
|
|
661
|
-
if (
|
|
662
|
-
let o =
|
|
663
|
-
if (!
|
|
664
|
-
if (
|
|
665
|
-
let
|
|
666
|
-
if (
|
|
667
|
-
let
|
|
668
|
-
await
|
|
669
|
-
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 ) SELECT ?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?\n WHERE NOT EXISTS (\n SELECT 1 FROM coordinator_scope_membership_effect_receipts WHERE effect_id = ?\n )\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(
|
|
670
|
-
|
|
439
|
+
return (await X(n.length ? s.bind(...n) : s)).map((e) => F(e));
|
|
440
|
+
}
|
|
441
|
+
async grantScopeMembership(t) {
|
|
442
|
+
let n = e(t.effectId), i = p(t), a = await K(this.db, n);
|
|
443
|
+
if (a) return d(a, "grant", i), s(a);
|
|
444
|
+
let o = h(t.scopeId), c = h(t.deviceId), l = o ? await this.getScope(o) : null;
|
|
445
|
+
if (!l) throw new f("scope_not_found");
|
|
446
|
+
if (l.status !== "active") throw new f("scope_inactive");
|
|
447
|
+
let u = o && c ? await this.getScopeMembership(o, c) : null, m = r(t, l, u);
|
|
448
|
+
if (m.groupId && !await this.getEnrollment(m.groupId, m.deviceId)) throw new f("device_not_enrolled");
|
|
449
|
+
let g = L();
|
|
450
|
+
await J(this.db, [
|
|
451
|
+
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 ) SELECT ?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?\n WHERE NOT EXISTS (\n SELECT 1 FROM coordinator_scope_membership_effect_receipts WHERE effect_id = ?\n )\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(m.scopeId, m.deviceId, m.role, m.membershipEpoch, m.coordinatorId, m.groupId, m.manifestIssuerDeviceId, m.manifestHash, m.signedManifestJson, g, n),
|
|
452
|
+
q(this.db, {
|
|
671
453
|
effectId: n,
|
|
672
|
-
requestJson:
|
|
673
|
-
scopeId:
|
|
674
|
-
deviceId:
|
|
675
|
-
createdAt:
|
|
454
|
+
requestJson: i,
|
|
455
|
+
scopeId: m.scopeId,
|
|
456
|
+
deviceId: m.deviceId,
|
|
457
|
+
createdAt: g
|
|
676
458
|
}),
|
|
677
459
|
G(this.db, {
|
|
678
460
|
effectId: n,
|
|
679
|
-
requestJson:
|
|
461
|
+
requestJson: i,
|
|
680
462
|
action: "grant",
|
|
681
|
-
previous:
|
|
682
|
-
scopeId:
|
|
683
|
-
deviceId:
|
|
463
|
+
previous: u,
|
|
464
|
+
scopeId: m.scopeId,
|
|
465
|
+
deviceId: m.deviceId,
|
|
684
466
|
status: "active",
|
|
685
|
-
membershipEpoch:
|
|
686
|
-
updatedAt:
|
|
687
|
-
actorType:
|
|
688
|
-
actorId:
|
|
689
|
-
createdAt:
|
|
467
|
+
membershipEpoch: m.membershipEpoch,
|
|
468
|
+
updatedAt: g,
|
|
469
|
+
actorType: m.actorType,
|
|
470
|
+
actorId: m.actorId,
|
|
471
|
+
createdAt: g
|
|
690
472
|
})
|
|
691
473
|
]);
|
|
692
|
-
let
|
|
693
|
-
if (!
|
|
694
|
-
return
|
|
695
|
-
}
|
|
696
|
-
async revokeScopeMembership(
|
|
697
|
-
let
|
|
698
|
-
if (!
|
|
699
|
-
let
|
|
700
|
-
if (
|
|
701
|
-
let
|
|
702
|
-
if (
|
|
703
|
-
let
|
|
704
|
-
if (
|
|
705
|
-
let
|
|
706
|
-
effectId:
|
|
707
|
-
requestJson:
|
|
708
|
-
scopeId:
|
|
709
|
-
deviceId:
|
|
710
|
-
createdAt:
|
|
711
|
-
}),
|
|
712
|
-
effectId:
|
|
713
|
-
requestJson:
|
|
474
|
+
let _ = await K(this.db, n);
|
|
475
|
+
if (!_) throw Error("scope membership grant was not applied.");
|
|
476
|
+
return d(_, "grant", i), s(_);
|
|
477
|
+
}
|
|
478
|
+
async revokeScopeMembership(n) {
|
|
479
|
+
let r = h(n.scopeId), i = h(n.deviceId);
|
|
480
|
+
if (!r || !i) throw Error("scopeId and deviceId are required.");
|
|
481
|
+
let a = e(n.effectId), o = v(n), s = await K(this.db, a);
|
|
482
|
+
if (s) return d(s, "revoke", o), s.outcome_applied === 1;
|
|
483
|
+
let c = n.membershipEpoch == null ? null : t(n.membershipEpoch), l = h(n.groupId), u = l ? await this.getScope(r) : null;
|
|
484
|
+
if (l && l !== u?.group_id) throw new f("scope_group_mismatch");
|
|
485
|
+
let p = await this.getScopeMembership(r, i);
|
|
486
|
+
if (c != null && p && c <= p.membership_epoch) throw Error("membershipEpoch must increase on revoke.");
|
|
487
|
+
let m = L(), g = c ?? (p?.membership_epoch ?? -1) + 1, _ = 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 = ?\n AND NOT EXISTS (\n SELECT 1 FROM coordinator_scope_membership_effect_receipts WHERE effect_id = ?\n )").bind(c, c, h(n.manifestHash), h(n.signedManifestJson), m, r, i, p?.membership_epoch ?? -1, p?.status ?? "", a), y = ne(this.db, {
|
|
488
|
+
effectId: a,
|
|
489
|
+
requestJson: o,
|
|
490
|
+
scopeId: r,
|
|
491
|
+
deviceId: i,
|
|
492
|
+
createdAt: m
|
|
493
|
+
}), b = G(this.db, {
|
|
494
|
+
effectId: a,
|
|
495
|
+
requestJson: o,
|
|
714
496
|
action: "revoke",
|
|
715
|
-
previous:
|
|
716
|
-
scopeId:
|
|
717
|
-
deviceId:
|
|
497
|
+
previous: p,
|
|
498
|
+
scopeId: r,
|
|
499
|
+
deviceId: i,
|
|
718
500
|
status: "revoked",
|
|
719
|
-
membershipEpoch:
|
|
720
|
-
updatedAt:
|
|
721
|
-
actorType:
|
|
722
|
-
actorId:
|
|
723
|
-
createdAt:
|
|
501
|
+
membershipEpoch: g,
|
|
502
|
+
updatedAt: m,
|
|
503
|
+
actorType: h(n.actorType),
|
|
504
|
+
actorId: h(n.actorId),
|
|
505
|
+
createdAt: m
|
|
724
506
|
});
|
|
725
507
|
try {
|
|
726
|
-
await
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
508
|
+
await J(this.db, [
|
|
509
|
+
_,
|
|
510
|
+
y,
|
|
511
|
+
b
|
|
730
512
|
]);
|
|
731
513
|
} catch (e) {
|
|
732
|
-
let
|
|
733
|
-
if (
|
|
514
|
+
let t = await this.getScopeMembership(r, i);
|
|
515
|
+
if (p && (!t || t.membership_epoch !== p.membership_epoch || t.status !== p.status)) return !1;
|
|
734
516
|
throw e;
|
|
735
517
|
}
|
|
736
|
-
let
|
|
737
|
-
if (!
|
|
738
|
-
return
|
|
518
|
+
let x = await K(this.db, a);
|
|
519
|
+
if (!x) throw Error("scope membership revoke receipt was not persisted.");
|
|
520
|
+
return d(x, "revoke", o), x.outcome_applied === 1;
|
|
739
521
|
}
|
|
740
522
|
async listScopeMemberships(e, t = !1) {
|
|
741
|
-
let n =
|
|
523
|
+
let n = h(e);
|
|
742
524
|
if (!n) throw Error("scopeId is required.");
|
|
743
525
|
let r = t ? "" : "AND status = 'active'";
|
|
744
526
|
return (await X(this.db.prepare(`SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,
|
|
745
527
|
manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at
|
|
746
528
|
FROM coordinator_scope_memberships
|
|
747
529
|
WHERE scope_id = ? ${r}
|
|
748
|
-
ORDER BY device_id ASC`).bind(n))).map((e) =>
|
|
530
|
+
ORDER BY device_id ASC`).bind(n))).map((e) => F(e));
|
|
749
531
|
}
|
|
750
532
|
async listDeviceScopeMemberships(e, t = !1) {
|
|
751
|
-
let n =
|
|
533
|
+
let n = h(e);
|
|
752
534
|
if (!n) throw Error("deviceId is required.");
|
|
753
535
|
let r = t ? "" : "AND status = 'active'";
|
|
754
536
|
return (await X(this.db.prepare(`SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,
|
|
755
537
|
manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at
|
|
756
538
|
FROM coordinator_scope_memberships
|
|
757
539
|
WHERE device_id = ? ${r}
|
|
758
|
-
ORDER BY scope_id ASC`).bind(n))).map((e) =>
|
|
540
|
+
ORDER BY scope_id ASC`).bind(n))).map((e) => F(e));
|
|
759
541
|
}
|
|
760
542
|
async listScopeMembershipAuditEvents(e) {
|
|
761
|
-
let t =
|
|
543
|
+
let t = h(e.scopeId);
|
|
762
544
|
if (!t) throw Error("scopeId is required.");
|
|
763
|
-
let
|
|
545
|
+
let r = h(e.deviceId), i = n(e.limit), a = r ? "scope_id = ? AND device_id = ?" : "scope_id = ?", o = r ? [
|
|
764
546
|
t,
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
] : [t,
|
|
547
|
+
r,
|
|
548
|
+
i
|
|
549
|
+
] : [t, i];
|
|
768
550
|
return (await X(this.db.prepare(`SELECT event_id, effect_id, action, scope_id, device_id, role, status, membership_epoch,
|
|
769
551
|
previous_role, previous_status, previous_membership_epoch,
|
|
770
552
|
coordinator_id, group_id, actor_type, actor_id, manifest_hash, created_at
|
|
771
553
|
FROM coordinator_scope_membership_audit_log
|
|
772
|
-
WHERE ${
|
|
554
|
+
WHERE ${a}
|
|
773
555
|
ORDER BY event_id ASC
|
|
774
|
-
LIMIT ?`).bind(...
|
|
556
|
+
LIMIT ?`).bind(...o))).map((e) => F(e));
|
|
775
557
|
}
|
|
776
558
|
async getBootstrapGrant(e) {
|
|
777
559
|
let t = await Z(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));
|
|
778
|
-
return t ?
|
|
560
|
+
return t ? F(t) : null;
|
|
779
561
|
}
|
|
780
562
|
async listBootstrapGrants(e) {
|
|
781
|
-
return (await X(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) =>
|
|
563
|
+
return (await X(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) => F(e));
|
|
782
564
|
}
|
|
783
|
-
async revokeBootstrapGrant(e, t =
|
|
565
|
+
async revokeBootstrapGrant(e, t = L()) {
|
|
784
566
|
return await Q(this.db.prepare("UPDATE coordinator_bootstrap_grants\n SET revoked_at = COALESCE(revoked_at, ?)\n WHERE grant_id = ?").bind(t, e)) > 0;
|
|
785
567
|
}
|
|
786
568
|
async listReciprocalApprovals(e) {
|
|
@@ -788,46 +570,46 @@ var $ = class {
|
|
|
788
570
|
return (await X(this.db.prepare(`SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at
|
|
789
571
|
FROM coordinator_reciprocal_approvals
|
|
790
572
|
WHERE group_id = ? AND ${t} = ? AND status = ?
|
|
791
|
-
ORDER BY created_at ASC, request_id ASC`).bind(e.groupId, e.deviceId, n))).map((e) =>
|
|
573
|
+
ORDER BY created_at ASC, request_id ASC`).bind(e.groupId, e.deviceId, n))).map((e) => F(e));
|
|
792
574
|
}
|
|
793
575
|
async createLegacyTeamCompletion(e, t) {
|
|
794
|
-
let [n] =
|
|
576
|
+
let [n] = _([e]);
|
|
795
577
|
if (!n) throw Error("completion_manifest_invalid");
|
|
796
578
|
let r = await this.getGroup(n);
|
|
797
579
|
if (!r) throw Error("group_not_found");
|
|
798
580
|
if (r.archived_at) throw Error("group_archived");
|
|
799
|
-
let i =
|
|
800
|
-
|
|
581
|
+
let i = C(t), a = JSON.parse(i);
|
|
582
|
+
b(a);
|
|
801
583
|
let o = await Z(this.db.prepare("SELECT manifest_json FROM coordinator_legacy_team_completions\n WHERE group_id = ? AND candidate_ref = ?").bind(n, a.candidate_ref));
|
|
802
584
|
if (o) {
|
|
803
|
-
if (o.manifest_json !== i) throw new
|
|
585
|
+
if (o.manifest_json !== i) throw new g();
|
|
804
586
|
return {
|
|
805
587
|
status: "existing",
|
|
806
|
-
manifest:
|
|
588
|
+
manifest: y(JSON.parse(o.manifest_json))
|
|
807
589
|
};
|
|
808
590
|
}
|
|
809
|
-
let s = await X(this.db.prepare("SELECT DISTINCT\n requested.scope_id,\n scope.authority_type,\n scope.coordinator_id,\n scope.group_id,\n scope.status\n FROM (\n SELECT json_extract(value, '$.scope_id') AS scope_id\n FROM json_each(?, '$.project_mappings')\n ) AS requested\n LEFT JOIN coordinator_scopes AS scope ON scope.scope_id = requested.scope_id").bind(i)), c =
|
|
591
|
+
let s = await X(this.db.prepare("SELECT DISTINCT\n requested.scope_id,\n scope.authority_type,\n scope.coordinator_id,\n scope.group_id,\n scope.status\n FROM (\n SELECT json_extract(value, '$.scope_id') AS scope_id\n FROM json_each(?, '$.project_mappings')\n ) AS requested\n LEFT JOIN coordinator_scopes AS scope ON scope.scope_id = requested.scope_id").bind(i)), c = w(a, n, s), l = await Q(this.db.prepare("INSERT OR IGNORE INTO coordinator_legacy_team_completions(\n group_id, candidate_ref, manifest_version, manifest_json, completed_at, created_at\n ) SELECT ?, ?, ?, ?, ?, ?\n FROM groups\n WHERE group_id = ? AND archived_at IS NULL\n AND NOT EXISTS (\n SELECT 1\n FROM json_each(?, '$.project_mappings') AS requested\n LEFT JOIN coordinator_scopes AS scope\n ON scope.scope_id = json_extract(requested.value, '$.scope_id')\n AND scope.authority_type = 'coordinator'\n AND scope.coordinator_id = ?\n AND scope.group_id = ?\n AND scope.status = 'active'\n WHERE scope.scope_id IS NULL\n )\n AND NOT EXISTS (\n SELECT 1 FROM enrolled_devices AS enrolled\n WHERE enrolled.group_id = ?\n AND NOT EXISTS (\n SELECT 1 FROM json_each(?, '$.device_decisions') AS requested\n WHERE json_extract(requested.value, '$.device_id') = enrolled.device_id\n AND json_extract(requested.value, '$.key_fingerprint') = enrolled.fingerprint\n AND json_extract(requested.value, '$.enabled') = enrolled.enabled\n )\n )\n AND NOT EXISTS (\n SELECT 1 FROM json_each(?, '$.device_decisions') AS requested\n WHERE json_extract(requested.value, '$.decision') = 'included'\n AND NOT EXISTS (\n SELECT 1 FROM enrolled_devices AS enrolled\n WHERE enrolled.group_id = ?\n AND enrolled.device_id = json_extract(requested.value, '$.device_id')\n AND enrolled.fingerprint = json_extract(requested.value, '$.key_fingerprint')\n AND enrolled.enabled = 1\n )\n )").bind(n, a.candidate_ref, a.version, i, a.completed_at, L(), n, i, c, n, n, i, i, n)), u = await Z(this.db.prepare("SELECT manifest_json FROM coordinator_legacy_team_completions\n WHERE group_id = ? AND candidate_ref = ?").bind(n, a.candidate_ref));
|
|
810
592
|
if (!u) {
|
|
811
593
|
let e = await this.getGroup(n);
|
|
812
594
|
if (!e) throw Error("group_not_found");
|
|
813
595
|
if (e.archived_at) throw Error("group_archived");
|
|
814
596
|
let t = await X(this.db.prepare("SELECT DISTINCT\n requested.scope_id,\n scope.authority_type,\n scope.coordinator_id,\n scope.group_id,\n scope.status\n FROM (\n SELECT json_extract(value, '$.scope_id') AS scope_id\n FROM json_each(?, '$.project_mappings')\n ) AS requested\n LEFT JOIN coordinator_scopes AS scope ON scope.scope_id = requested.scope_id").bind(i));
|
|
815
|
-
throw
|
|
597
|
+
throw w(a, n, t), Error("completion_manifest_unavailable");
|
|
816
598
|
}
|
|
817
|
-
if (u.manifest_json !== i) throw new
|
|
599
|
+
if (u.manifest_json !== i) throw new g();
|
|
818
600
|
return {
|
|
819
601
|
status: l === 1 ? "created" : "existing",
|
|
820
|
-
manifest:
|
|
602
|
+
manifest: y(JSON.parse(u.manifest_json))
|
|
821
603
|
};
|
|
822
604
|
}
|
|
823
|
-
async getLegacyTeamCompletion(
|
|
824
|
-
let [
|
|
825
|
-
if (!
|
|
826
|
-
let
|
|
827
|
-
return
|
|
605
|
+
async getLegacyTeamCompletion(e, t) {
|
|
606
|
+
let [n] = _([e]), r = j(t);
|
|
607
|
+
if (!n) throw Error("completion_manifest_invalid");
|
|
608
|
+
let i = await Z(this.db.prepare("SELECT manifest_json FROM coordinator_legacy_team_completions\n WHERE group_id = ? AND candidate_ref = ?").bind(n, r));
|
|
609
|
+
return i ? y(JSON.parse(i.manifest_json)) : null;
|
|
828
610
|
}
|
|
829
611
|
async listLegacyTeamCompletions(e) {
|
|
830
|
-
let t =
|
|
612
|
+
let t = _(e);
|
|
831
613
|
if (t.length === 0) return [];
|
|
832
614
|
let n = t.map(() => "?").join(", "), r = await Z(this.db.prepare(`SELECT
|
|
833
615
|
COUNT(*) AS record_count,
|
|
@@ -838,7 +620,7 @@ var $ = class {
|
|
|
838
620
|
FROM coordinator_legacy_team_completions
|
|
839
621
|
WHERE group_id IN (${n})`).bind(...t));
|
|
840
622
|
if (!r || r.record_count > 500 || r.batch_bytes > 375e5 || r.max_manifest_bytes > 15e5) throw Error("completion_results_too_large");
|
|
841
|
-
let
|
|
623
|
+
let i = await X(this.db.prepare(`WITH completion_stats AS (
|
|
842
624
|
SELECT
|
|
843
625
|
COUNT(*) AS record_count,
|
|
844
626
|
COALESCE(SUM(
|
|
@@ -853,20 +635,20 @@ var $ = class {
|
|
|
853
635
|
CROSS JOIN completion_stats
|
|
854
636
|
WHERE completions.group_id IN (${n})
|
|
855
637
|
AND completion_stats.record_count <= 500
|
|
856
|
-
AND completion_stats.batch_bytes <= ${
|
|
857
|
-
AND completion_stats.max_manifest_bytes <= ${
|
|
858
|
-
AND LENGTH(completions.manifest_json) <= ${
|
|
859
|
-
AND LENGTH(CAST(completions.manifest_json AS BLOB)) <= ${
|
|
638
|
+
AND completion_stats.batch_bytes <= ${E}
|
|
639
|
+
AND completion_stats.max_manifest_bytes <= ${x}
|
|
640
|
+
AND LENGTH(completions.manifest_json) <= ${x}
|
|
641
|
+
AND LENGTH(CAST(completions.manifest_json AS BLOB)) <= ${x}
|
|
860
642
|
ORDER BY completions.group_id, completions.completed_at, completions.candidate_ref
|
|
861
643
|
LIMIT 501`).bind(...t, ...t));
|
|
862
|
-
if (
|
|
863
|
-
return
|
|
644
|
+
if (i.length === 0 && r.record_count > 0 || i.length > 500 || i.reduce((e, t) => e + new TextEncoder().encode(t.group_id).byteLength + new TextEncoder().encode(t.manifest_json).byteLength, 0) > 375e5) throw Error("completion_results_too_large");
|
|
645
|
+
return i.map((e) => ({
|
|
864
646
|
group_id: e.group_id,
|
|
865
|
-
manifest:
|
|
647
|
+
manifest: y(JSON.parse(e.manifest_json))
|
|
866
648
|
}));
|
|
867
649
|
}
|
|
868
650
|
async upsertPresence(e) {
|
|
869
|
-
let t = /* @__PURE__ */ new Date(), n = new Date(t.getTime() + e.ttlS * 1e3).toISOString(), r =
|
|
651
|
+
let t = /* @__PURE__ */ new Date(), n = new Date(t.getTime() + e.ttlS * 1e3).toISOString(), r = c([], e.addresses);
|
|
870
652
|
return await this.db.prepare("INSERT INTO presence_records(group_id, device_id, addresses_json, last_seen_at, expires_at, capabilities_json)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(group_id, device_id) DO UPDATE SET\n addresses_json = excluded.addresses_json,\n last_seen_at = excluded.last_seen_at,\n expires_at = excluded.expires_at,\n capabilities_json = excluded.capabilities_json").bind(e.groupId, e.deviceId, JSON.stringify(r), t.toISOString(), n, JSON.stringify(e.capabilities ?? {})).run(), {
|
|
871
653
|
group_id: e.groupId,
|
|
872
654
|
device_id: e.deviceId,
|
|
@@ -875,14 +657,14 @@ var $ = class {
|
|
|
875
657
|
};
|
|
876
658
|
}
|
|
877
659
|
async listGroupPeers(e, t) {
|
|
878
|
-
let n =
|
|
660
|
+
let n = L();
|
|
879
661
|
return (await X(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) => {
|
|
880
662
|
let t = String(e.expires_at ?? "").trim(), r = !0;
|
|
881
663
|
if (t) {
|
|
882
664
|
let e = new Date(t);
|
|
883
665
|
r = Number.isNaN(e.getTime()) || e.toISOString() <= n;
|
|
884
666
|
}
|
|
885
|
-
let i = r ? [] :
|
|
667
|
+
let i = r ? [] : c([], JSON.parse(String(e.addresses_json ?? "[]")));
|
|
886
668
|
return {
|
|
887
669
|
device_id: String(e.device_id ?? ""),
|
|
888
670
|
public_key: String(e.public_key ?? ""),
|
|
@@ -899,18 +681,18 @@ var $ = class {
|
|
|
899
681
|
};
|
|
900
682
|
//#endregion
|
|
901
683
|
//#region src/d1-coordinator-runtime.ts
|
|
902
|
-
function
|
|
684
|
+
function re(e) {
|
|
903
685
|
let t = {
|
|
904
686
|
adminSecret: () => String(e.adminSecret ?? "").trim() || null,
|
|
905
687
|
now: e.now ?? (() => (/* @__PURE__ */ new Date()).toISOString())
|
|
906
688
|
};
|
|
907
|
-
return
|
|
689
|
+
return k({
|
|
908
690
|
storeFactory: () => new $(e.db),
|
|
909
691
|
runtime: t,
|
|
910
692
|
requestVerifier: e.requestVerifier
|
|
911
693
|
});
|
|
912
694
|
}
|
|
913
695
|
//#endregion
|
|
914
|
-
export {
|
|
696
|
+
export { A as COORDINATOR_LEGACY_TEAM_COMPLETION_CONFLICT, E as COORDINATOR_LEGACY_TEAM_COMPLETION_MAX_BATCH_BYTES, te as COORDINATOR_LEGACY_TEAM_COMPLETION_MAX_BATCH_RESPONSE_BYTES, x as COORDINATOR_LEGACY_TEAM_COMPLETION_MAX_BYTES, m as COORDINATOR_LEGACY_TEAM_COMPLETION_MAX_GROUPS, ee as COORDINATOR_LEGACY_TEAM_COMPLETION_MAX_RECORDS, O as COORDINATOR_LEGACY_TEAM_COMPLETION_VERSION, g as CoordinatorLegacyTeamCompletionConflictError, $ as D1CoordinatorStore, T as DEFAULT_TIME_WINDOW_S, C as canonicalCoordinatorLegacyTeamCompletionManifestJson, re as createD1CoordinatorApp, j as normalizeCoordinatorLegacyTeamCompletionCandidateRef, _ as normalizeCoordinatorLegacyTeamCompletionGroupIds, y as normalizeCoordinatorLegacyTeamCompletionManifest };
|
|
915
697
|
|
|
916
698
|
//# sourceMappingURL=cloudflare-coordinator.js.map
|