@codemem/core 0.39.0 → 0.40.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.
Files changed (99) hide show
  1. package/dist/api-types.d.ts +35 -1
  2. package/dist/api-types.d.ts.map +1 -1
  3. package/dist/better-sqlite-coordinator-store.d.ts +6 -2
  4. package/dist/better-sqlite-coordinator-store.d.ts.map +1 -1
  5. package/dist/coordinator-actions.d.ts +35 -0
  6. package/dist/coordinator-actions.d.ts.map +1 -1
  7. package/dist/{coordinator-api-hZ1RVJUN.js → coordinator-api-Btb6CEhw.js} +1204 -497
  8. package/dist/coordinator-api-Btb6CEhw.js.map +1 -0
  9. package/dist/coordinator-api.d.ts.map +1 -1
  10. package/dist/coordinator-invites.d.ts +13 -1
  11. package/dist/coordinator-invites.d.ts.map +1 -1
  12. package/dist/coordinator-membership-effects.d.ts +31 -0
  13. package/dist/coordinator-membership-effects.d.ts.map +1 -0
  14. package/dist/coordinator-store-contract.d.ts +127 -1
  15. package/dist/coordinator-store-contract.d.ts.map +1 -1
  16. package/dist/coordinator-store-test-harness.d.ts +3 -0
  17. package/dist/coordinator-store-test-harness.d.ts.map +1 -1
  18. package/dist/coordinator-store.d.ts +1 -1
  19. package/dist/coordinator-store.d.ts.map +1 -1
  20. package/dist/d1-coordinator-store.d.ts +6 -2
  21. package/dist/d1-coordinator-store.d.ts.map +1 -1
  22. package/dist/db.d.ts +1 -18
  23. package/dist/db.d.ts.map +1 -1
  24. package/dist/extraction-benchmark-scoring.d.ts +99 -0
  25. package/dist/extraction-benchmark-scoring.d.ts.map +1 -0
  26. package/dist/extraction-benchmarks.d.ts +29 -0
  27. package/dist/extraction-benchmarks.d.ts.map +1 -1
  28. package/dist/extraction-eval.d.ts +5 -0
  29. package/dist/extraction-eval.d.ts.map +1 -1
  30. package/dist/extraction-model-pricing.d.ts +21 -0
  31. package/dist/extraction-model-pricing.d.ts.map +1 -0
  32. package/dist/extraction-replay.d.ts +23 -2
  33. package/dist/extraction-replay.d.ts.map +1 -1
  34. package/dist/extraction-tier-routing.d.ts.map +1 -1
  35. package/dist/index.d.ts +51 -16
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +15017 -9210
  38. package/dist/index.js.map +1 -1
  39. package/dist/ingest-xml-parser.d.ts +17 -0
  40. package/dist/ingest-xml-parser.d.ts.map +1 -1
  41. package/dist/internal/cloudflare-coordinator.js +495 -220
  42. package/dist/internal/cloudflare-coordinator.js.map +1 -1
  43. package/dist/legacy-recipient-policy-projection.d.ts +122 -0
  44. package/dist/legacy-recipient-policy-projection.d.ts.map +1 -0
  45. package/dist/observer-client.d.ts +15 -6
  46. package/dist/observer-client.d.ts.map +1 -1
  47. package/dist/observer-config.d.ts +2 -0
  48. package/dist/observer-config.d.ts.map +1 -1
  49. package/dist/project-invite-acceptance.d.ts +10 -0
  50. package/dist/project-invite-acceptance.d.ts.map +1 -0
  51. package/dist/project-invite-identity.d.ts +14 -0
  52. package/dist/project-invite-identity.d.ts.map +1 -0
  53. package/dist/project-scope-settings.d.ts.map +1 -1
  54. package/dist/recipient-policy-contract.d.ts +153 -0
  55. package/dist/recipient-policy-contract.d.ts.map +1 -0
  56. package/dist/recipient-policy-edges.d.ts +85 -0
  57. package/dist/recipient-policy-edges.d.ts.map +1 -0
  58. package/dist/recipient-policy-intent.d.ts +12 -0
  59. package/dist/recipient-policy-intent.d.ts.map +1 -0
  60. package/dist/recipient-policy-migration.d.ts +22 -0
  61. package/dist/recipient-policy-migration.d.ts.map +1 -0
  62. package/dist/recipient-policy-onboarding.d.ts +111 -0
  63. package/dist/recipient-policy-onboarding.d.ts.map +1 -0
  64. package/dist/recipient-policy-reconciler.d.ts +69 -0
  65. package/dist/recipient-policy-reconciler.d.ts.map +1 -0
  66. package/dist/recipient-policy-reconciliation.d.ts +199 -0
  67. package/dist/recipient-policy-reconciliation.d.ts.map +1 -0
  68. package/dist/recipient-policy-review.d.ts +47 -0
  69. package/dist/recipient-policy-review.d.ts.map +1 -0
  70. package/dist/recipient-reviewed-intent.d.ts +63 -0
  71. package/dist/recipient-reviewed-intent.d.ts.map +1 -0
  72. package/dist/schema-bootstrap.d.ts.map +1 -1
  73. package/dist/schema.d.ts +5676 -1920
  74. package/dist/schema.d.ts.map +1 -1
  75. package/dist/scope-membership-cache.d.ts +1 -1
  76. package/dist/scope-membership-cache.d.ts.map +1 -1
  77. package/dist/share-operation-lifecycle.d.ts +44 -0
  78. package/dist/share-operation-lifecycle.d.ts.map +1 -0
  79. package/dist/share-operation.d.ts +85 -0
  80. package/dist/share-operation.d.ts.map +1 -0
  81. package/dist/share-provisioning.d.ts +57 -0
  82. package/dist/share-provisioning.d.ts.map +1 -0
  83. package/dist/store.d.ts +6 -3
  84. package/dist/store.d.ts.map +1 -1
  85. package/dist/sync-bootstrap.d.ts +3 -2
  86. package/dist/sync-bootstrap.d.ts.map +1 -1
  87. package/dist/sync-capability.d.ts +7 -0
  88. package/dist/sync-capability.d.ts.map +1 -1
  89. package/dist/sync-daemon.d.ts +14 -1
  90. package/dist/sync-daemon.d.ts.map +1 -1
  91. package/dist/sync-pass.d.ts +1 -0
  92. package/dist/sync-pass.d.ts.map +1 -1
  93. package/dist/sync-replication.d.ts +24 -0
  94. package/dist/sync-replication.d.ts.map +1 -1
  95. package/dist/sync-scope-protocol.d.ts.map +1 -1
  96. package/dist/test-schema.generated.d.ts +1 -1
  97. package/dist/test-schema.generated.d.ts.map +1 -1
  98. package/package.json +1 -1
  99. package/dist/coordinator-api-hZ1RVJUN.js.map +0 -1
@@ -1,10 +1,10 @@
1
- import { d as e, r as t, t as n } from "../coordinator-api-hZ1RVJUN.js";
1
+ import { A as e, D as t, F as n, M as r, N as i, O as a, P as o, S as s, b as c, h as l, j as u, k as d, n as f, t as p, v as m } from "../coordinator-api-Btb6CEhw.js";
2
2
  //#region src/d1-coordinator-store.ts
3
- function r(e) {
3
+ function h(e) {
4
4
  if (e == null) throw Error("expected row");
5
5
  return e;
6
6
  }
7
- function i(e) {
7
+ function g(e) {
8
8
  let t = e.trim();
9
9
  if (!t) return "";
10
10
  let n = t.includes("://") ? t : `http://${t}`;
@@ -15,7 +15,7 @@ function i(e) {
15
15
  return "";
16
16
  }
17
17
  }
18
- function a(e) {
18
+ function _(e) {
19
19
  if (!e) return "";
20
20
  try {
21
21
  let t = new URL(e), n = t.hostname.toLowerCase();
@@ -23,18 +23,18 @@ function a(e) {
23
23
  } catch {}
24
24
  return e;
25
25
  }
26
- function o(e, t) {
26
+ function v(e, t) {
27
27
  let n = [], r = /* @__PURE__ */ new Set();
28
- for (let o of [...e, ...t]) {
29
- let e = i(o), t = a(e);
28
+ for (let i of [...e, ...t]) {
29
+ let e = g(i), t = _(e);
30
30
  !e || r.has(t) || (r.add(t), n.push(e));
31
31
  }
32
32
  return n;
33
33
  }
34
- function s() {
34
+ function y() {
35
35
  return (/* @__PURE__ */ new Date()).toISOString();
36
36
  }
37
- function c(e, t) {
37
+ function b(e, t) {
38
38
  return e <= t ? {
39
39
  low: e,
40
40
  high: t
@@ -43,17 +43,22 @@ function c(e, t) {
43
43
  high: e
44
44
  };
45
45
  }
46
- function l(e) {
46
+ function x(e) {
47
47
  return e instanceof Error && /unique|constraint/i.test(e.message);
48
48
  }
49
- function u(e) {
49
+ function S(e) {
50
50
  let t = new Uint8Array(e);
51
51
  globalThis.crypto.getRandomValues(t);
52
52
  let n = [];
53
53
  for (let e of t) n.push("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"[e % 64] ?? "A");
54
54
  return n.join("");
55
55
  }
56
- function d(e) {
56
+ async function C(e) {
57
+ let t = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
58
+ return Array.from(new Uint8Array(t), (e) => e.toString(16).padStart(2, "0")).join("");
59
+ }
60
+ var w = "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", T = "group_id, device_id, public_key, fingerprint, identity_id, display_name, enabled, created_at";
61
+ function E(e) {
57
62
  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;
58
63
  if (!t || !n || !r || !i) throw Error("groupId, seedDeviceId, workerDeviceId, and expiresAt are required.");
59
64
  return {
@@ -64,95 +69,194 @@ function d(e) {
64
69
  createdBy: a
65
70
  };
66
71
  }
67
- function f(e) {
72
+ function D(e) {
68
73
  return e?.trim() || null;
69
74
  }
70
- function p(e, t = 0) {
75
+ async function O(e) {
76
+ let t = e.inviteKind ?? (D(e.operationId) ? "project_share" : "legacy_enrollment"), n = D(e.policyTeamId), r = D(e.targetIdentityId), i = D(e.reviewedPreviewDigest);
77
+ if (![
78
+ "legacy_enrollment",
79
+ "project_share",
80
+ "team_member",
81
+ "add_device"
82
+ ].includes(t)) throw Error("inviteKind is invalid.");
83
+ if ([n, r].filter((e) => !!e).some((e) => e.length > 256 || /[\p{Cc}\p{Cf}]/u.test(e))) throw Error("recipient invite identifier is invalid.");
84
+ if (i && !/^[a-f0-9]{64}$/u.test(i)) throw Error("reviewedPreviewDigest must be a SHA-256 digest.");
85
+ if (t === "project_share") {
86
+ if (!D(e.operationId)) throw Error("project_share invite requires operationId.");
87
+ if (n || r || i) throw Error("recipient invite metadata requires a recipient invite kind.");
88
+ } else if (t === "legacy_enrollment") {
89
+ if (D(e.operationId)) throw Error("legacy_enrollment invite cannot reference an operation.");
90
+ if (n || r || i) throw Error("recipient invite metadata requires a recipient invite kind.");
91
+ } else if (t === "team_member") {
92
+ if (!n || !i || r || D(e.operationId)) throw Error("team_member invite metadata is invalid.");
93
+ } else if (t === "add_device" && (!r || !i || n || D(e.operationId))) throw Error("add_device invite metadata is invalid.");
94
+ if (!(e.reviewedIntent !== void 0 && e.reviewedIntent !== null)) {
95
+ if (t === "team_member" || t === "add_device") throw Error("recipient_invite_review_unavailable");
96
+ return {
97
+ inviteKind: t,
98
+ policyTeamId: n,
99
+ targetIdentityId: r,
100
+ reviewedPreviewDigest: i,
101
+ reviewedIntentJson: null
102
+ };
103
+ }
104
+ let a;
105
+ if (t === "team_member" && n && i) a = {
106
+ kind: "team_member",
107
+ policyTeamId: n
108
+ };
109
+ else if (t === "add_device" && r && i) a = {
110
+ kind: "add_device",
111
+ targetIdentityId: r
112
+ };
113
+ else throw Error("recipient invite metadata requires a recipient invite kind.");
114
+ return await s(e.reviewedIntent, {
115
+ target: a,
116
+ digest: i
117
+ }), {
118
+ inviteKind: t,
119
+ policyTeamId: n,
120
+ targetIdentityId: r,
121
+ reviewedPreviewDigest: i,
122
+ reviewedIntentJson: m(e.reviewedIntent, a)
123
+ };
124
+ }
125
+ async function k(e) {
126
+ if (e.invite_kind === "team_member") {
127
+ if (!e.policy_team_id || !t(e.assigned_identity_id) || !e.reviewed_preview_digest) throw Error("invite_invalid");
128
+ let n = await c(e.reviewed_intent_json, {
129
+ target: {
130
+ kind: "team_member",
131
+ policyTeamId: e.policy_team_id
132
+ },
133
+ digest: e.reviewed_preview_digest
134
+ });
135
+ return {
136
+ kind: "team_member",
137
+ invite: e,
138
+ policy_team_id: e.policy_team_id,
139
+ assigned_identity_id: e.assigned_identity_id,
140
+ reviewed_preview_digest: e.reviewed_preview_digest,
141
+ reviewed_intent: n,
142
+ bound: !!e.consumed_at
143
+ };
144
+ }
145
+ if (e.invite_kind === "add_device") {
146
+ if (!e.target_identity_id || !e.reviewed_preview_digest) throw Error("invite_invalid");
147
+ let t = await c(e.reviewed_intent_json, {
148
+ target: {
149
+ kind: "add_device",
150
+ targetIdentityId: e.target_identity_id
151
+ },
152
+ digest: e.reviewed_preview_digest
153
+ });
154
+ return {
155
+ kind: "add_device",
156
+ invite: e,
157
+ target_identity_id: e.target_identity_id,
158
+ reviewed_preview_digest: e.reviewed_preview_digest,
159
+ reviewed_intent: t,
160
+ bound: !!e.consumed_at
161
+ };
162
+ }
163
+ return null;
164
+ }
165
+ function A(e, t = 0) {
71
166
  if (e == null) return t;
72
167
  if (!Number.isFinite(e) || e < 0) throw Error("membershipEpoch must be non-negative.");
73
168
  return Math.trunc(e);
74
169
  }
75
- function m(e) {
76
- let t = f(e.scopeId), n = f(e.label);
170
+ function j(e) {
171
+ let t = D(e.scopeId), n = D(e.label);
77
172
  if (!t || !n) throw Error("scopeId and label are required.");
78
173
  return {
79
174
  scopeId: t,
80
175
  label: n,
81
- kind: f(e.kind) ?? "user",
82
- authorityType: f(e.authorityType) ?? "coordinator",
83
- coordinatorId: f(e.coordinatorId),
84
- groupId: f(e.groupId),
85
- manifestIssuerDeviceId: f(e.manifestIssuerDeviceId),
86
- membershipEpoch: p(e.membershipEpoch),
87
- manifestHash: f(e.manifestHash),
88
- status: f(e.status) ?? "active"
176
+ kind: D(e.kind) ?? "user",
177
+ authorityType: D(e.authorityType) ?? "coordinator",
178
+ coordinatorId: D(e.coordinatorId),
179
+ groupId: D(e.groupId),
180
+ manifestIssuerDeviceId: D(e.manifestIssuerDeviceId),
181
+ membershipEpoch: A(e.membershipEpoch),
182
+ manifestHash: D(e.manifestHash),
183
+ status: D(e.status) ?? "active"
89
184
  };
90
185
  }
91
- function h(e, t, n) {
186
+ function M(e, t, n) {
92
187
  if (e === void 0) return t;
93
- let r = f(e);
188
+ let r = D(e);
94
189
  if (!r) throw Error(`${n} must not be empty.`);
95
190
  return r;
96
191
  }
97
- function g(e, t) {
98
- return e === void 0 ? t : f(e);
192
+ function N(e, t) {
193
+ return e === void 0 ? t : D(e);
99
194
  }
100
- function _(e, t) {
101
- let n = f(e.scopeId);
195
+ function P(e, t) {
196
+ let n = D(e.scopeId);
102
197
  if (!n) throw Error("scopeId is required.");
103
- let r = e.membershipEpoch == null ? null : p(e.membershipEpoch);
198
+ let r = e.membershipEpoch == null ? null : A(e.membershipEpoch);
104
199
  if (r != null && r < t.membership_epoch) throw Error("membershipEpoch must not move backwards.");
105
200
  return {
106
201
  scopeId: n,
107
- label: h(e.label, t.label, "label"),
108
- kind: h(e.kind, t.kind, "kind"),
109
- authorityType: h(e.authorityType, t.authority_type, "authorityType"),
110
- coordinatorId: g(e.coordinatorId, t.coordinator_id),
111
- groupId: g(e.groupId, t.group_id),
112
- manifestIssuerDeviceId: g(e.manifestIssuerDeviceId, t.manifest_issuer_device_id),
202
+ label: M(e.label, t.label, "label"),
203
+ kind: M(e.kind, t.kind, "kind"),
204
+ authorityType: M(e.authorityType, t.authority_type, "authorityType"),
205
+ coordinatorId: N(e.coordinatorId, t.coordinator_id),
206
+ groupId: N(e.groupId, t.group_id),
207
+ manifestIssuerDeviceId: N(e.manifestIssuerDeviceId, t.manifest_issuer_device_id),
113
208
  membershipEpoch: r ?? t.membership_epoch,
114
- manifestHash: g(e.manifestHash, t.manifest_hash),
115
- status: h(e.status, t.status, "status")
209
+ manifestHash: N(e.manifestHash, t.manifest_hash),
210
+ status: M(e.status, t.status, "status")
116
211
  };
117
212
  }
118
- function v(e, t, n) {
119
- let r = f(e.scopeId), i = f(e.deviceId);
120
- if (!r || !i) throw Error("scopeId and deviceId are required.");
121
- let a = f(e.coordinatorId), o = f(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 : p(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);
213
+ function F(t, n, r) {
214
+ let i = D(t.scopeId), a = D(t.deviceId);
215
+ if (!i || !a) throw Error("scopeId and deviceId are required.");
216
+ let o = D(t.coordinatorId), s = D(t.groupId);
217
+ if (o && o !== n?.coordinator_id) throw Error("membership coordinatorId must match the scope coordinatorId.");
218
+ if (s && s !== n?.group_id) throw new e("scope_group_mismatch");
219
+ let c = t.membershipEpoch == null ? null : A(t.membershipEpoch), l = n?.membership_epoch ?? 0;
220
+ if (c != null && c < l) throw Error("membershipEpoch must not be lower than the scope membershipEpoch.");
221
+ if (c != null && r && c < (r.status === "revoked" ? r.membership_epoch + 1 : r.membership_epoch)) throw Error("membershipEpoch must not move backwards.");
222
+ let u = c ?? (r ? Math.max(l, r.membership_epoch + +(r.status === "revoked")) : l);
128
223
  return {
129
- scopeId: r,
130
- deviceId: i,
131
- role: f(e.role) ?? "member",
132
- membershipEpoch: l,
133
- coordinatorId: t?.coordinator_id ?? null,
134
- groupId: t?.group_id ?? null,
135
- manifestIssuerDeviceId: f(e.manifestIssuerDeviceId) ?? t?.manifest_issuer_device_id ?? null,
136
- manifestHash: f(e.manifestHash) ?? t?.manifest_hash ?? null,
137
- signedManifestJson: f(e.signedManifestJson),
138
- actorType: f(e.actorType),
139
- actorId: f(e.actorId)
224
+ scopeId: i,
225
+ deviceId: a,
226
+ role: D(t.role) ?? "member",
227
+ membershipEpoch: u,
228
+ coordinatorId: n?.coordinator_id ?? null,
229
+ groupId: n?.group_id ?? null,
230
+ manifestIssuerDeviceId: D(t.manifestIssuerDeviceId) ?? n?.manifest_issuer_device_id ?? null,
231
+ manifestHash: D(t.manifestHash) ?? n?.manifest_hash ?? null,
232
+ signedManifestJson: D(t.signedManifestJson),
233
+ actorType: D(t.actorType),
234
+ actorId: D(t.actorId)
140
235
  };
141
236
  }
142
- function y(e) {
237
+ function I(e) {
143
238
  return e == null || !Number.isFinite(e) ? 100 : Math.max(1, Math.min(1e3, Math.trunc(e)));
144
239
  }
145
- function b(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);
240
+ function L(e, t) {
241
+ 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);
147
242
  }
148
- async function x(e, t) {
243
+ async function R(e, t) {
244
+ return await G(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));
245
+ }
246
+ function z(e, t) {
247
+ 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);
248
+ }
249
+ function B(e, t) {
250
+ 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);
251
+ }
252
+ async function V(e, t) {
149
253
  if (!e.batch) throw Error("D1 batch support is required for audited scope membership changes.");
150
254
  return await e.batch(t);
151
255
  }
152
- function S(e) {
256
+ function H(e) {
153
257
  return Number(e?.meta?.changes ?? 0);
154
258
  }
155
- function C(e) {
259
+ function U(e) {
156
260
  if (!e) return null;
157
261
  let t = String(e.seedDeviceId ?? "").trim(), n = String(e.expiresAt ?? "").trim(), r = String(e.createdBy ?? "").trim() || null;
158
262
  if (!t || !n) throw Error("bootstrapGrant.seedDeviceId and expiresAt are required.");
@@ -164,108 +268,245 @@ function C(e) {
164
268
  createdBy: r
165
269
  };
166
270
  }
167
- async function w(e) {
271
+ async function W(e) {
168
272
  let t = await e.all();
169
273
  return Array.isArray(t?.results) ? t.results : [];
170
274
  }
171
- async function T(e) {
275
+ async function G(e) {
172
276
  return await e.first();
173
277
  }
174
- async function E(e) {
278
+ async function K(e) {
175
279
  let t = await e.run();
176
280
  return Number(t?.meta?.changes ?? 0);
177
281
  }
178
- var D = class {
282
+ var q = class {
179
283
  db;
180
284
  constructor(e) {
181
285
  this.db = e;
182
286
  }
183
287
  async close() {}
184
288
  async createGroup(e, t) {
185
- await this.db.prepare("INSERT OR IGNORE INTO groups(group_id, display_name, archived_at, created_at) VALUES (?, ?, NULL, ?)").bind(e, t ?? null, s()).run();
289
+ await this.db.prepare("INSERT OR IGNORE INTO groups(group_id, display_name, archived_at, created_at) VALUES (?, ?, NULL, ?)").bind(e, t ?? null, y()).run();
186
290
  }
187
291
  async getGroup(e) {
188
- let t = await T(this.db.prepare("SELECT group_id, display_name, archived_at, created_at FROM groups WHERE group_id = ?").bind(e));
189
- return t ? r(t) : null;
292
+ let t = await G(this.db.prepare("SELECT group_id, display_name, archived_at, created_at FROM groups WHERE group_id = ?").bind(e));
293
+ return t ? h(t) : null;
190
294
  }
191
295
  async listGroups(e = !1) {
192
296
  let t = e ? "" : "WHERE archived_at IS NULL";
193
- return (await w(this.db.prepare(`SELECT group_id, display_name, archived_at, created_at FROM groups ${t} ORDER BY created_at ASC`))).map((e) => r(e));
297
+ return (await W(this.db.prepare(`SELECT group_id, display_name, archived_at, created_at FROM groups ${t} ORDER BY created_at ASC`))).map((e) => h(e));
194
298
  }
195
299
  async renameGroup(e, t) {
196
- return await E(this.db.prepare("UPDATE groups SET display_name = ? WHERE group_id = ?").bind(t, e)) > 0;
300
+ return await K(this.db.prepare("UPDATE groups SET display_name = ? WHERE group_id = ?").bind(t, e)) > 0;
197
301
  }
198
- async archiveGroup(e, t = s()) {
199
- return await E(this.db.prepare("UPDATE groups SET archived_at = ? WHERE group_id = ? AND archived_at IS NULL").bind(t, e)) > 0;
302
+ async archiveGroup(e, t = y()) {
303
+ return await K(this.db.prepare("UPDATE groups SET archived_at = ? WHERE group_id = ? AND archived_at IS NULL").bind(t, e)) > 0;
200
304
  }
201
305
  async unarchiveGroup(e) {
202
- return await E(this.db.prepare("UPDATE groups SET archived_at = NULL WHERE group_id = ? AND archived_at IS NOT NULL").bind(e)) > 0;
306
+ return await K(this.db.prepare("UPDATE groups SET archived_at = NULL WHERE group_id = ? AND archived_at IS NOT NULL").bind(e)) > 0;
203
307
  }
204
308
  async enrollDevice(e, t) {
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, s()).run();
309
+ if (await K(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, y())) === 0) throw Error("invite_identity_conflict");
206
310
  }
207
311
  async listEnrolledDevices(e, t) {
208
312
  let n = t ? "" : "AND enabled = 1";
209
- return (await w(this.db.prepare(`SELECT group_id, device_id, public_key, fingerprint, display_name, enabled, created_at
313
+ return (await W(this.db.prepare(`SELECT ${T}
210
314
  FROM enrolled_devices
211
315
  WHERE group_id = ? ${n}
212
- ORDER BY created_at ASC, device_id ASC`).bind(e))).map((e) => r(e));
316
+ ORDER BY created_at ASC, device_id ASC`).bind(e))).map((e) => h(e));
213
317
  }
214
- async getEnrollment(e, t) {
215
- let n = await T(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));
216
- return n ? r(n) : null;
318
+ async getEnrollment(e, t, n = !1) {
319
+ let r = n ? "" : "AND enabled = 1", i = await G(this.db.prepare(`SELECT ${T}
320
+ FROM enrolled_devices
321
+ WHERE group_id = ? AND device_id = ? ${r}`).bind(e, t));
322
+ return i ? h(i) : null;
217
323
  }
218
324
  async renameDevice(e, t, n) {
219
- return await E(this.db.prepare("UPDATE enrolled_devices SET display_name = ?\n WHERE group_id = ? AND device_id = ?").bind(n, e, t)) > 0;
325
+ return await K(this.db.prepare("UPDATE enrolled_devices SET display_name = ?\n WHERE group_id = ? AND device_id = ?").bind(n, e, t)) > 0;
220
326
  }
221
327
  async setDeviceEnabled(e, t, n) {
222
- return await E(this.db.prepare("UPDATE enrolled_devices SET enabled = ?\n WHERE group_id = ? AND device_id = ?").bind(+!!n, e, t)) > 0;
328
+ return await K(this.db.prepare("UPDATE enrolled_devices SET enabled = ?\n WHERE group_id = ? AND device_id = ?").bind(+!!n, e, t)) > 0;
223
329
  }
224
330
  async removeDevice(e, t) {
225
331
  if (!this.db.batch) throw Error("D1 batch support is required for atomic device removal.");
226
- return S((await this.db.batch([
332
+ return H((await this.db.batch([
227
333
  this.db.prepare("DELETE FROM presence_records WHERE group_id = ? AND device_id = ?").bind(e, t),
228
334
  this.db.prepare("DELETE FROM coordinator_reciprocal_approvals WHERE group_id = ? AND (requesting_device_id = ? OR requested_device_id = ?)").bind(e, t, t),
229
335
  this.db.prepare("DELETE FROM enrolled_devices WHERE group_id = ? AND device_id = ?").bind(e, t)
230
336
  ]))[2]) > 0;
231
337
  }
232
338
  async recordNonce(e, t, n) {
233
- return await E(this.db.prepare("INSERT OR IGNORE INTO request_nonces(device_id, nonce, created_at) VALUES (?, ?, ?)").bind(e, t, n)) > 0;
339
+ return await K(this.db.prepare("INSERT OR IGNORE INTO request_nonces(device_id, nonce, created_at) VALUES (?, ?, ?)").bind(e, t, n)) > 0;
234
340
  }
235
341
  async cleanupNonces(e) {
236
342
  await this.db.prepare("DELETE FROM request_nonces WHERE created_at < ?").bind(e).run();
237
343
  }
238
- async createInvite(t) {
239
- let n = s(), i = u(12), a = u(24), o = e(t.expiresAt), c = await this.getGroup(t.groupId);
240
- 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(i, t.groupId, a, t.policy, o, n, t.createdBy ?? null, c?.display_name ?? null).run(), r(await T(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(i)));
344
+ async createInvite(e) {
345
+ let t = y(), n = S(12), r = S(24), i = await C(r), o = a(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:${S(18)}` : null;
346
+ if (!!c != !!l) throw Error("operationId and reviewedProjectSetDigest must be provided together.");
347
+ let f = async () => {
348
+ if (!c) return null;
349
+ let t = await G(this.db.prepare(`SELECT ${w} FROM coordinator_invites WHERE operation_id = ?`).bind(c));
350
+ if (!t) return null;
351
+ if (t.consumed_at) throw Error("invite_already_bound");
352
+ 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");
353
+ return h(t);
354
+ }, p = async (n) => {
355
+ if (!n.revoked_at && n.expires_at > t) return n;
356
+ await K(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, o, t, e.createdBy ?? null, s?.display_name ?? null, c, n.token, t));
357
+ let a = await f();
358
+ if (!a) throw Error("invite_operation_reissue_failed");
359
+ return a;
360
+ };
361
+ if (c) {
362
+ let e = await f();
363
+ if (e) return await p(e);
364
+ }
365
+ try {
366
+ await this.db.prepare("INSERT INTO coordinator_invites(\n invite_id, group_id, token, policy, expires_at, created_at, created_by,\n team_name_snapshot, revoked_at, operation_id, reviewed_project_set_digest,\n token_digest, inviter_actor_id, inviter_display_name, inviter_device_id,\n pending_person_id, project_summaries_json, project_intent_json, trust_state,\n invite_kind, policy_team_id, target_identity_id, assigned_identity_id,\n reviewed_preview_digest, reviewed_intent_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").bind(n, e.groupId, r, e.policy, o, t, e.createdBy ?? null, s?.display_name ?? null, c, l, i, String(e.inviterActorId ?? "").trim() || null, String(e.inviterDisplayName ?? "").trim() || null, String(e.inviterDeviceId ?? "").trim() || null, String(e.pendingPersonId ?? "").trim() || null, e.projectSummaries ? JSON.stringify(e.projectSummaries) : null, e.projectIntent ? JSON.stringify(e.projectIntent) : null, c ? "pending" : null, u.inviteKind, u.policyTeamId, u.targetIdentityId, d, u.reviewedPreviewDigest, u.reviewedIntentJson).run();
367
+ } catch (e) {
368
+ if (c) {
369
+ let e = await f();
370
+ if (e) return await p(e);
371
+ }
372
+ throw e;
373
+ }
374
+ return h(await G(this.db.prepare(`SELECT ${w} FROM coordinator_invites WHERE invite_id = ?`).bind(n)));
241
375
  }
242
376
  async getInviteByToken(e) {
243
- let t = await T(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, s()));
244
- return t ? r(t) : null;
377
+ let t = await C(e), n = await G(this.db.prepare(`SELECT ${w}
378
+ FROM coordinator_invites
379
+ WHERE (token_digest = ? OR token = ?)
380
+ AND revoked_at IS NULL
381
+ AND expires_at > ?`).bind(t, e, y()));
382
+ return n ? h(n) : null;
383
+ }
384
+ async getInviteByTokenForInspection(e) {
385
+ let t = await C(e), n = await G(this.db.prepare(`SELECT ${w} FROM coordinator_invites WHERE token_digest = ? OR token = ?`).bind(t, e));
386
+ return n ? h(n) : null;
387
+ }
388
+ async inspectRecipientInvite(e) {
389
+ let t = await this.getInviteByTokenForInspection(e.token);
390
+ if (!t) return null;
391
+ let n = await k(t);
392
+ if (!n) return null;
393
+ if (t.revoked_at) throw Error("invite_invalid");
394
+ if (!t.consumed_at && new Date(t.expires_at) <= new Date(a(e.now))) throw Error("invite_expired");
395
+ let r = await this.getGroup(t.group_id);
396
+ if (!r) throw Error("group_not_found");
397
+ if (r.archived_at) throw Error("group_archived");
398
+ return n;
399
+ }
400
+ async consumeRecipientInvite(e) {
401
+ let t = a(e.now);
402
+ 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");
403
+ let n = await C(e.token), r = await this.getInviteByTokenForInspection(e.token), i = r ? await k(r) : null;
404
+ if (!r || !i || i.kind !== e.inviteKind || r.revoked_at) throw Error("invite_invalid");
405
+ let o = await this.getGroup(r.group_id);
406
+ if (!o) throw Error("group_not_found");
407
+ if (o.archived_at) throw Error("group_archived");
408
+ if (!r.consumed_at && new Date(r.expires_at) <= new Date(t)) throw Error("invite_expired");
409
+ if (l(e.publicKey) !== e.fingerprint) throw Error("fingerprint_mismatch");
410
+ let s = d(i);
411
+ if (s !== e.identityId) throw Error("invite_identity_conflict");
412
+ let c = r.bound_device_id === e.deviceId && r.bound_public_key === e.publicKey && r.bound_fingerprint === e.fingerprint;
413
+ if (r.consumed_at && !c) throw Error("invite_already_bound");
414
+ if (r.consumed_at && r.recipient_actor_id !== s) throw Error("invite_identity_conflict");
415
+ let u = await G(this.db.prepare(`SELECT ${T}
416
+ FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(r.group_id, e.deviceId));
417
+ if (u && (u.public_key !== e.publicKey || u.fingerprint !== e.fingerprint || u.identity_id !== null && u.identity_id !== s)) throw Error("invite_identity_conflict");
418
+ let f = 0;
419
+ if (!r.consumed_at) {
420
+ if (!this.db.batch) throw Error("D1 batch support is required for atomic invite consume.");
421
+ f = H((await this.db.batch([this.db.prepare("UPDATE coordinator_invites SET token = ?, consumed_at = ?, bound_device_id = ?,\n bound_public_key = ?, bound_fingerprint = ?, recipient_actor_id = ?\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:${r.invite_id}`, t, e.deviceId, e.publicKey, e.fingerprint, s, n, e.token, t, e.inviteKind, r.reviewed_intent_json, r.reviewed_preview_digest, s, s, e.deviceId, e.publicKey, e.fingerprint, s), 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, NULL, 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 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, e.publicKey, e.fingerprint, s)]))[0]);
422
+ }
423
+ let p = await this.getGroup(r.group_id);
424
+ if (!p) throw Error("group_not_found");
425
+ if (p.archived_at) throw Error("group_archived");
426
+ let m = await G(this.db.prepare(`SELECT ${T}
427
+ FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(r.group_id, e.deviceId));
428
+ if (m && (m.public_key !== e.publicKey || m.fingerprint !== e.fingerprint || m.identity_id !== null && m.identity_id !== s)) throw Error("invite_identity_conflict");
429
+ let h = await this.getInviteByTokenForInspection(e.token);
430
+ if (!h || h.revoked_at || !h.consumed_at && new Date(h.expires_at) <= new Date(t)) throw Error("invite_invalid");
431
+ let g = await k(h);
432
+ if (!g || g.kind !== e.inviteKind) throw Error("invite_invalid");
433
+ if (d(g) !== s) throw Error("invite_identity_conflict");
434
+ if (h.bound_device_id !== e.deviceId || h.bound_public_key !== e.publicKey || h.bound_fingerprint !== e.fingerprint) throw Error("invite_already_bound");
435
+ if (h.recipient_actor_id !== s) throw Error("invite_identity_conflict");
436
+ 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(s, h.group_id, e.deviceId, e.publicKey, e.fingerprint).run();
437
+ let _ = await this.getEnrollment(h.group_id, e.deviceId);
438
+ if (!_) throw Error("invite_acceptance_incomplete");
439
+ if (_.public_key !== e.publicKey || _.fingerprint !== e.fingerprint || _.identity_id !== s) throw Error("invite_identity_conflict");
440
+ return {
441
+ status: f === 1 ? "accepted" : "existing",
442
+ invite: h,
443
+ reviewed_intent: g.reviewed_intent
444
+ };
445
+ }
446
+ async consumeProjectInvite(e) {
447
+ if (!this.db.batch) throw Error("D1 batch support is required for atomic invite consume.");
448
+ let t = a(e.now), n = await C(e.token), r = await this.getInviteByTokenForInspection(e.token);
449
+ if (!r?.operation_id || !r.project_intent_json || r.revoked_at) throw Error("invite_invalid");
450
+ let i = await this.getGroup(r.group_id);
451
+ if (!i) throw Error("group_not_found");
452
+ if (i.archived_at) throw Error("group_archived");
453
+ if (r.operation_id !== e.operationId) throw Error("invite_invalid");
454
+ if (l(e.publicKey) !== e.fingerprint) throw Error("fingerprint_mismatch");
455
+ if (!r.consumed_at && new Date(r.expires_at) <= new Date(t)) throw Error("invite_expired");
456
+ let o = r.bound_device_id === e.deviceId && r.bound_public_key === e.publicKey && r.bound_fingerprint === e.fingerprint;
457
+ if (r.consumed_at && !o) throw Error("invite_already_bound");
458
+ 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");
459
+ let s = await G(this.db.prepare(`SELECT ${T}
460
+ FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(r.group_id, e.deviceId));
461
+ if (s && (s.public_key !== e.publicKey || s.fingerprint !== e.fingerprint)) throw Error("invite_identity_conflict");
462
+ let c = S(12), u = H((await this.db.batch([
463
+ 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),
464
+ this.db.prepare("INSERT INTO enrolled_devices(\n group_id, device_id, public_key, fingerprint, display_name, enabled, created_at\n ) SELECT i.group_id, i.bound_device_id, i.bound_public_key, i.bound_fingerprint,\n 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 display_name = excluded.display_name, enabled = 1").bind(t, n, e.token, e.deviceId, +!r.consumed_at),
465
+ 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(c, n, e.token, e.deviceId, t),
466
+ 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)
467
+ ]))[0]) === 1, d = await this.getGroup(r.group_id);
468
+ if (!d) throw Error("group_not_found");
469
+ if (d.archived_at) throw Error("group_archived");
470
+ let f = await this.getInviteByTokenForInspection(e.token);
471
+ if (!f) throw Error("invite_invalid");
472
+ if (f.bound_device_id !== e.deviceId || f.bound_public_key !== e.publicKey || f.bound_fingerprint !== e.fingerprint) throw Error("invite_already_bound");
473
+ if (f.recipient_actor_id !== e.recipientActorId || f.recipient_display_name !== e.recipientDisplayName || f.recipient_device_display_name !== e.deviceDisplayName) throw Error("invite_identity_conflict");
474
+ let p = await this.getEnrollment(f.group_id, e.deviceId);
475
+ if (!p) throw Error("invite_acceptance_incomplete");
476
+ let m = f.inviter_device_id ? await this.getEnrollment(f.group_id, f.inviter_device_id) : null, h = f.bootstrap_grant_id ? await this.getBootstrapGrant(f.bootstrap_grant_id) : null;
477
+ return {
478
+ status: u ? "accepted" : "existing",
479
+ invite: f,
480
+ enrollment: p,
481
+ seed_enrollment: m,
482
+ bootstrap_grant: h
483
+ };
245
484
  }
246
485
  async listInvites(e) {
247
- return (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 group_id = ?\n ORDER BY created_at DESC").bind(e))).map((e) => r(e));
486
+ return (await W(this.db.prepare(`SELECT ${w}
487
+ FROM coordinator_invites WHERE group_id = ?
488
+ ORDER BY created_at DESC`).bind(e))).map((e) => h(e));
248
489
  }
249
490
  async createJoinRequest(e) {
250
- let t = s(), n = u(12);
251
- 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(), r(await T(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)));
491
+ let t = y(), n = S(12);
492
+ 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(), h(await G(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)));
252
493
  }
253
494
  async listJoinRequests(e, t) {
254
495
  let n = t ?? "pending";
255
- return (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\n WHERE group_id = ? AND status = ?\n ORDER BY created_at ASC, device_id ASC").bind(e, n))).map((e) => r(e));
496
+ return (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\n WHERE group_id = ? AND status = ?\n ORDER BY created_at ASC, device_id ASC").bind(e, n))).map((e) => h(e));
256
497
  }
257
498
  async reviewJoinRequest(e) {
258
- let t = await T(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));
499
+ let t = await G(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));
259
500
  if (!t) return null;
260
501
  if (t.status !== "pending") return {
261
- ...r(t),
502
+ ...h(t),
262
503
  _no_transition: !0
263
504
  };
264
- let n = C(e.bootstrapGrant), i = s(), a = e.approved ? "approved" : "denied", o = null, c = null;
505
+ let n = U(e.bootstrapGrant), r = y(), i = e.approved ? "approved" : "denied", a = null, o = null;
265
506
  if (e.approved && n) {
266
- if (!await T(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.");
507
+ if (!await G(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.");
267
508
  if (n.seedDeviceId === t.device_id) throw Error("bootstrap grant seed and worker device ids must differ.");
268
- o = {
509
+ a = {
269
510
  ...n,
270
511
  groupId: t.group_id,
271
512
  workerDeviceId: t.device_id
@@ -273,10 +514,10 @@ var D = class {
273
514
  }
274
515
  if (this.db.batch) {
275
516
  let t = [];
276
- 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(a, i, 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(s(), e.requestId, i)), o)) {
277
- c = u(12);
278
- let n = s();
279
- 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(c, o.groupId, o.seedDeviceId, o.workerDeviceId, o.expiresAt, n, o.createdBy ?? null, e.requestId, i));
517
+ 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(y(), e.requestId, r)), a)) {
518
+ o = S(12);
519
+ let n = y();
520
+ 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));
280
521
  }
281
522
  await this.db.batch(t);
282
523
  } else {
@@ -286,182 +527,216 @@ var D = class {
286
527
  fingerprint: t.fingerprint,
287
528
  publicKey: t.public_key,
288
529
  displayName: (t.display_name ?? "").trim() || null
289
- }), o)) {
290
- let e = await this.createBootstrapGrant(o);
291
- n = e.grant_id, c = e.grant_id;
530
+ }), a)) {
531
+ let e = await this.createBootstrapGrant(a);
532
+ n = e.grant_id, o = e.grant_id;
292
533
  }
293
- if (await E(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) {
534
+ if (await K(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)) === 0) {
294
535
  n && await this.revokeBootstrapGrant(n);
295
- let t = await T(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));
536
+ let t = await G(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));
296
537
  return t ? {
297
- ...r(t),
538
+ ...h(t),
298
539
  _no_transition: !0
299
540
  } : null;
300
541
  }
301
542
  }
302
- let l = await T(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));
303
- if (!l) return null;
304
- let d = o ? c ? await this.getBootstrapGrant(c) : await this.createBootstrapGrant(o) : null;
543
+ let s = await G(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));
544
+ if (!s) return null;
545
+ let c = a ? o ? await this.getBootstrapGrant(o) : await this.createBootstrapGrant(a) : null;
305
546
  return {
306
- ...r(l),
307
- bootstrap_grant: d
547
+ ...h(s),
548
+ bootstrap_grant: c
308
549
  };
309
550
  }
310
551
  async createReciprocalApproval(e) {
311
- let t = e.groupId.trim(), n = e.requestingDeviceId.trim(), i = e.requestedDeviceId.trim();
312
- if (!t || !n || !i) throw Error("groupId, requestingDeviceId, and requestedDeviceId are required.");
313
- if (n === i) throw Error("requesting and requested device ids must differ.");
314
- let a = c(n, i), o = await T(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, i));
315
- if (o) return r(o);
316
- let d = await T(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, n));
317
- if (d) {
318
- let e = s();
319
- return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, d.request_id).run(), r(await T(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)));
552
+ let t = e.groupId.trim(), n = e.requestingDeviceId.trim(), r = e.requestedDeviceId.trim();
553
+ if (!t || !n || !r) throw Error("groupId, requestingDeviceId, and requestedDeviceId are required.");
554
+ if (n === r) throw Error("requesting and requested device ids must differ.");
555
+ let i = b(n, r), a = await G(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));
556
+ if (a) return h(a);
557
+ let o = await G(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));
558
+ if (o) {
559
+ let e = y();
560
+ return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, o.request_id).run(), h(await G(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(o.request_id)));
320
561
  }
321
- let f = u(12), p = s();
562
+ let s = S(12), c = y();
322
563
  try {
323
- 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, n, i, a.low, a.high, p).run();
564
+ 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(s, t, n, r, i.low, i.high, c).run();
324
565
  } catch (e) {
325
- if (!l(e)) throw e;
326
- let a = await T(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, i));
327
- if (a) return r(a);
328
- let o = await T(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, n));
329
- if (o) {
330
- let e = s();
331
- return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, o.request_id).run(), r(await T(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(o.request_id)));
566
+ if (!x(e)) throw e;
567
+ let i = await G(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));
568
+ if (i) return h(i);
569
+ let a = await G(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));
570
+ if (a) {
571
+ let e = y();
572
+ return await this.db.prepare("UPDATE coordinator_reciprocal_approvals SET status = 'completed', resolved_at = ? WHERE request_id = ?").bind(e, a.request_id).run(), h(await G(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)));
332
573
  }
333
574
  throw e;
334
575
  }
335
- return r(await T(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)));
576
+ return h(await G(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)));
336
577
  }
337
578
  async createBootstrapGrant(e) {
338
- let t = d(e), n = u(12), i = s();
339
- 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, i, t.createdBy).run(), r(await T(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)));
579
+ let t = E(e), n = S(12), r = y();
580
+ 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(), h(await G(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)));
340
581
  }
341
582
  async getScope(e) {
342
- let t = await T(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));
343
- return t ? r(t) : null;
583
+ let t = await G(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));
584
+ return t ? h(t) : null;
344
585
  }
345
586
  async getScopeMembership(e, t) {
346
- let n = await T(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));
347
- return n ? r(n) : null;
587
+ let n = await G(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));
588
+ return n ? h(n) : null;
348
589
  }
349
590
  async createScope(e) {
350
- let t = m(e);
591
+ let t = j(e);
351
592
  if (await this.getScope(t.scopeId)) throw Error("scopeId already exists.");
352
- let n = s();
593
+ let n = y();
353
594
  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();
354
595
  let r = await this.getScope(t.scopeId);
355
596
  if (!r) throw Error("scope insert returned no row");
356
597
  return r;
357
598
  }
358
599
  async updateScope(e) {
359
- let t = f(e.scopeId), n = t ? await this.getScope(t) : null;
600
+ let t = D(e.scopeId), n = t ? await this.getScope(t) : null;
360
601
  if (!n) return null;
361
- let r = _(e, n);
362
- 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, s(), r.scopeId).run(), await this.getScope(r.scopeId);
602
+ let r = P(e, n);
603
+ 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, y(), r.scopeId).run(), await this.getScope(r.scopeId);
363
604
  }
364
605
  async listScopes(e = {}) {
365
- let t = [], n = [], i = f(e.coordinatorId), a = f(e.groupId), o = f(e.status);
366
- i && (t.push("coordinator_id = ?"), n.push(i)), a && (t.push("group_id = ?"), n.push(a)), o ? (t.push("status = ?"), n.push(o)) : e.includeInactive || t.push("status = 'active'");
367
- let s = t.length ? `WHERE ${t.join(" AND ")}` : "", c = this.db.prepare(`SELECT scope_id, label, kind, authority_type, coordinator_id, group_id,
606
+ let t = [], n = [], r = D(e.coordinatorId), i = D(e.groupId), a = D(e.status);
607
+ 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'");
608
+ let o = t.length ? `WHERE ${t.join(" AND ")}` : "", s = this.db.prepare(`SELECT scope_id, label, kind, authority_type, coordinator_id, group_id,
368
609
  manifest_issuer_device_id, membership_epoch, manifest_hash, status, created_at, updated_at
369
- FROM coordinator_scopes ${s}
610
+ FROM coordinator_scopes ${o}
370
611
  ORDER BY coordinator_id ASC, group_id ASC, scope_id ASC`);
371
- return (await w(n.length ? c.bind(...n) : c)).map((e) => r(e));
372
- }
373
- async grantScopeMembership(e) {
374
- let t = f(e.scopeId), n = f(e.deviceId), i = t ? await this.getScope(t) : null;
375
- if (!i) throw Error("scopeId must reference an existing scope.");
376
- let a = t && n ? await this.getScopeMembership(t, n) : null, o = v(e, i, a);
377
- if (o.groupId && !await this.getEnrollment(o.groupId, o.deviceId)) throw Error("device must be enrolled and enabled in the scope group.");
378
- let c = s();
379
- if (S((await x(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(o.scopeId, o.deviceId, o.role, o.membershipEpoch, o.coordinatorId, o.groupId, o.manifestIssuerDeviceId, o.manifestHash, o.signedManifestJson, c), b(this.db, {
380
- action: "grant",
381
- previous: a,
382
- scopeId: o.scopeId,
383
- deviceId: o.deviceId,
384
- status: "active",
385
- membershipEpoch: o.membershipEpoch,
386
- updatedAt: c,
387
- actorType: o.actorType,
388
- actorId: o.actorId,
389
- createdAt: c
390
- })]))[0]) <= 0) throw Error("scope membership grant was not applied.");
391
- return r(await T(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(o.scopeId, o.deviceId)));
392
- }
393
- async revokeScopeMembership(e) {
394
- let t = f(e.scopeId), n = f(e.deviceId);
395
- if (!t || !n) throw Error("scopeId and deviceId are required.");
396
- let r = e.membershipEpoch == null ? null : p(e.membershipEpoch), i = await this.getScopeMembership(t, n);
397
- if (!i) return !1;
398
- if (r != null && i && r <= i.membership_epoch) throw Error("membershipEpoch must increase on revoke.");
399
- let a = s(), o = 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, f(e.manifestHash), f(e.signedManifestJson), a, t, n, i.membership_epoch, i.status), l = b(this.db, {
612
+ return (await W(n.length ? s.bind(...n) : s)).map((e) => h(e));
613
+ }
614
+ async grantScopeMembership(t) {
615
+ let n = o(t.effectId), a = r(t), s = await R(this.db, n);
616
+ if (s) return u(s, "grant", a), i(s);
617
+ let c = D(t.scopeId), l = D(t.deviceId), d = c ? await this.getScope(c) : null;
618
+ if (!d) throw new e("scope_not_found");
619
+ if (d.status !== "active") throw new e("scope_inactive");
620
+ let f = c && l ? await this.getScopeMembership(c, l) : null, p = F(t, d, f);
621
+ if (p.groupId && !await this.getEnrollment(p.groupId, p.deviceId)) throw new e("device_not_enrolled");
622
+ let m = y();
623
+ await V(this.db, [
624
+ 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(p.scopeId, p.deviceId, p.role, p.membershipEpoch, p.coordinatorId, p.groupId, p.manifestIssuerDeviceId, p.manifestHash, p.signedManifestJson, m, n),
625
+ z(this.db, {
626
+ effectId: n,
627
+ requestJson: a,
628
+ scopeId: p.scopeId,
629
+ deviceId: p.deviceId,
630
+ createdAt: m
631
+ }),
632
+ L(this.db, {
633
+ effectId: n,
634
+ requestJson: a,
635
+ action: "grant",
636
+ previous: f,
637
+ scopeId: p.scopeId,
638
+ deviceId: p.deviceId,
639
+ status: "active",
640
+ membershipEpoch: p.membershipEpoch,
641
+ updatedAt: m,
642
+ actorType: p.actorType,
643
+ actorId: p.actorId,
644
+ createdAt: m
645
+ })
646
+ ]);
647
+ let h = await R(this.db, n);
648
+ if (!h) throw Error("scope membership grant was not applied.");
649
+ return u(h, "grant", a), i(h);
650
+ }
651
+ async revokeScopeMembership(t) {
652
+ let r = D(t.scopeId), i = D(t.deviceId);
653
+ if (!r || !i) throw Error("scopeId and deviceId are required.");
654
+ let a = o(t.effectId), s = n(t), c = await R(this.db, a);
655
+ if (c) return u(c, "revoke", s), c.outcome_applied === 1;
656
+ let l = t.membershipEpoch == null ? null : A(t.membershipEpoch), d = D(t.groupId), f = d ? await this.getScope(r) : null;
657
+ if (d && d !== f?.group_id) throw new e("scope_group_mismatch");
658
+ let p = await this.getScopeMembership(r, i);
659
+ if (l != null && p && l <= p.membership_epoch) throw Error("membershipEpoch must increase on revoke.");
660
+ let m = y(), h = l ?? (p?.membership_epoch ?? -1) + 1, g = 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(l, l, D(t.manifestHash), D(t.signedManifestJson), m, r, i, p?.membership_epoch ?? -1, p?.status ?? "", a), _ = B(this.db, {
661
+ effectId: a,
662
+ requestJson: s,
663
+ scopeId: r,
664
+ deviceId: i,
665
+ createdAt: m
666
+ }), v = L(this.db, {
667
+ effectId: a,
668
+ requestJson: s,
400
669
  action: "revoke",
401
- previous: i,
402
- scopeId: t,
403
- deviceId: n,
670
+ previous: p,
671
+ scopeId: r,
672
+ deviceId: i,
404
673
  status: "revoked",
405
- membershipEpoch: o,
406
- updatedAt: a,
407
- actorType: f(e.actorType),
408
- actorId: f(e.actorId),
409
- createdAt: a
410
- }), u;
674
+ membershipEpoch: h,
675
+ updatedAt: m,
676
+ actorType: D(t.actorType),
677
+ actorId: D(t.actorId),
678
+ createdAt: m
679
+ });
411
680
  try {
412
- u = await x(this.db, [c, l]);
681
+ await V(this.db, [
682
+ g,
683
+ _,
684
+ v
685
+ ]);
413
686
  } catch (e) {
414
- let r = await this.getScopeMembership(t, n);
415
- if (!r || r.membership_epoch !== i.membership_epoch || r.status !== i.status) return !1;
687
+ let t = await this.getScopeMembership(r, i);
688
+ if (p && (!t || t.membership_epoch !== p.membership_epoch || t.status !== p.status)) return !1;
416
689
  throw e;
417
690
  }
418
- return !(S(u[0]) <= 0);
691
+ let b = await R(this.db, a);
692
+ if (!b) throw Error("scope membership revoke receipt was not persisted.");
693
+ return u(b, "revoke", s), b.outcome_applied === 1;
419
694
  }
420
695
  async listScopeMemberships(e, t = !1) {
421
- let n = f(e);
696
+ let n = D(e);
422
697
  if (!n) throw Error("scopeId is required.");
423
- let i = t ? "" : "AND status = 'active'";
424
- return (await w(this.db.prepare(`SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,
698
+ let r = t ? "" : "AND status = 'active'";
699
+ return (await W(this.db.prepare(`SELECT scope_id, device_id, role, status, membership_epoch, coordinator_id, group_id,
425
700
  manifest_issuer_device_id, manifest_hash, signed_manifest_json, updated_at
426
701
  FROM coordinator_scope_memberships
427
- WHERE scope_id = ? ${i}
428
- ORDER BY device_id ASC`).bind(n))).map((e) => r(e));
702
+ WHERE scope_id = ? ${r}
703
+ ORDER BY device_id ASC`).bind(n))).map((e) => h(e));
429
704
  }
430
705
  async listScopeMembershipAuditEvents(e) {
431
- let t = f(e.scopeId);
706
+ let t = D(e.scopeId);
432
707
  if (!t) throw Error("scopeId is required.");
433
- let n = f(e.deviceId), i = y(e.limit), a = n ? "scope_id = ? AND device_id = ?" : "scope_id = ?", o = n ? [
708
+ let n = D(e.deviceId), r = I(e.limit), i = n ? "scope_id = ? AND device_id = ?" : "scope_id = ?", a = n ? [
434
709
  t,
435
710
  n,
436
- i
437
- ] : [t, i];
438
- return (await w(this.db.prepare(`SELECT event_id, action, scope_id, device_id, role, status, membership_epoch,
711
+ r
712
+ ] : [t, r];
713
+ return (await W(this.db.prepare(`SELECT event_id, effect_id, action, scope_id, device_id, role, status, membership_epoch,
439
714
  previous_role, previous_status, previous_membership_epoch,
440
715
  coordinator_id, group_id, actor_type, actor_id, manifest_hash, created_at
441
716
  FROM coordinator_scope_membership_audit_log
442
- WHERE ${a}
717
+ WHERE ${i}
443
718
  ORDER BY event_id ASC
444
- LIMIT ?`).bind(...o))).map((e) => r(e));
719
+ LIMIT ?`).bind(...a))).map((e) => h(e));
445
720
  }
446
721
  async getBootstrapGrant(e) {
447
- let t = await T(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));
448
- return t ? r(t) : null;
722
+ let t = await G(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));
723
+ return t ? h(t) : null;
449
724
  }
450
725
  async listBootstrapGrants(e) {
451
- return (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 group_id = ?\n ORDER BY created_at DESC, grant_id DESC").bind(e))).map((e) => r(e));
726
+ return (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 group_id = ?\n ORDER BY created_at DESC, grant_id DESC").bind(e))).map((e) => h(e));
452
727
  }
453
- async revokeBootstrapGrant(e, t = s()) {
454
- return await E(this.db.prepare("UPDATE coordinator_bootstrap_grants\n SET revoked_at = COALESCE(revoked_at, ?)\n WHERE grant_id = ?").bind(t, e)) > 0;
728
+ async revokeBootstrapGrant(e, t = y()) {
729
+ return await K(this.db.prepare("UPDATE coordinator_bootstrap_grants\n SET revoked_at = COALESCE(revoked_at, ?)\n WHERE grant_id = ?").bind(t, e)) > 0;
455
730
  }
456
731
  async listReciprocalApprovals(e) {
457
732
  let t = e.direction === "incoming" ? "requested_device_id" : "requesting_device_id", n = e.status?.trim() || "pending";
458
- return (await w(this.db.prepare(`SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at
733
+ return (await W(this.db.prepare(`SELECT request_id, group_id, requesting_device_id, requested_device_id, status, created_at, resolved_at
459
734
  FROM coordinator_reciprocal_approvals
460
735
  WHERE group_id = ? AND ${t} = ? AND status = ?
461
- ORDER BY created_at ASC, request_id ASC`).bind(e.groupId, e.deviceId, n))).map((e) => r(e));
736
+ ORDER BY created_at ASC, request_id ASC`).bind(e.groupId, e.deviceId, n))).map((e) => h(e));
462
737
  }
463
738
  async upsertPresence(e) {
464
- let t = /* @__PURE__ */ new Date(), n = new Date(t.getTime() + e.ttlS * 1e3).toISOString(), r = o([], e.addresses);
739
+ let t = /* @__PURE__ */ new Date(), n = new Date(t.getTime() + e.ttlS * 1e3).toISOString(), r = v([], e.addresses);
465
740
  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(), {
466
741
  group_id: e.groupId,
467
742
  device_id: e.deviceId,
@@ -470,14 +745,14 @@ var D = class {
470
745
  };
471
746
  }
472
747
  async listGroupPeers(e, t) {
473
- let n = s();
474
- return (await w(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) => {
748
+ let n = y();
749
+ return (await W(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) => {
475
750
  let t = String(e.expires_at ?? "").trim(), r = !0;
476
751
  if (t) {
477
752
  let e = new Date(t);
478
753
  r = Number.isNaN(e.getTime()) || e.toISOString() <= n;
479
754
  }
480
- let i = r ? [] : o([], JSON.parse(String(e.addresses_json ?? "[]")));
755
+ let i = r ? [] : v([], JSON.parse(String(e.addresses_json ?? "[]")));
481
756
  return {
482
757
  device_id: String(e.device_id ?? ""),
483
758
  public_key: String(e.public_key ?? ""),
@@ -494,9 +769,9 @@ var D = class {
494
769
  };
495
770
  //#endregion
496
771
  //#region src/d1-coordinator-runtime.ts
497
- function O(e) {
498
- return n({
499
- storeFactory: () => new D(e.db),
772
+ function J(e) {
773
+ return p({
774
+ storeFactory: () => new q(e.db),
500
775
  runtime: {
501
776
  adminSecret: () => String(e.adminSecret ?? "").trim() || null,
502
777
  now: e.now ?? (() => (/* @__PURE__ */ new Date()).toISOString())
@@ -505,6 +780,6 @@ function O(e) {
505
780
  });
506
781
  }
507
782
  //#endregion
508
- export { D as D1CoordinatorStore, t as DEFAULT_TIME_WINDOW_S, O as createD1CoordinatorApp };
783
+ export { q as D1CoordinatorStore, f as DEFAULT_TIME_WINDOW_S, J as createD1CoordinatorApp };
509
784
 
510
785
  //# sourceMappingURL=cloudflare-coordinator.js.map