@codemem/core 0.40.2 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-types.d.ts +17 -0
- package/dist/api-types.d.ts.map +1 -1
- package/dist/claude-hooks.d.ts +12 -4
- package/dist/claude-hooks.d.ts.map +1 -1
- package/dist/codex-hooks.d.ts +7 -3
- package/dist/codex-hooks.d.ts.map +1 -1
- package/dist/coordinator-actions.d.ts.map +1 -1
- package/dist/coordinator-api-SeLosPIq.js +3102 -0
- package/dist/coordinator-api-SeLosPIq.js.map +1 -0
- package/dist/coordinator-api.d.ts.map +1 -1
- package/dist/coordinator-runtime.d.ts.map +1 -1
- package/dist/db.d.ts +9 -3
- package/dist/db.d.ts.map +1 -1
- package/dist/device-identity-binding.d.ts +50 -0
- package/dist/device-identity-binding.d.ts.map +1 -0
- package/dist/device-identity-inventory.d.ts +72 -0
- package/dist/device-identity-inventory.d.ts.map +1 -0
- package/dist/hook-transcript.d.ts +25 -0
- package/dist/hook-transcript.d.ts.map +1 -0
- package/dist/identity-target.d.ts +16 -0
- package/dist/identity-target.d.ts.map +1 -0
- package/dist/index.d.ts +27 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24492 -4337
- package/dist/index.js.map +1 -1
- package/dist/internal/cloudflare-coordinator.js +159 -159
- package/dist/operational-status.d.ts +36 -0
- package/dist/operational-status.d.ts.map +1 -0
- package/dist/policy-team-device-eligibility.d.ts +51 -0
- package/dist/policy-team-device-eligibility.d.ts.map +1 -0
- package/dist/project-invite-identity.d.ts +2 -0
- package/dist/project-invite-identity.d.ts.map +1 -1
- package/dist/project-share-intent.d.ts +16 -0
- package/dist/project-share-intent.d.ts.map +1 -0
- package/dist/prompt-transport.d.ts +36 -0
- package/dist/prompt-transport.d.ts.map +1 -0
- package/dist/raw-event-flush.d.ts +1 -0
- package/dist/raw-event-flush.d.ts.map +1 -1
- package/dist/raw-event-ingest.d.ts +19 -0
- package/dist/raw-event-ingest.d.ts.map +1 -0
- package/dist/raw-event-sweeper.d.ts +6 -1
- package/dist/raw-event-sweeper.d.ts.map +1 -1
- package/dist/recipient-policy-edges.d.ts.map +1 -1
- package/dist/recipient-policy-intent.d.ts.map +1 -1
- package/dist/recipient-policy-onboarding.d.ts +3 -1
- package/dist/recipient-policy-onboarding.d.ts.map +1 -1
- package/dist/recipient-policy-reconciliation.d.ts +10 -1
- package/dist/recipient-policy-reconciliation.d.ts.map +1 -1
- package/dist/release-discovery.d.ts +47 -0
- package/dist/release-discovery.d.ts.map +1 -0
- package/dist/schema-bootstrap.d.ts +9 -0
- package/dist/schema-bootstrap.d.ts.map +1 -1
- package/dist/schema.d.ts +1625 -344
- package/dist/schema.d.ts.map +1 -1
- package/dist/scope-membership-cache.d.ts +2 -0
- package/dist/scope-membership-cache.d.ts.map +1 -1
- package/dist/share-operation.d.ts +4 -15
- package/dist/share-operation.d.ts.map +1 -1
- package/dist/store.d.ts +2 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/sync-auth.d.ts +65 -2
- package/dist/sync-auth.d.ts.map +1 -1
- package/dist/sync-bootstrap-constants.d.ts +7 -0
- package/dist/sync-bootstrap-constants.d.ts.map +1 -0
- package/dist/sync-bootstrap.d.ts +4 -11
- package/dist/sync-bootstrap.d.ts.map +1 -1
- package/dist/sync-daemon.d.ts +2 -2
- package/dist/sync-daemon.d.ts.map +1 -1
- package/dist/sync-http-client.d.ts +1 -0
- package/dist/sync-http-client.d.ts.map +1 -1
- package/dist/sync-identity.d.ts +10 -2
- package/dist/sync-identity.d.ts.map +1 -1
- package/dist/sync-pass.d.ts +1 -0
- package/dist/sync-pass.d.ts.map +1 -1
- package/dist/sync-replication.d.ts.map +1 -1
- package/dist/sync-scope-protocol.d.ts +1 -3
- package/dist/sync-scope-protocol.d.ts.map +1 -1
- package/dist/test-schema.generated.d.ts +1 -1
- package/dist/test-schema.generated.d.ts.map +1 -1
- package/dist/viewer-probe.d.ts +50 -0
- package/dist/viewer-probe.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/coordinator-api-CvU8oTg1.js +0 -21107
- package/dist/coordinator-api-CvU8oTg1.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as e, D as t, G as n, H as r, K as i, R as a, U as o, V as s, W as c, j as l, k as u, n as d, t as f, w as p, z as m } from "../coordinator-api-SeLosPIq.js";
|
|
2
2
|
//#region src/d1-coordinator-store.ts
|
|
3
3
|
function h(e) {
|
|
4
4
|
if (e == null) throw Error("expected row");
|
|
@@ -92,7 +92,7 @@ function k(e) {
|
|
|
92
92
|
return e?.trim() || null;
|
|
93
93
|
}
|
|
94
94
|
async function A(e) {
|
|
95
|
-
let n = e.inviteKind ?? (k(e.operationId) ? "project_share" : "legacy_enrollment"), r = k(e.policyTeamId), i = k(e.targetIdentityId),
|
|
95
|
+
let n = e.inviteKind ?? (k(e.operationId) ? "project_share" : "legacy_enrollment"), r = k(e.policyTeamId), i = k(e.targetIdentityId), a = k(e.reviewedPreviewDigest);
|
|
96
96
|
if (![
|
|
97
97
|
"legacy_enrollment",
|
|
98
98
|
"project_share",
|
|
@@ -100,83 +100,83 @@ async function A(e) {
|
|
|
100
100
|
"add_device"
|
|
101
101
|
].includes(n)) throw Error("inviteKind is invalid.");
|
|
102
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 (
|
|
103
|
+
if (a && !/^[a-f0-9]{64}$/u.test(a)) throw Error("reviewedPreviewDigest must be a SHA-256 digest.");
|
|
104
104
|
if (n === "project_share") {
|
|
105
105
|
if (!k(e.operationId)) throw Error("project_share invite requires operationId.");
|
|
106
|
-
if (r || i ||
|
|
106
|
+
if (r || i || a) throw Error("recipient invite metadata requires a recipient invite kind.");
|
|
107
107
|
} else if (n === "legacy_enrollment") {
|
|
108
108
|
if (k(e.operationId)) throw Error("legacy_enrollment invite cannot reference an operation.");
|
|
109
|
-
if (r || i ||
|
|
109
|
+
if (r || i || a) throw Error("recipient invite metadata requires a recipient invite kind.");
|
|
110
110
|
} else if (n === "team_member") {
|
|
111
|
-
if (!r || !
|
|
112
|
-
} else if (n === "add_device" && (!i || !
|
|
111
|
+
if (!r || !a || i || k(e.operationId)) throw Error("team_member invite metadata is invalid.");
|
|
112
|
+
} else if (n === "add_device" && (!i || !a || r || k(e.operationId))) throw Error("add_device invite metadata is invalid.");
|
|
113
113
|
if (!(e.reviewedIntent !== void 0 && e.reviewedIntent !== null)) {
|
|
114
114
|
if (n === "team_member" || n === "add_device") throw Error("recipient_invite_review_unavailable");
|
|
115
115
|
return {
|
|
116
116
|
inviteKind: n,
|
|
117
117
|
policyTeamId: r,
|
|
118
118
|
targetIdentityId: i,
|
|
119
|
-
reviewedPreviewDigest:
|
|
119
|
+
reviewedPreviewDigest: a,
|
|
120
120
|
reviewedIntentJson: null
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
let
|
|
124
|
-
if (n === "team_member" && r &&
|
|
123
|
+
let o;
|
|
124
|
+
if (n === "team_member" && r && a) o = {
|
|
125
125
|
kind: "team_member",
|
|
126
126
|
policyTeamId: r
|
|
127
127
|
};
|
|
128
|
-
else if (n === "add_device" && i &&
|
|
128
|
+
else if (n === "add_device" && i && a) o = {
|
|
129
129
|
kind: "add_device",
|
|
130
130
|
targetIdentityId: i
|
|
131
131
|
};
|
|
132
132
|
else throw Error("recipient invite metadata requires a recipient invite kind.");
|
|
133
|
-
return await
|
|
134
|
-
target:
|
|
135
|
-
digest:
|
|
133
|
+
return await l(e.reviewedIntent, {
|
|
134
|
+
target: o,
|
|
135
|
+
digest: a
|
|
136
136
|
}), {
|
|
137
137
|
inviteKind: n,
|
|
138
138
|
policyTeamId: r,
|
|
139
139
|
targetIdentityId: i,
|
|
140
|
-
reviewedPreviewDigest:
|
|
141
|
-
reviewedIntentJson: t(e.reviewedIntent,
|
|
140
|
+
reviewedPreviewDigest: a,
|
|
141
|
+
reviewedIntentJson: t(e.reviewedIntent, o)
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
|
-
async function j(
|
|
145
|
-
if (
|
|
146
|
-
if (!
|
|
147
|
-
let
|
|
144
|
+
async function j(e) {
|
|
145
|
+
if (e.invite_kind === "team_member") {
|
|
146
|
+
if (!e.policy_team_id || !a(e.assigned_identity_id) || !e.reviewed_preview_digest) throw Error("invite_invalid");
|
|
147
|
+
let t = await u(e.reviewed_intent_json, {
|
|
148
148
|
target: {
|
|
149
149
|
kind: "team_member",
|
|
150
|
-
policyTeamId:
|
|
150
|
+
policyTeamId: e.policy_team_id
|
|
151
151
|
},
|
|
152
|
-
digest:
|
|
152
|
+
digest: e.reviewed_preview_digest
|
|
153
153
|
});
|
|
154
154
|
return {
|
|
155
155
|
kind: "team_member",
|
|
156
|
-
invite:
|
|
157
|
-
policy_team_id:
|
|
158
|
-
assigned_identity_id:
|
|
159
|
-
reviewed_preview_digest:
|
|
160
|
-
reviewed_intent:
|
|
161
|
-
bound: !!
|
|
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
162
|
};
|
|
163
163
|
}
|
|
164
|
-
if (
|
|
165
|
-
if (!
|
|
166
|
-
let
|
|
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 u(e.reviewed_intent_json, {
|
|
167
167
|
target: {
|
|
168
168
|
kind: "add_device",
|
|
169
|
-
targetIdentityId:
|
|
169
|
+
targetIdentityId: e.target_identity_id
|
|
170
170
|
},
|
|
171
|
-
digest:
|
|
171
|
+
digest: e.reviewed_preview_digest
|
|
172
172
|
});
|
|
173
173
|
return {
|
|
174
174
|
kind: "add_device",
|
|
175
|
-
invite:
|
|
176
|
-
target_identity_id:
|
|
177
|
-
reviewed_preview_digest:
|
|
178
|
-
reviewed_intent:
|
|
179
|
-
bound: !!
|
|
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
180
|
};
|
|
181
181
|
}
|
|
182
182
|
return null;
|
|
@@ -230,18 +230,18 @@ function I(e, t) {
|
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
232
|
function L(e, t, n) {
|
|
233
|
-
let
|
|
234
|
-
if (!
|
|
235
|
-
let
|
|
236
|
-
if (
|
|
237
|
-
if (
|
|
233
|
+
let r = k(e.scopeId), i = k(e.deviceId);
|
|
234
|
+
if (!r || !i) throw Error("scopeId and deviceId are required.");
|
|
235
|
+
let a = k(e.coordinatorId), o = k(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 s("scope_group_mismatch");
|
|
238
238
|
let c = e.membershipEpoch == null ? null : M(e.membershipEpoch), l = t?.membership_epoch ?? 0;
|
|
239
239
|
if (c != null && c < l) throw Error("membershipEpoch must not be lower than the scope membershipEpoch.");
|
|
240
240
|
if (c != null && n && c < (n.status === "revoked" ? n.membership_epoch + 1 : n.membership_epoch)) throw Error("membershipEpoch must not move backwards.");
|
|
241
241
|
let u = c ?? (n ? Math.max(l, n.membership_epoch + +(n.status === "revoked")) : l);
|
|
242
242
|
return {
|
|
243
|
-
scopeId:
|
|
244
|
-
deviceId:
|
|
243
|
+
scopeId: r,
|
|
244
|
+
deviceId: i,
|
|
245
245
|
role: k(e.role) ?? "member",
|
|
246
246
|
membershipEpoch: u,
|
|
247
247
|
coordinatorId: t?.coordinator_id ?? null,
|
|
@@ -364,32 +364,32 @@ var Y = class {
|
|
|
364
364
|
await this.db.prepare("DELETE FROM request_nonces WHERE created_at < ?").bind(e).run();
|
|
365
365
|
}
|
|
366
366
|
async createInvite(e) {
|
|
367
|
-
let t = b(), n = C(12), r = C(24), i = await w(r), a =
|
|
367
|
+
let t = b(), n = C(12), r = C(24), i = await w(r), a = m(e.expiresAt), o = await this.getGroup(e.groupId), s = String(e.operationId ?? "").trim() || null, c = String(e.reviewedProjectSetDigest ?? "").trim() || null, l = await A(e), u = l.inviteKind === "team_member" ? `identity:${C(18)}` : null;
|
|
368
368
|
if (!!s != !!c) throw Error("operationId and reviewedProjectSetDigest must be provided together.");
|
|
369
|
-
let
|
|
369
|
+
let d = async () => {
|
|
370
370
|
if (!s) return null;
|
|
371
371
|
let t = await q(this.db.prepare(`SELECT ${T} FROM coordinator_invites WHERE operation_id = ?`).bind(s));
|
|
372
372
|
if (!t) return null;
|
|
373
373
|
if (t.consumed_at) throw Error("invite_already_bound");
|
|
374
|
-
if (t.group_id !== e.groupId || t.policy !== e.policy || t.invite_kind !==
|
|
374
|
+
if (t.group_id !== e.groupId || t.policy !== e.policy || t.invite_kind !== l.inviteKind || t.reviewed_project_set_digest !== c || 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 !== l.policyTeamId || t.target_identity_id !== l.targetIdentityId || t.reviewed_preview_digest !== l.reviewedPreviewDigest || t.reviewed_intent_json !== l.reviewedIntentJson) throw Error("invite_operation_intent_conflict");
|
|
375
375
|
return h(t);
|
|
376
|
-
},
|
|
376
|
+
}, f = async (n) => {
|
|
377
377
|
if (!n.revoked_at && n.expires_at > t) return n;
|
|
378
378
|
await J(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, o?.display_name ?? null, s, n.token, t));
|
|
379
|
-
let c = await
|
|
379
|
+
let c = await d();
|
|
380
380
|
if (!c) throw Error("invite_operation_reissue_failed");
|
|
381
381
|
return c;
|
|
382
382
|
};
|
|
383
383
|
if (s) {
|
|
384
|
-
let e = await
|
|
385
|
-
if (e) return await
|
|
384
|
+
let e = await d();
|
|
385
|
+
if (e) return await f(e);
|
|
386
386
|
}
|
|
387
387
|
try {
|
|
388
|
-
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, a, t, e.createdBy ?? null, o?.display_name ?? null, s, c, 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, s ? "pending" : null,
|
|
388
|
+
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, a, t, e.createdBy ?? null, o?.display_name ?? null, s, c, 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, s ? "pending" : null, l.inviteKind, l.policyTeamId, l.targetIdentityId, u, l.reviewedPreviewDigest, l.reviewedIntentJson).run();
|
|
389
389
|
} catch (e) {
|
|
390
390
|
if (s) {
|
|
391
|
-
let e = await
|
|
392
|
-
if (e) return await
|
|
391
|
+
let e = await d();
|
|
392
|
+
if (e) return await f(e);
|
|
393
393
|
}
|
|
394
394
|
throw e;
|
|
395
395
|
}
|
|
@@ -413,69 +413,69 @@ var Y = class {
|
|
|
413
413
|
let n = await j(t);
|
|
414
414
|
if (!n) return null;
|
|
415
415
|
if (t.revoked_at) throw Error("invite_invalid");
|
|
416
|
-
if (!t.consumed_at && new Date(t.expires_at) <= new Date(
|
|
416
|
+
if (!t.consumed_at && new Date(t.expires_at) <= new Date(m(e.now))) throw Error("invite_expired");
|
|
417
417
|
let r = await this.getGroup(t.group_id);
|
|
418
418
|
if (!r) throw Error("group_not_found");
|
|
419
419
|
if (r.archived_at) throw Error("group_archived");
|
|
420
420
|
return n;
|
|
421
421
|
}
|
|
422
|
-
async consumeRecipientInvite(
|
|
423
|
-
let
|
|
424
|
-
if (!
|
|
425
|
-
let
|
|
426
|
-
if (!
|
|
427
|
-
let
|
|
428
|
-
if (!
|
|
429
|
-
if (
|
|
430
|
-
if (!
|
|
431
|
-
if (
|
|
432
|
-
let
|
|
433
|
-
if (
|
|
434
|
-
let u =
|
|
435
|
-
if (
|
|
436
|
-
if (
|
|
437
|
-
let
|
|
438
|
-
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(
|
|
439
|
-
if (
|
|
440
|
-
let
|
|
441
|
-
if (!
|
|
422
|
+
async consumeRecipientInvite(t) {
|
|
423
|
+
let n = m(t.now), r = t.recipientDisplayName ?? null, i = t.deviceDisplayName ?? null;
|
|
424
|
+
if (!t.identityId || !t.deviceId || !t.publicKey || !t.fingerprint || t.identityId !== t.identityId.trim() || t.deviceId !== t.deviceId.trim() || t.identityId.length > 256 || t.deviceId.length > 256 || /[\p{Cc}\p{Cf}]/u.test(t.identityId) || /[\p{Cc}\p{Cf}]/u.test(t.deviceId)) throw Error("invite_identity_conflict");
|
|
425
|
+
let a = await w(t.token), o = await this.getInviteByTokenForInspection(t.token), s = o ? await j(o) : null;
|
|
426
|
+
if (!o || !s || s.kind !== t.inviteKind || o.revoked_at) throw Error("invite_invalid");
|
|
427
|
+
let c = await this.getGroup(o.group_id);
|
|
428
|
+
if (!c) throw Error("group_not_found");
|
|
429
|
+
if (c.archived_at) throw Error("group_archived");
|
|
430
|
+
if (!o.consumed_at && new Date(o.expires_at) <= new Date(n)) throw Error("invite_expired");
|
|
431
|
+
if (p(t.publicKey) !== t.fingerprint) throw Error("fingerprint_mismatch");
|
|
432
|
+
let l = e(s);
|
|
433
|
+
if (l !== t.identityId) throw Error("invite_identity_conflict");
|
|
434
|
+
let u = o.bound_device_id === t.deviceId && o.bound_public_key === t.publicKey && o.bound_fingerprint === t.fingerprint;
|
|
435
|
+
if (o.consumed_at && !u) throw Error("invite_already_bound");
|
|
436
|
+
if (o.consumed_at && o.recipient_actor_id !== l) throw Error("invite_identity_conflict");
|
|
437
|
+
let d = await q(this.db.prepare(`SELECT ${E}
|
|
438
|
+
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(o.group_id, t.deviceId));
|
|
439
|
+
if (d && (d.public_key !== t.publicKey || d.fingerprint !== t.fingerprint || d.identity_id !== null && d.identity_id !== l)) throw Error("invite_identity_conflict");
|
|
440
|
+
let f = 0, h = C(12);
|
|
441
|
+
if (!o.consumed_at) {
|
|
442
442
|
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(
|
|
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(h,
|
|
447
|
-
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(
|
|
443
|
+
f = W((await this.db.batch([
|
|
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:${o.invite_id}`, n, t.deviceId, t.publicKey, t.fingerprint, l, r, i, a, t.token, n, t.inviteKind, o.reviewed_intent_json, o.reviewed_preview_digest, l, l, t.deviceId, t.publicKey, t.fingerprint, l),
|
|
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(n, a, t.token, t.deviceId, t.publicKey, t.fingerprint, l),
|
|
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(h, a, t.token, n),
|
|
447
|
+
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(n, a, t.token, t.deviceId)
|
|
448
448
|
]))[0]);
|
|
449
449
|
}
|
|
450
|
-
let g = await this.getGroup(
|
|
450
|
+
let g = await this.getGroup(o.group_id);
|
|
451
451
|
if (!g) throw Error("group_not_found");
|
|
452
452
|
if (g.archived_at) throw Error("group_archived");
|
|
453
453
|
let _ = await q(this.db.prepare(`SELECT ${E}
|
|
454
|
-
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(
|
|
455
|
-
if (_ && (_.public_key !==
|
|
456
|
-
let v = await this.getInviteByTokenForInspection(
|
|
457
|
-
if (!v || v.revoked_at || !v.consumed_at && new Date(v.expires_at) <= new Date(
|
|
454
|
+
FROM enrolled_devices WHERE group_id = ? AND device_id = ?`).bind(o.group_id, t.deviceId));
|
|
455
|
+
if (_ && (_.public_key !== t.publicKey || _.fingerprint !== t.fingerprint || _.identity_id !== null && _.identity_id !== l)) throw Error("invite_identity_conflict");
|
|
456
|
+
let v = await this.getInviteByTokenForInspection(t.token);
|
|
457
|
+
if (!v || v.revoked_at || !v.consumed_at && new Date(v.expires_at) <= new Date(n)) throw Error("invite_invalid");
|
|
458
458
|
let y = await j(v);
|
|
459
|
-
if (!y || y.kind !==
|
|
460
|
-
if (
|
|
461
|
-
if (v.bound_device_id !==
|
|
462
|
-
if (v.recipient_actor_id !==
|
|
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 b = await this.getEnrollment(v.group_id,
|
|
459
|
+
if (!y || y.kind !== t.inviteKind) throw Error("invite_invalid");
|
|
460
|
+
if (e(y) !== l) throw Error("invite_identity_conflict");
|
|
461
|
+
if (v.bound_device_id !== t.deviceId || v.bound_public_key !== t.publicKey || v.bound_fingerprint !== t.fingerprint) throw Error("invite_already_bound");
|
|
462
|
+
if (v.recipient_actor_id !== l) throw Error("invite_identity_conflict");
|
|
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(l, v.group_id, t.deviceId, t.publicKey, t.fingerprint).run();
|
|
464
|
+
let b = await this.getEnrollment(v.group_id, t.deviceId);
|
|
465
465
|
if (!b) throw Error("invite_acceptance_incomplete");
|
|
466
|
-
if (b.public_key !==
|
|
466
|
+
if (b.public_key !== t.publicKey || b.fingerprint !== t.fingerprint || b.identity_id !== l) throw Error("invite_identity_conflict");
|
|
467
467
|
let x = v;
|
|
468
|
-
if (y.kind === "add_device" && v.inviter_device_id && !v.bootstrap_grant_id && new Date(v.expires_at) > new Date(
|
|
468
|
+
if (y.kind === "add_device" && v.inviter_device_id && !v.bootstrap_grant_id && new Date(v.expires_at) > new Date(n)) {
|
|
469
469
|
if (!this.db.batch) throw Error("D1 batch support is required for atomic bootstrap grant recovery.");
|
|
470
|
-
let
|
|
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(
|
|
472
|
-
let r = await this.getInviteByTokenForInspection(
|
|
470
|
+
let e = C(12);
|
|
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(e, v.invite_id, t.deviceId, l, n), 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(n, v.invite_id, t.deviceId)]);
|
|
472
|
+
let r = await this.getInviteByTokenForInspection(t.token);
|
|
473
473
|
if (!r) throw Error("invite_invalid");
|
|
474
474
|
x = r;
|
|
475
475
|
}
|
|
476
476
|
let S = x.bootstrap_grant_id ? await this.getBootstrapGrant(x.bootstrap_grant_id) : null;
|
|
477
477
|
return {
|
|
478
|
-
status:
|
|
478
|
+
status: f === 1 ? "accepted" : "existing",
|
|
479
479
|
invite: x,
|
|
480
480
|
reviewed_intent: y.reviewed_intent,
|
|
481
481
|
bootstrap_grant: S
|
|
@@ -483,13 +483,13 @@ var Y = class {
|
|
|
483
483
|
}
|
|
484
484
|
async consumeProjectInvite(e) {
|
|
485
485
|
if (!this.db.batch) throw Error("D1 batch support is required for atomic invite consume.");
|
|
486
|
-
let t =
|
|
486
|
+
let t = m(e.now), n = await w(e.token), r = await this.getInviteByTokenForInspection(e.token);
|
|
487
487
|
if (!r?.operation_id || !r.project_intent_json || r.revoked_at) throw Error("invite_invalid");
|
|
488
488
|
let i = await this.getGroup(r.group_id);
|
|
489
489
|
if (!i) throw Error("group_not_found");
|
|
490
490
|
if (i.archived_at) throw Error("group_archived");
|
|
491
491
|
if (r.operation_id !== e.operationId) throw Error("invite_invalid");
|
|
492
|
-
if (
|
|
492
|
+
if (p(e.publicKey) !== e.fingerprint) throw Error("fingerprint_mismatch");
|
|
493
493
|
if (!r.consumed_at && new Date(r.expires_at) <= new Date(t)) throw Error("invite_expired");
|
|
494
494
|
let a = r.bound_device_id === e.deviceId && r.bound_public_key === e.publicKey && r.bound_fingerprint === e.fingerprint;
|
|
495
495
|
if (r.consumed_at && !a) throw Error("invite_already_bound");
|
|
@@ -502,23 +502,23 @@ var Y = class {
|
|
|
502
502
|
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
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(s, n, e.token, e.deviceId, t),
|
|
504
504
|
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
|
-
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,
|
|
513
|
-
let
|
|
514
|
-
if (!
|
|
515
|
-
if (
|
|
516
|
-
let
|
|
505
|
+
]))[0]) === 1, l = await this.getGroup(r.group_id);
|
|
506
|
+
if (!l) throw Error("group_not_found");
|
|
507
|
+
if (l.archived_at) throw Error("group_archived");
|
|
508
|
+
let u = await this.getInviteByTokenForInspection(e.token);
|
|
509
|
+
if (!u) throw Error("invite_invalid");
|
|
510
|
+
if (u.bound_device_id !== e.deviceId || u.bound_public_key !== e.publicKey || u.bound_fingerprint !== e.fingerprint) throw Error("invite_already_bound");
|
|
511
|
+
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");
|
|
512
|
+
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();
|
|
513
|
+
let d = await this.getEnrollment(u.group_id, e.deviceId);
|
|
514
|
+
if (!d) throw Error("invite_acceptance_incomplete");
|
|
515
|
+
if (d.identity_id !== e.recipientActorId) throw Error("invite_identity_conflict");
|
|
516
|
+
let f = u.inviter_device_id ? await this.getEnrollment(u.group_id, u.inviter_device_id) : null, h = u.bootstrap_grant_id ? await this.getBootstrapGrant(u.bootstrap_grant_id) : null;
|
|
517
517
|
return {
|
|
518
518
|
status: c ? "accepted" : "existing",
|
|
519
|
-
invite:
|
|
520
|
-
enrollment:
|
|
521
|
-
seed_enrollment:
|
|
519
|
+
invite: u,
|
|
520
|
+
enrollment: d,
|
|
521
|
+
seed_enrollment: f,
|
|
522
522
|
bootstrap_grant: h
|
|
523
523
|
};
|
|
524
524
|
}
|
|
@@ -652,64 +652,64 @@ var Y = class {
|
|
|
652
652
|
return (await K(n.length ? s.bind(...n) : s)).map((e) => h(e));
|
|
653
653
|
}
|
|
654
654
|
async grantScopeMembership(e) {
|
|
655
|
-
let t =
|
|
656
|
-
if (a) return
|
|
657
|
-
let
|
|
658
|
-
if (!
|
|
659
|
-
if (
|
|
660
|
-
let
|
|
661
|
-
if (
|
|
662
|
-
let
|
|
655
|
+
let t = n(e.effectId), i = o(e), a = await B(this.db, t);
|
|
656
|
+
if (a) return r(a, "grant", i), c(a);
|
|
657
|
+
let l = k(e.scopeId), u = k(e.deviceId), d = l ? await this.getScope(l) : null;
|
|
658
|
+
if (!d) throw new s("scope_not_found");
|
|
659
|
+
if (d.status !== "active") throw new s("scope_inactive");
|
|
660
|
+
let f = l && u ? await this.getScopeMembership(l, u) : null, p = L(e, d, f);
|
|
661
|
+
if (p.groupId && !await this.getEnrollment(p.groupId, p.deviceId)) throw new s("device_not_enrolled");
|
|
662
|
+
let m = b();
|
|
663
663
|
await U(this.db, [
|
|
664
|
-
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(
|
|
664
|
+
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, t),
|
|
665
665
|
V(this.db, {
|
|
666
666
|
effectId: t,
|
|
667
|
-
requestJson:
|
|
668
|
-
scopeId:
|
|
669
|
-
deviceId:
|
|
670
|
-
createdAt:
|
|
667
|
+
requestJson: i,
|
|
668
|
+
scopeId: p.scopeId,
|
|
669
|
+
deviceId: p.deviceId,
|
|
670
|
+
createdAt: m
|
|
671
671
|
}),
|
|
672
672
|
z(this.db, {
|
|
673
673
|
effectId: t,
|
|
674
|
-
requestJson:
|
|
674
|
+
requestJson: i,
|
|
675
675
|
action: "grant",
|
|
676
|
-
previous:
|
|
677
|
-
scopeId:
|
|
678
|
-
deviceId:
|
|
676
|
+
previous: f,
|
|
677
|
+
scopeId: p.scopeId,
|
|
678
|
+
deviceId: p.deviceId,
|
|
679
679
|
status: "active",
|
|
680
|
-
membershipEpoch:
|
|
681
|
-
updatedAt:
|
|
682
|
-
actorType:
|
|
683
|
-
actorId:
|
|
684
|
-
createdAt:
|
|
680
|
+
membershipEpoch: p.membershipEpoch,
|
|
681
|
+
updatedAt: m,
|
|
682
|
+
actorType: p.actorType,
|
|
683
|
+
actorId: p.actorId,
|
|
684
|
+
createdAt: m
|
|
685
685
|
})
|
|
686
686
|
]);
|
|
687
687
|
let h = await B(this.db, t);
|
|
688
688
|
if (!h) throw Error("scope membership grant was not applied.");
|
|
689
|
-
return
|
|
689
|
+
return r(h, "grant", i), c(h);
|
|
690
690
|
}
|
|
691
691
|
async revokeScopeMembership(e) {
|
|
692
|
-
let t = k(e.scopeId),
|
|
693
|
-
if (!t || !
|
|
694
|
-
let
|
|
695
|
-
if (
|
|
696
|
-
let
|
|
697
|
-
if (d && d !== f?.group_id) throw new
|
|
698
|
-
let p = await this.getScopeMembership(t,
|
|
699
|
-
if (
|
|
700
|
-
let m = b(), h =
|
|
701
|
-
effectId:
|
|
702
|
-
requestJson:
|
|
692
|
+
let t = k(e.scopeId), a = k(e.deviceId);
|
|
693
|
+
if (!t || !a) throw Error("scopeId and deviceId are required.");
|
|
694
|
+
let o = n(e.effectId), c = i(e), l = await B(this.db, o);
|
|
695
|
+
if (l) return r(l, "revoke", c), l.outcome_applied === 1;
|
|
696
|
+
let u = e.membershipEpoch == null ? null : M(e.membershipEpoch), d = k(e.groupId), f = d ? await this.getScope(t) : null;
|
|
697
|
+
if (d && d !== f?.group_id) throw new s("scope_group_mismatch");
|
|
698
|
+
let p = await this.getScopeMembership(t, a);
|
|
699
|
+
if (u != null && p && u <= p.membership_epoch) throw Error("membershipEpoch must increase on revoke.");
|
|
700
|
+
let m = b(), h = u ?? (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(u, u, k(e.manifestHash), k(e.signedManifestJson), m, t, a, p?.membership_epoch ?? -1, p?.status ?? "", o), _ = H(this.db, {
|
|
701
|
+
effectId: o,
|
|
702
|
+
requestJson: c,
|
|
703
703
|
scopeId: t,
|
|
704
|
-
deviceId:
|
|
704
|
+
deviceId: a,
|
|
705
705
|
createdAt: m
|
|
706
706
|
}), v = z(this.db, {
|
|
707
|
-
effectId:
|
|
708
|
-
requestJson:
|
|
707
|
+
effectId: o,
|
|
708
|
+
requestJson: c,
|
|
709
709
|
action: "revoke",
|
|
710
710
|
previous: p,
|
|
711
711
|
scopeId: t,
|
|
712
|
-
deviceId:
|
|
712
|
+
deviceId: a,
|
|
713
713
|
status: "revoked",
|
|
714
714
|
membershipEpoch: h,
|
|
715
715
|
updatedAt: m,
|
|
@@ -724,13 +724,13 @@ var Y = class {
|
|
|
724
724
|
v
|
|
725
725
|
]);
|
|
726
726
|
} catch (e) {
|
|
727
|
-
let
|
|
728
|
-
if (p && (!
|
|
727
|
+
let n = await this.getScopeMembership(t, a);
|
|
728
|
+
if (p && (!n || n.membership_epoch !== p.membership_epoch || n.status !== p.status)) return !1;
|
|
729
729
|
throw e;
|
|
730
730
|
}
|
|
731
|
-
let y = await B(this.db,
|
|
731
|
+
let y = await B(this.db, o);
|
|
732
732
|
if (!y) throw Error("scope membership revoke receipt was not persisted.");
|
|
733
|
-
return
|
|
733
|
+
return r(y, "revoke", c), y.outcome_applied === 1;
|
|
734
734
|
}
|
|
735
735
|
async listScopeMemberships(e, t = !1) {
|
|
736
736
|
let n = k(e);
|
|
@@ -810,7 +810,7 @@ var Y = class {
|
|
|
810
810
|
//#endregion
|
|
811
811
|
//#region src/d1-coordinator-runtime.ts
|
|
812
812
|
function X(e) {
|
|
813
|
-
return
|
|
813
|
+
return f({
|
|
814
814
|
storeFactory: () => new Y(e.db),
|
|
815
815
|
runtime: {
|
|
816
816
|
adminSecret: () => String(e.adminSecret ?? "").trim() || null,
|
|
@@ -820,6 +820,6 @@ function X(e) {
|
|
|
820
820
|
});
|
|
821
821
|
}
|
|
822
822
|
//#endregion
|
|
823
|
-
export { Y as D1CoordinatorStore,
|
|
823
|
+
export { Y as D1CoordinatorStore, d as DEFAULT_TIME_WINDOW_S, X as createD1CoordinatorApp };
|
|
824
824
|
|
|
825
825
|
//# sourceMappingURL=cloudflare-coordinator.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Database } from "./db.js";
|
|
2
|
+
export type OperationalMaintenanceState = "idle" | "running" | "failed" | "unknown";
|
|
3
|
+
export type OperationalSemanticState = "healthy" | "pending" | "degraded" | "failed" | "unknown";
|
|
4
|
+
export interface OperationalStatusSnapshot {
|
|
5
|
+
sync: {
|
|
6
|
+
available: boolean;
|
|
7
|
+
daemon_error: boolean;
|
|
8
|
+
needs_attention: boolean;
|
|
9
|
+
peer_errors: number;
|
|
10
|
+
};
|
|
11
|
+
maintenance: {
|
|
12
|
+
state: OperationalMaintenanceState;
|
|
13
|
+
running: number;
|
|
14
|
+
failed: number;
|
|
15
|
+
};
|
|
16
|
+
semantic_index: {
|
|
17
|
+
state: OperationalSemanticState;
|
|
18
|
+
vector_table_present: boolean;
|
|
19
|
+
};
|
|
20
|
+
raw_events: {
|
|
21
|
+
available: boolean;
|
|
22
|
+
pending: number;
|
|
23
|
+
failed_batches: number;
|
|
24
|
+
};
|
|
25
|
+
observer: {
|
|
26
|
+
available: boolean;
|
|
27
|
+
failed_batches: number;
|
|
28
|
+
backoff_batches: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Collect bounded operational aggregates from an already-open database without writing schema. */
|
|
32
|
+
export declare function collectOperationalStatus(db: Database, options?: {
|
|
33
|
+
embeddingDisabled?: boolean;
|
|
34
|
+
recentFailureCutoff?: string;
|
|
35
|
+
}): OperationalStatusSnapshot;
|
|
36
|
+
//# sourceMappingURL=operational-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operational-status.d.ts","sourceRoot":"","sources":["../src/operational-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,QAAQ,EAAe,MAAM,SAAS,CAAC;AAGnE,MAAM,MAAM,2BAA2B,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AACpF,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjG,MAAM,WAAW,yBAAyB;IACzC,IAAI,EAAE;QACL,SAAS,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,OAAO,CAAC;QACtB,eAAe,EAAE,OAAO,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,EAAE;QACZ,KAAK,EAAE,2BAA2B,CAAC;QACnC,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE;QACf,KAAK,EAAE,wBAAwB,CAAC;QAChC,oBAAoB,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF,UAAU,EAAE;QACX,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,QAAQ,EAAE;QACT,SAAS,EAAE,OAAO,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACxB,CAAC;CACF;AAoMD,mGAAmG;AACnG,wBAAgB,wBAAwB,CACvC,EAAE,EAAE,QAAQ,EACZ,OAAO,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAO,GACzE,yBAAyB,CAQ3B"}
|