@codemem/server 0.32.3 → 0.33.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/static/app.js CHANGED
@@ -3200,21 +3200,6 @@
3200
3200
  async function loadPairing(includeDiagnostics = false) {
3201
3201
  return fetchJson(`/api/sync/pairing${includeDiagnostics ? "?includeDiagnostics=1" : ""}`);
3202
3202
  }
3203
- async function updatePeerScope(peerDeviceId, include, exclude, inheritGlobal = false) {
3204
- const resp = await fetch("/api/sync/peers/scope", {
3205
- method: "POST",
3206
- headers: { "Content-Type": "application/json" },
3207
- body: JSON.stringify({
3208
- peer_device_id: peerDeviceId,
3209
- include,
3210
- exclude,
3211
- inherit_global: inheritGlobal
3212
- })
3213
- });
3214
- const { text, payload } = await readJsonPayload(resp);
3215
- if (!resp.ok) throw new Error(payloadError(payload) || text || "request failed");
3216
- return payload;
3217
- }
3218
3203
  async function assignPeerActor(peerDeviceId, actorId) {
3219
3204
  const resp = await fetch("/api/sync/peers/identity", {
3220
3205
  method: "POST",
@@ -3497,7 +3482,7 @@
3497
3482
  function escapeHtml(value) {
3498
3483
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3499
3484
  }
3500
- function escapeRegExp(value) {
3485
+ function escapeRegExp$1(value) {
3501
3486
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3502
3487
  }
3503
3488
  function highlightText(text, query) {
@@ -3505,7 +3490,7 @@
3505
3490
  if (!q) return escapeHtml(text);
3506
3491
  const safe = escapeHtml(text);
3507
3492
  try {
3508
- const re = new RegExp(`(${escapeRegExp(q)})`, "ig");
3493
+ const re = new RegExp(`(${escapeRegExp$1(q)})`, "ig");
3509
3494
  return safe.replace(re, "<mark class=\"match\">$1</mark>");
3510
3495
  } catch {
3511
3496
  return safe;
@@ -4103,6 +4088,23 @@
4103
4088
  return /* @__PURE__ */ u("input", { ...props });
4104
4089
  }
4105
4090
  //#endregion
4091
+ //#region src/tabs/coordinator-admin/data/device-card.ts
4092
+ function coordinatorAdminDeviceCardCopy(device, fallbackTeamId) {
4093
+ const deviceId = String(device.device_id || "").trim();
4094
+ const teamId = String(device.group_id || fallbackTeamId || "").trim();
4095
+ const displayName = String(device.display_name || deviceId || "Unnamed device");
4096
+ const enabled = device.enabled !== false && device.enabled !== 0;
4097
+ const advancedParts = [`Device ID ${deviceId || "unknown"}`];
4098
+ if (teamId) advancedParts.push(`Team ID ${teamId}`);
4099
+ return {
4100
+ advancedDetail: `Advanced: ${advancedParts.join(" · ")}`,
4101
+ deviceId,
4102
+ displayName,
4103
+ statusLabel: enabled ? "Enabled in this Team" : "Disabled in this Team",
4104
+ teamId
4105
+ };
4106
+ }
4107
+ //#endregion
4106
4108
  //#region src/tabs/coordinator-admin/data/state.ts
4107
4109
  var ADMIN_TARGET_GROUP_KEY = "codemem-coordinator-admin-target-group";
4108
4110
  var coordinatorAdminState = {
@@ -4138,17 +4140,16 @@
4138
4140
  return _$3(RadixTabsContent, {
4139
4141
  className: "coordinator-admin-panel",
4140
4142
  value: "devices"
4141
- }, _$3("h3", null, "Enrolled devices"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Rename, disable, re-enable, or remove enrolled devices from the operator surface without confusing this with direct sync state." : "Finish setup first. Device administration stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No enrolled devices found for the active coordinator group." : "Device administration will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, items.map((item) => {
4142
- const deviceId = String(item.device_id || "").trim();
4143
- const groupId = String(item.group_id || state.lastCoordinatorAdminStatus?.active_group || "").trim();
4144
- const displayName = String(item.display_name || deviceId || "Unnamed device");
4143
+ }, _$3("h3", null, "Enrolled devices"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Rename, disable, re-enable, or remove Team devices here. Space access is granted from Spaces below; Team membership alone does not share memories." : "Finish setup first. Device administration stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No enrolled devices found for the active coordinator group." : "Device administration will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, items.map((item) => {
4144
+ const copy = coordinatorAdminDeviceCardCopy(item, String(state.lastCoordinatorAdminStatus?.active_group || ""));
4145
+ const { deviceId, displayName, teamId } = copy;
4145
4146
  const pending = coordinatorAdminState.deviceActionPendingId === deviceId;
4146
4147
  const draft = coordinatorAdminState.deviceRenameDrafts.get(deviceId) ?? String(item.display_name || "");
4147
4148
  const enabled = item.enabled !== false && item.enabled !== 0;
4148
4149
  return _$3("div", {
4149
4150
  class: "peer-card peer-card--padded",
4150
4151
  key: deviceId || String(item.fingerprint || "unknown")
4151
- }, _$3("div", { class: "peer-title" }, _$3("strong", null, draft || displayName)), _$3("div", { class: "peer-meta" }, `Device: ${deviceId || "unknown"}`), groupId ? _$3("div", { class: "peer-submeta" }, `Group: ${groupId}`) : null, _$3("div", { class: "peer-submeta" }, enabled ? "Enabled" : "Disabled"), _$3("div", { class: "coordinator-admin-form-grid" }, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
4152
+ }, _$3("div", { class: "peer-title" }, _$3("strong", null, draft || displayName)), _$3("div", { class: "peer-submeta" }, copy.statusLabel), _$3("div", { class: "peer-meta" }, copy.advancedDetail), _$3("div", { class: "coordinator-admin-form-grid" }, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
4152
4153
  class: "peer-scope-input",
4153
4154
  disabled: summary.readiness !== "ready" || pending,
4154
4155
  onInput: (event) => {
@@ -4159,22 +4160,22 @@
4159
4160
  }))), _$3("div", { class: "peer-actions" }, _$3("button", {
4160
4161
  class: "settings-button",
4161
4162
  disabled: !deviceId || pending || summary.readiness !== "ready",
4162
- onClick: () => runDevice(deviceId, groupId, displayName, "rename"),
4163
+ onClick: () => runDevice(deviceId, teamId, displayName, "rename"),
4163
4164
  type: "button"
4164
4165
  }, pending && coordinatorAdminState.deviceActionPendingKind === "rename" ? "Renaming…" : "Rename"), enabled ? _$3("button", {
4165
4166
  class: "settings-button danger",
4166
4167
  disabled: !deviceId || pending || summary.readiness !== "ready",
4167
- onClick: () => runDevice(deviceId, groupId, displayName, "disable"),
4168
+ onClick: () => runDevice(deviceId, teamId, displayName, "disable"),
4168
4169
  type: "button"
4169
4170
  }, pending && coordinatorAdminState.deviceActionPendingKind === "disable" ? "Disabling…" : "Disable") : _$3("button", {
4170
4171
  class: "settings-button",
4171
4172
  disabled: !deviceId || pending || summary.readiness !== "ready",
4172
- onClick: () => runDevice(deviceId, groupId, displayName, "enable"),
4173
+ onClick: () => runDevice(deviceId, teamId, displayName, "enable"),
4173
4174
  type: "button"
4174
4175
  }, pending && coordinatorAdminState.deviceActionPendingKind === "enable" ? "Enabling…" : "Enable"), _$3("button", {
4175
4176
  class: "settings-button danger",
4176
4177
  disabled: !deviceId || pending || summary.readiness !== "ready",
4177
- onClick: () => runDevice(deviceId, groupId, displayName, "remove"),
4178
+ onClick: () => runDevice(deviceId, teamId, displayName, "remove"),
4178
4179
  type: "button"
4179
4180
  }, pending && coordinatorAdminState.deviceActionPendingKind === "remove" ? "Removing…" : "Remove")));
4180
4181
  })));
@@ -10057,6 +10058,36 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10057
10058
  const value = String(status || "active").trim();
10058
10059
  return value ? value.replaceAll("_", " ") : "active";
10059
10060
  }
10061
+ function spaceCardCopy(scope) {
10062
+ const title = String(scope.label || "").trim() || "Untitled Space";
10063
+ const status = scopeStatusLabel(scope.status);
10064
+ const kind = String(scope.kind || "user").replaceAll("_", " ");
10065
+ const scopeId = String(scope.scope_id || "").trim() || "unknown";
10066
+ const epoch = scope.membership_epoch == null ? "—" : String(scope.membership_epoch);
10067
+ return {
10068
+ title,
10069
+ summary: `${status} Space · ${kind}`,
10070
+ advancedDetail: `Advanced: Space ID ${scopeId} · Membership epoch ${epoch}`
10071
+ };
10072
+ }
10073
+ function spaceAccessDeviceCopy(row) {
10074
+ const statusLabel = {
10075
+ active: "Space access active",
10076
+ revoked: "Space access revoked",
10077
+ not_member: "No Space access"
10078
+ };
10079
+ const role = row.role.replaceAll("_", " ");
10080
+ const detail = row.status === "not_member" ? statusLabel[row.status] : `${statusLabel[row.status]} · ${role}`;
10081
+ const epoch = row.membershipEpoch == null ? "—" : String(row.membershipEpoch);
10082
+ return {
10083
+ statusLabel: statusLabel[row.status],
10084
+ detail,
10085
+ advancedDetail: `Advanced: membership epoch ${epoch}`
10086
+ };
10087
+ }
10088
+ function spaceRevokeMemberTitle(scope, displayName, deviceId) {
10089
+ return `Revoke ${displayName || deviceId || "this device"} from ${spaceCardCopy(scope).title}?`;
10090
+ }
10060
10091
  function deriveScopeMembershipDeviceRows(devices, members) {
10061
10092
  const memberByDevice = new Map(members.map((member) => [String(member.device_id || "").trim(), member]).filter(([deviceId]) => deviceId.length > 0));
10062
10093
  return devices.map((device) => {
@@ -10251,7 +10282,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10251
10282
  const scopeId = String(scope.scope_id || "").trim();
10252
10283
  if (!scopeId) return;
10253
10284
  if (!await openSyncConfirmDialog({
10254
- title: `Revoke ${displayName || deviceId} from ${scope.label || scopeId}?`,
10285
+ title: spaceRevokeMemberTitle(scope, displayName, deviceId),
10255
10286
  description: "Revocation only blocks future sync for this Space. Data already copied to that device can remain there.",
10256
10287
  confirmLabel: "Revoke membership",
10257
10288
  cancelLabel: "Keep membership",
@@ -10290,31 +10321,30 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10290
10321
  const pending = draft.actionPendingKey === pendingKey;
10291
10322
  const canGrant = row.enabled && row.status !== "active";
10292
10323
  const canRevoke = row.status === "active";
10293
- const statusCopy = row.status === "not_member" ? "Not a member" : row.status === "revoked" ? "Revoked" : "Active member";
10294
- const epochCopy = row.membershipEpoch == null ? "epoch —" : `epoch ${row.membershipEpoch}`;
10324
+ const copy = spaceAccessDeviceCopy(row);
10295
10325
  return _$3("div", {
10296
10326
  class: "coordinator-admin-scope-member-row",
10297
10327
  key: row.deviceId
10298
- }, _$3("div", { class: "coordinator-admin-scope-member-copy" }, _$3("strong", null, row.displayName), _$3("span", null, `${statusCopy} · ${row.role} · ${epochCopy}`), row.enabled ? null : _$3("span", null, "Device is disabled in this Team.")), _$3("div", { class: "peer-actions" }, canGrant ? _$3("button", {
10328
+ }, _$3("div", { class: "coordinator-admin-scope-member-copy" }, _$3("strong", null, row.displayName), _$3("span", null, copy.detail), _$3("span", { class: "peer-meta" }, copy.advancedDetail), row.enabled ? null : _$3("span", null, "Device is disabled in this Team.")), _$3("div", { class: "peer-actions" }, canGrant ? _$3("button", {
10299
10329
  class: "settings-button",
10300
10330
  disabled: !ready || Boolean(draft.actionPendingKey),
10301
10331
  onClick: () => void grantMember(groupId, scopeId, row.deviceId, renderShell),
10302
10332
  type: "button"
10303
- }, pending && draft.actionPendingKind === "grant" ? "Granting…" : "Grant") : null, canRevoke ? _$3("button", {
10333
+ }, pending && draft.actionPendingKind === "grant" ? "Granting…" : "Grant access") : null, canRevoke ? _$3("button", {
10304
10334
  class: "settings-button danger",
10305
10335
  disabled: !ready || Boolean(draft.actionPendingKey),
10306
10336
  onClick: () => void revokeMember(groupId, scope, row.deviceId, row.displayName, renderShell),
10307
10337
  type: "button"
10308
- }, pending && draft.actionPendingKind === "revoke" ? "Revoking…" : "Revoke") : null));
10338
+ }, pending && draft.actionPendingKind === "revoke" ? "Revoking…" : "Revoke access") : null));
10309
10339
  }));
10310
10340
  }
10311
10341
  function renderScopeCard(groupId, scope, draft, ready, renderShell) {
10312
10342
  const scopeId = String(scope.scope_id || "").trim();
10313
- const label = String(scope.label || scopeId || "Untitled Space");
10343
+ const copy = spaceCardCopy(scope);
10314
10344
  return _$3("div", {
10315
10345
  class: "peer-card peer-card--padded coordinator-admin-scope-card",
10316
- key: scopeId || label
10317
- }, _$3("div", { class: "peer-title" }, _$3("strong", null, label)), _$3("div", { class: "peer-submeta" }, `Status: ${scopeStatusLabel(scope.status)} · Kind: ${scope.kind || "user"}`), _$3("div", { class: "peer-meta" }, `Advanced: Space ID ${scopeId || "unknown"} · Membership epoch ${scope.membership_epoch ?? 0}`), _$3("div", { class: "peer-submeta" }, "Devices below are enrolled in the Team; only active Space members can sync this data boundary."), renderMembershipRows(groupId, scope, draft, ready, renderShell));
10346
+ key: scopeId || copy.title
10347
+ }, _$3("div", { class: "peer-title" }, _$3("strong", null, copy.title)), _$3("div", { class: "peer-submeta" }, copy.summary), _$3("div", { class: "peer-meta" }, copy.advancedDetail), _$3("div", { class: "peer-submeta" }, "Devices below are enrolled in the Team; only active Space members can sync this data boundary."), renderMembershipRows(groupId, scope, draft, ready, renderShell));
10318
10348
  }
10319
10349
  function renderGroupScopeManagementPanel(deps) {
10320
10350
  const { groupId, ready, summary, renderShell } = deps;
@@ -10482,10 +10512,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10482
10512
  const includeLabelId = `coord-admin-scope-include-${groupId}`;
10483
10513
  const excludeLabelId = `coord-admin-scope-exclude-${groupId}`;
10484
10514
  const fieldsDisabled = !ready || draft.saving || !draft.auto_seed_scope;
10485
- return _$3(k$3, null, _$3("h4", { class: "coordinator-admin-drawer-title" }, "Team defaults"), _$3("div", { class: "peer-submeta" }, "Project filters only narrow what future writes sync; they never grant Space access by themselves. Use the default Space toggle to control whether newly joined devices receive the Team's default Space."), _$3("label", { class: "coordinator-admin-inline-filter" }, _$3("span", {
10515
+ return _$3(k$3, null, _$3("h4", { class: "coordinator-admin-drawer-title" }, "Team defaults"), _$3("div", { class: "peer-submeta" }, "Space access grants decide what new devices can sync. Advanced sharing rules only narrow future writes after Space access already exists."), _$3("label", { class: "coordinator-admin-inline-filter" }, _$3("span", {
10486
10516
  class: "section-meta",
10487
10517
  id: autoSeedLabelId
10488
- }, "Auto-seed project filters"), _$3(RadixSwitch, {
10518
+ }, "Auto-apply advanced rules to new devices"), _$3(RadixSwitch, {
10489
10519
  "aria-labelledby": autoSeedLabelId,
10490
10520
  checked: draft.auto_seed_scope,
10491
10521
  className: "coordinator-admin-switch",
@@ -10516,7 +10546,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10516
10546
  renderShell();
10517
10547
  },
10518
10548
  thumbClassName: "coordinator-admin-switch-thumb"
10519
- })), draft.default_space_scope_id ? _$3("div", { class: "peer-submeta" }, "Default Space configured.") : _$3("div", { class: "peer-submeta" }, "No default Space has been created yet."), _$3("div", { class: "coordinator-admin-field" }, _$3("span", { id: includeLabelId }, "Include projects"), _$3(ProjectScopePicker, {
10549
+ })), draft.default_space_scope_id ? _$3("div", { class: "peer-submeta" }, "Default Space configured.") : _$3("div", { class: "peer-submeta" }, "No default Space has been created yet."), _$3("div", { class: "coordinator-admin-field" }, _$3("span", { id: includeLabelId }, "Include template"), _$3(ProjectScopePicker, {
10520
10550
  "aria-labelledby": includeLabelId,
10521
10551
  availableProjects: coordinatorAdminState.availableProjects,
10522
10552
  disabled: fieldsDisabled,
@@ -10531,7 +10561,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10531
10561
  },
10532
10562
  placeholder: "Add project",
10533
10563
  values: draft.projects_include
10534
- }), _$3("span", { class: "peer-submeta" }, "Leave empty to allow every project. Type to search or create a new name.")), _$3("div", { class: "coordinator-admin-field" }, _$3("span", { id: excludeLabelId }, "Exclude projects"), _$3(ProjectScopePicker, {
10564
+ }), _$3("span", { class: "peer-submeta" }, "Leave empty to allow every project inside the granted Space. Type to search or create a new name.")), _$3("div", { class: "coordinator-admin-field" }, _$3("span", { id: excludeLabelId }, "Exclude template"), _$3(ProjectScopePicker, {
10535
10565
  "aria-labelledby": excludeLabelId,
10536
10566
  availableProjects: coordinatorAdminState.availableProjects,
10537
10567
  disabled: fieldsDisabled,
@@ -10837,7 +10867,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10837
10867
  return _$3(RadixTabsContent, {
10838
10868
  className: "coordinator-admin-panel",
10839
10869
  value: "join-requests"
10840
- }, _$3("h3", null, "Pending join requests"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Approve or deny teammate join requests from the dedicated operator surface instead of burying them in Sync." : "Finish setup first. Join request review stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No pending join requests right now." : "Join request review will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, items.map((item) => {
10870
+ }, _$3("h3", null, "Pending join requests"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Approve or deny devices that want to join this Team. Default Space access is handled by Team defaults and can be reviewed in Spaces." : "Finish setup first. Join request review stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No pending join requests right now." : "Join request review will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, items.map((item) => {
10841
10871
  const requestId = String(item.request_id || "").trim();
10842
10872
  const deviceId = String(item.device_id || "unknown-device");
10843
10873
  const displayName = String(item.display_name || deviceId);
@@ -10845,7 +10875,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10845
10875
  return _$3("div", {
10846
10876
  class: "peer-card peer-card--padded",
10847
10877
  key: requestId || deviceId
10848
- }, _$3("div", { class: "peer-title" }, _$3("strong", null, displayName)), _$3("div", { class: "peer-meta" }, `Device: ${deviceId}`), _$3("div", { class: "peer-actions" }, _$3("button", {
10878
+ }, _$3("div", { class: "peer-title" }, _$3("strong", null, displayName)), _$3("div", { class: "peer-meta" }, `Advanced: Device ID ${deviceId}`), _$3("div", { class: "peer-actions" }, _$3("button", {
10849
10879
  class: "settings-button",
10850
10880
  disabled: !requestId || pending,
10851
10881
  onClick: () => reviewJoinRequest(requestId, "approve"),
@@ -10963,7 +10993,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10963
10993
  state.lastTeamInvite = result;
10964
10994
  coordinatorAdminState.inviteGroup = groupId;
10965
10995
  const warnings = Array.isArray(result.warnings) ? result.warnings : [];
10966
- showGlobalNotice(warnings.length ? `Invite created. Review ${warnings.length === 1 ? "the warning" : `${warnings.length} warnings`} before sharing it.` : "Invite created. Copy it from Coordinator Admin and share it with your teammate.", warnings.length ? "warning" : "success");
10996
+ showGlobalNotice(warnings.length ? `Invite created. Review ${warnings.length === 1 ? "the warning" : `${warnings.length} warnings`} before sharing it.` : "Invite created. Copy it from Teams and share it with your teammate.", warnings.length ? "warning" : "success");
10967
10997
  } catch (error) {
10968
10998
  showGlobalNotice(error instanceof Error ? error.message : "Failed to create invite.", "warning");
10969
10999
  } finally {
@@ -18095,11 +18125,16 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18095
18125
  warning: false
18096
18126
  };
18097
18127
  }
18098
- if (failedItems.filter((item) => cleanText(item.error).toLowerCase().includes("401") && cleanText(item.error).toLowerCase().includes("unauthorized")).length === failedItems.length) return {
18128
+ if (failedItems.filter((item) => isTrustFailureError(cleanText(item.error))).length === failedItems.length) return {
18099
18129
  ok: false,
18100
18130
  message: "This device no longer has two-way trust with the peer. Pair it again from the other device, or remove the stale local record if it should be gone.",
18101
18131
  warning: true
18102
18132
  };
18133
+ if (failedItems.filter((item) => isScopeMembershipFailureError(cleanText(item.error))).length === failedItems.length) return {
18134
+ ok: false,
18135
+ message: "Sync ran, but the peer is not authorized for one or more Spaces. Review Space access for this device in Teams, then sync again.",
18136
+ warning: true
18137
+ };
18103
18138
  if (failedItems.length < items.length) return {
18104
18139
  ok: false,
18105
18140
  message: `${failedItems.length} of ${items.length} device sync attempts failed. Open the affected device cards for the specific errors.`,
@@ -18111,6 +18146,41 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18111
18146
  warning: true
18112
18147
  };
18113
18148
  }
18149
+ /**
18150
+ * True when a sync-failure error string looks like a two-way-trust failure
18151
+ * (401 unauthorized on the peer's /v1/status), which is the only class of
18152
+ * failure that should trigger the "no longer has two-way trust" toast. Any
18153
+ * other class — connectivity, scope/membership, generation mismatch — flows
18154
+ * through the generic mixed-failure or scoped paths so users do not get
18155
+ * pointed at re-pairing for problems that re-pairing will not fix.
18156
+ */
18157
+ function isTrustFailureError(error) {
18158
+ const lower = error.toLowerCase();
18159
+ return lower.includes("401") && lower.includes("unauthorized");
18160
+ }
18161
+ /**
18162
+ * True when a sync-failure error string indicates the peer is not authorized
18163
+ * for a Space (or is authorized at a stale epoch). These failures map to the
18164
+ * scoped-sync protocol classes documented in
18165
+ * docs/plans/2026-05-25-scoped-sync-protocol.md:
18166
+ *
18167
+ * - `403: scope_rejected` from POST /v1/ops outbound scope filter.
18168
+ * - `409: reset_required` with `reason=missing_scope` or `stale_epoch`
18169
+ * from GET /v1/ops or GET /v1/snapshot.
18170
+ * - syncOneScope's aggregate string only when it includes one of those wire
18171
+ * reasons. Other scoped-sync failures remain generic sync failures.
18172
+ *
18173
+ * Detection is intentionally substring-based because the wire reason can
18174
+ * arrive embedded in a longer error string from the address-fallback loop.
18175
+ */
18176
+ function isScopeMembershipFailureError(error) {
18177
+ const lower = error.toLowerCase();
18178
+ if (lower.includes("scope_rejected")) return true;
18179
+ if (lower.includes("missing_scope")) return true;
18180
+ if (lower.includes("stale_epoch")) return true;
18181
+ if (lower.includes("scope_inactive")) return true;
18182
+ return false;
18183
+ }
18114
18184
  function outboundFilterLabel(detail) {
18115
18185
  const reason = cleanText(detail?.reason);
18116
18186
  return OUTBOUND_FILTER_LABELS[reason] ?? (reason.replaceAll("_", " ") || "sync filters");
@@ -18261,8 +18331,9 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18261
18331
  function derivePeerAuthorizedDomainsView(peer) {
18262
18332
  const domains = (Array.isArray(peer.authorized_scopes) ? peer.authorized_scopes : []).map((scope) => {
18263
18333
  const scopeId = cleanText(scope.scope_id);
18264
- const label = cleanText(scope.label) ?? scopeId;
18265
- if (!scopeId && !label) return null;
18334
+ const rawLabel = cleanText(scope.label);
18335
+ if (!scopeId && !rawLabel) return null;
18336
+ const label = rawLabel || "Untitled Space";
18266
18337
  const detail = [
18267
18338
  labelPart(cleanText(scope.kind), "user"),
18268
18339
  labelPart(cleanText(scope.authority_type), "local"),
@@ -18270,17 +18341,17 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18270
18341
  ].filter(Boolean).join(" · ");
18271
18342
  return {
18272
18343
  scopeId: scopeId || label,
18273
- label: label || scopeId,
18344
+ label,
18274
18345
  detail
18275
18346
  };
18276
18347
  }).filter((item) => item != null);
18277
18348
  const total = domains.length;
18278
18349
  return {
18279
18350
  total,
18280
- badgeLabel: total === 1 ? "1 Sharing domain" : total > 1 ? `${total} Sharing domains` : "No Sharing domains",
18351
+ badgeLabel: total === 1 ? "1 Space" : total > 1 ? `${total} Spaces` : "No Space access",
18281
18352
  isWarning: total === 0,
18282
18353
  domains,
18283
- emptyMessage: "No Sharing-domain grants exist for this device yet. Project filters below cannot send data by themselves."
18354
+ emptyMessage: "No Space access grants exist for this device yet. Advanced project filters cannot send data by themselves."
18284
18355
  };
18285
18356
  }
18286
18357
  var PERSONAL_SCOPE_WORDS = [
@@ -18360,25 +18431,32 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18360
18431
  title: ""
18361
18432
  };
18362
18433
  return {
18363
- badgeLabel: "Review domain fit",
18364
- detail: "Coordinator/group context helps find the device, and project filters only narrow already-authorized domains. Neither one grants a missing work/client domain.",
18434
+ badgeLabel: "Review Space fit",
18435
+ detail: "Team discovery helps find the device, and advanced project filters only narrow already-authorized Spaces. Neither one grants missing work/client Space access.",
18365
18436
  isVisible: true,
18366
- message: "This coordinator-discovered device has personal or OSS Sharing-domain grants, but no separate work/client-like domain grant. If this device is meant for work/client sync, add that Sharing domain explicitly before treating sync as validated.",
18367
- title: "Check this device's Sharing-domain role"
18437
+ message: "This Team-discovered device has personal or OSS Space access, but no separate work/client-like Space access. If this device is meant for work/client sync, grant that Space explicitly before treating sync as validated.",
18438
+ title: "Check this device's Space access"
18368
18439
  };
18369
18440
  }
18441
+ function hasActiveProjectNarrowing(include, exclude) {
18442
+ const normalizedInclude = include.map((item) => item.trim()).filter(Boolean);
18443
+ return normalizedInclude.length > 0 && !normalizedInclude.includes("*") || exclude.length > 0;
18444
+ }
18370
18445
  function derivePeerProjectNarrowingView(scope) {
18371
18446
  const effectiveInclude = cleanList(scope?.effective_include);
18372
18447
  const effectiveExclude = cleanList(scope?.effective_exclude);
18373
18448
  const sourceLabel = scope?.inherits_global ? "Global defaults" : "Device override";
18374
18449
  const includeLabel = `Include filter: ${shortList(effectiveInclude, "all projects")}`;
18375
18450
  const excludeLabel = `Exclude filter: ${shortList(effectiveExclude, "no exclusions")}`;
18451
+ const hasAdvancedFilters = hasActiveProjectNarrowing(effectiveInclude, effectiveExclude);
18376
18452
  return {
18453
+ hasAdvancedFilters,
18454
+ statusLabel: hasAdvancedFilters ? "Advanced filters active" : "No advanced filters",
18377
18455
  sourceLabel,
18378
18456
  includeLabel,
18379
18457
  excludeLabel,
18380
18458
  summary: `${sourceLabel}. ${includeLabel}; ${excludeLabel}.`,
18381
- note: "Project filters only narrow data after Sharing domain authorization; they never grant access to another domain."
18459
+ note: "Advanced filters only narrow data after Space access; they never grant access to another Space."
18382
18460
  };
18383
18461
  }
18384
18462
  //#endregion
@@ -18685,6 +18763,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18685
18763
  const unique = Array.from(new Set(addresses.filter(Boolean)));
18686
18764
  return typeof unique[0] === "string" ? unique[0] : "";
18687
18765
  }
18766
+ /**
18767
+ * Returns true when a "Removed peer X" style feedback message is stale
18768
+ * because the related peer has reappeared in the loaded peers list (e.g.
18769
+ * the user re-paired the same device they just removed). Used by
18770
+ * renderSyncPeers to clear the persistent banner once the user's view
18771
+ * of reality contradicts it.
18772
+ */
18773
+ function shouldClearStalePeersFeedback(feedback, peers) {
18774
+ const id = String(feedback?.relatedPeerDeviceId ?? "").trim();
18775
+ if (!id) return false;
18776
+ return peers.some((peer) => String(peer?.peer_device_id ?? "").trim() === id);
18777
+ }
18688
18778
  function actorLabel(actor) {
18689
18779
  if (!actor || typeof actor !== "object") return "Unknown person";
18690
18780
  const displayName = String(actor.display_name || "").trim();
@@ -18730,208 +18820,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18730
18820
  if (!targetActorId || !target) return "Choose which person should keep these devices.";
18731
18821
  return `Merge into ${actorDisplayLabel(target)}. Assigned devices move now; existing memories keep their current provenance.`;
18732
18822
  }
18733
- function createChipEditor(initialValues, placeholder, emptyLabel, availableProjects = []) {
18734
- let values = [...initialValues];
18735
- let query = "";
18736
- let activeIndex = 0;
18737
- let popoverOpen = false;
18738
- const container = el$1("div", "project-scope-picker");
18739
- const selectedList = el$1("ul", "project-scope-picker-selected");
18740
- const trigger = el$1("button", "project-scope-picker-trigger settings-button");
18741
- trigger.type = "button";
18742
- const triggerLabel = el$1("span", null, placeholder || "Add project");
18743
- const triggerPlus = el$1("span", null, "+");
18744
- triggerPlus.setAttribute("aria-hidden", "true");
18745
- trigger.append(triggerPlus, triggerLabel);
18746
- trigger.setAttribute("aria-haspopup", "listbox");
18747
- trigger.setAttribute("aria-expanded", "false");
18748
- const popover = el$1("div", "project-scope-picker-popover project-scope-picker-popover--inline");
18749
- popover.hidden = true;
18750
- const search = el$1("input", "project-scope-picker-search");
18751
- search.type = "text";
18752
- search.placeholder = "Search or create…";
18753
- search.setAttribute("aria-label", "Search projects");
18754
- const results = el$1("div", "project-scope-picker-results");
18755
- results.setAttribute("role", "listbox");
18756
- popover.append(search, results);
18757
- const knownPool = () => {
18758
- const seen = /* @__PURE__ */ new Set();
18759
- const out = [];
18760
- for (const item of [...availableProjects, ...values]) {
18761
- const trimmed = item.trim();
18762
- if (!trimmed || seen.has(trimmed)) continue;
18763
- seen.add(trimmed);
18764
- out.push(trimmed);
18765
- }
18766
- return out.sort((a, b) => a.localeCompare(b));
18767
- };
18768
- const filteredRows = () => {
18769
- const all = knownPool();
18770
- const q = query.trim().toLowerCase();
18771
- if (!q) return all;
18772
- return all.filter((project) => project.toLowerCase().includes(q));
18773
- };
18774
- const shouldShowCreateRow = () => {
18775
- const q = query.trim();
18776
- if (!q) return false;
18777
- return !knownPool().some((project) => project.toLowerCase() === q.toLowerCase());
18778
- };
18779
- const toggleValue = (project) => {
18780
- if (values.includes(project)) values = values.filter((value) => value !== project);
18781
- else values = Array.from(new Set([...values, project]));
18782
- renderSelected();
18783
- renderResults();
18784
- };
18785
- const createFromQuery = () => {
18786
- const trimmed = query.trim();
18787
- if (!trimmed) return;
18788
- values = Array.from(new Set([...values, trimmed]));
18789
- query = "";
18790
- search.value = "";
18791
- activeIndex = 0;
18792
- renderSelected();
18793
- renderResults();
18794
- };
18795
- const activateRow = (index) => {
18796
- const rows = filteredRows();
18797
- if (index < rows.length) {
18798
- const project = rows[index];
18799
- if (project) toggleValue(project);
18800
- return;
18801
- }
18802
- if (shouldShowCreateRow()) createFromQuery();
18803
- };
18804
- const renderSelected = () => {
18805
- selectedList.textContent = "";
18806
- if (!values.length) {
18807
- const note = el$1("li", "project-scope-picker-selected-empty", emptyLabel);
18808
- selectedList.appendChild(note);
18809
- return;
18810
- }
18811
- values.forEach((value) => {
18812
- const chip = el$1("li", "project-scope-picker-selected-chip");
18813
- const label = el$1("span", null, value);
18814
- const remove = el$1("button", "project-scope-picker-selected-remove", "×");
18815
- remove.type = "button";
18816
- remove.setAttribute("aria-label", `Remove ${value}`);
18817
- remove.addEventListener("click", () => {
18818
- values = values.filter((existing) => existing !== value);
18819
- renderSelected();
18820
- renderResults();
18821
- });
18822
- chip.append(label, remove);
18823
- selectedList.appendChild(chip);
18824
- });
18825
- };
18826
- const renderResults = () => {
18827
- results.textContent = "";
18828
- const rows = filteredRows();
18829
- const withCreate = shouldShowCreateRow();
18830
- const rowCount = rows.length + (withCreate ? 1 : 0);
18831
- if (activeIndex >= rowCount) activeIndex = Math.max(0, rowCount - 1);
18832
- if (!rows.length && !withCreate) {
18833
- const empty = el$1("div", "project-scope-picker-empty-row", "No projects yet. Type a name to create one.");
18834
- results.appendChild(empty);
18835
- return;
18836
- }
18837
- rows.forEach((project, index) => {
18838
- const selected = values.includes(project);
18839
- const row = el$1("button", index === activeIndex ? "project-scope-picker-row project-scope-picker-row--active" : "project-scope-picker-row");
18840
- row.type = "button";
18841
- row.setAttribute("role", "option");
18842
- row.setAttribute("aria-selected", selected ? "true" : "false");
18843
- const check = el$1("span", "project-scope-picker-row-check", selected ? "✓" : "");
18844
- check.setAttribute("aria-hidden", "true");
18845
- const labelEl = el$1("span", "project-scope-picker-row-label", project);
18846
- row.append(check, labelEl);
18847
- row.addEventListener("click", () => {
18848
- activeIndex = index;
18849
- toggleValue(project);
18850
- });
18851
- row.addEventListener("mouseenter", () => {
18852
- activeIndex = index;
18853
- renderResults();
18854
- });
18855
- results.appendChild(row);
18856
- });
18857
- if (withCreate) {
18858
- const index = rows.length;
18859
- const row = el$1("button", index === activeIndex ? "project-scope-picker-row project-scope-picker-row--create project-scope-picker-row--active" : "project-scope-picker-row project-scope-picker-row--create");
18860
- row.type = "button";
18861
- row.setAttribute("role", "option");
18862
- const check = el$1("span", "project-scope-picker-row-check", "+");
18863
- check.setAttribute("aria-hidden", "true");
18864
- const labelEl = el$1("span", "project-scope-picker-row-label", `Create "${query.trim()}"`);
18865
- row.append(check, labelEl);
18866
- row.addEventListener("click", () => createFromQuery());
18867
- row.addEventListener("mouseenter", () => {
18868
- activeIndex = index;
18869
- renderResults();
18870
- });
18871
- results.appendChild(row);
18872
- }
18873
- };
18874
- const setOpen = (next) => {
18875
- popoverOpen = next;
18876
- popover.hidden = !next;
18877
- trigger.setAttribute("aria-expanded", next ? "true" : "false");
18878
- if (next) {
18879
- query = "";
18880
- search.value = "";
18881
- activeIndex = 0;
18882
- renderResults();
18883
- requestAnimationFrame(() => search.focus());
18884
- }
18885
- };
18886
- trigger.addEventListener("click", (event) => {
18887
- event.stopPropagation();
18888
- setOpen(!popoverOpen);
18889
- });
18890
- search.addEventListener("input", () => {
18891
- query = search.value;
18892
- activeIndex = 0;
18893
- renderResults();
18894
- });
18895
- search.addEventListener("keydown", (event) => {
18896
- const rowCount = filteredRows().length + (shouldShowCreateRow() ? 1 : 0);
18897
- if (event.key === "ArrowDown") {
18898
- event.preventDefault();
18899
- activeIndex = Math.min(rowCount - 1, activeIndex + 1);
18900
- renderResults();
18901
- return;
18902
- }
18903
- if (event.key === "ArrowUp") {
18904
- event.preventDefault();
18905
- activeIndex = Math.max(0, activeIndex - 1);
18906
- renderResults();
18907
- return;
18908
- }
18909
- if (event.key === "Enter") {
18910
- event.preventDefault();
18911
- activateRow(activeIndex);
18912
- return;
18913
- }
18914
- if (event.key === "Escape") {
18915
- event.preventDefault();
18916
- setOpen(false);
18917
- }
18918
- });
18919
- const onDocumentClick = (event) => {
18920
- if (!popoverOpen) return;
18921
- const target = event.target;
18922
- if (!target) return;
18923
- if (container.contains(target)) return;
18924
- setOpen(false);
18925
- };
18926
- document.addEventListener("click", onDocumentClick);
18927
- container.append(selectedList, trigger, popover);
18928
- renderSelected();
18929
- renderResults();
18930
- return {
18931
- element: container,
18932
- values: () => [...values]
18933
- };
18934
- }
18935
18823
  function renderActionList(container, actions) {
18936
18824
  if (!container) return;
18937
18825
  container.textContent = "";
@@ -18974,6 +18862,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18974
18862
  if (isError && attempt.error) {
18975
18863
  const errText = String(attempt.error);
18976
18864
  detailParts.push(redact ? redactIpOctets(errText) : errText);
18865
+ if (redact && /enable diagnostics for details/i.test(errText)) detailParts.push("Turn off Redact in Advanced diagnostics to reveal the full error.");
18977
18866
  }
18978
18867
  if (!isError && (attempt.ops_in || attempt.ops_out)) detailParts.push(`${attempt.ops_in ?? 0} in · ${attempt.ops_out ?? 0} out`);
18979
18868
  if (!redact && attempt.address) detailParts.push(attempt.address);
@@ -19528,46 +19417,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19528
19417
  });
19529
19418
  }
19530
19419
  //#endregion
19531
- //#region src/tabs/sync/peer-scope-collapsible.tsx
19532
- function PeerScopeCollapsible({ contentHost, initialOpen, onOpenChange, children }) {
19533
- const [open, setOpen] = d$2(initialOpen);
19534
- const contentRef = A$1(null);
19535
- y$2(() => {
19536
- setOpen(initialOpen);
19537
- }, [initialOpen]);
19538
- _$2(() => {
19539
- onOpenChange(open);
19540
- }, [onOpenChange, open]);
19541
- y$2(() => {
19542
- if (!open) return;
19543
- queueMicrotask(() => {
19544
- (contentRef.current?.querySelector("button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])"))?.focus();
19545
- });
19546
- }, [open]);
19547
- return /* @__PURE__ */ u(Root$3, {
19548
- open,
19549
- onOpenChange: setOpen,
19550
- children: [/* @__PURE__ */ u(Trigger$4, {
19551
- asChild: true,
19552
- children: /* @__PURE__ */ u("button", {
19553
- type: "button",
19554
- className: "settings-button",
19555
- children: open ? "Hide sharing scope" : "Show sharing scope"
19556
- })
19557
- }), contentHost ? $$1(/* @__PURE__ */ u(Content$2, {
19558
- forceMount: true,
19559
- ref: contentRef,
19560
- className: `peer-scope-editor-wrap${open ? "" : " collapsed"}`,
19561
- hidden: !open,
19562
- inert: !open,
19563
- children: /* @__PURE__ */ u(ScopeEditorContent, { children })
19564
- }), contentHost) : null]
19565
- });
19566
- }
19567
- function ScopeEditorContent({ children }) {
19568
- return /* @__PURE__ */ u("div", { children });
19569
- }
19570
- //#endregion
19571
19420
  //#region src/tabs/sync/components/sync-inline-feedback.tsx
19572
19421
  function SyncInlineFeedback({ feedback }) {
19573
19422
  if (!feedback?.message) return null;
@@ -19636,42 +19485,27 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19636
19485
  },
19637
19486
  none: null
19638
19487
  };
19639
- function listText(value) {
19640
- return Array.isArray(value) ? value.map((item) => String(item || "").trim()).filter(Boolean) : [];
19641
- }
19642
19488
  function claimedLocalActorScopeMessage(scope) {
19643
- const scopeId = String(scope?.scope_id || "").trim();
19644
- if (!scope) return "Private same-person sync is limited to an allowed personal Sharing domain; team or org domains do not carry your private memories.";
19645
- if (scope.authorized) return `Private same-person sync is limited to personal Sharing domain ${scopeId || "this device's personal domain"}. Team and org domains do not carry your private memories.`;
19646
- return `Private same-person sync is blocked until this device is granted ${scopeId || "its personal Sharing domain"}.`;
19489
+ if (!scope) return "Private same-person sync is limited to an allowed personal Space; team or org Spaces do not carry your private memories.";
19490
+ if (scope.authorized) return "Private same-person sync is limited to your personal Space. Team and org Spaces do not carry your private memories.";
19491
+ return "Private same-person sync is blocked until this device is granted an allowed personal Space.";
19647
19492
  }
19648
- function ExistingElementSlot$1({ element }) {
19649
- const hostRef = A$1(null);
19650
- _$2(() => {
19651
- const host = hostRef.current;
19652
- if (!host) return;
19653
- if (element.parentElement !== host) host.appendChild(element);
19654
- return () => {
19655
- if (element.parentElement === host) host.removeChild(element);
19656
- };
19657
- }, [element]);
19658
- return /* @__PURE__ */ u("div", { ref: hostRef });
19493
+ function openTeamsAccessManagement() {
19494
+ window.location.hash = "coordinator-admin";
19659
19495
  }
19660
- function SyncPeerCard({ peer, onAssignActor, onRemove, onRename, onResetScope, onSaveScope, onSync }) {
19496
+ function SyncPeerCard({ peer, onAssignActor, onRemove, onRename, onSync }) {
19661
19497
  const peerId = String(peer.peer_device_id || "");
19662
19498
  const displayName = peer.name || (peerId ? peerId.slice(0, 8) : "unknown");
19663
19499
  const destructiveLabel = peer.name || peerId || displayName;
19664
- const pendingScopeReview = isPeerScopeReviewPending(peerId);
19665
19500
  const trustSummary = derivePeerTrustSummary(peer);
19666
19501
  const directionHint = DIRECTION_GLYPH[derivePeerDirection(peer)];
19667
19502
  const peerStatus = peer.status || {};
19668
19503
  const authorizedDomains = derivePeerAuthorizedDomainsView(peer);
19504
+ const rawPendingScopeReview = isPeerScopeReviewPending(peerId);
19505
+ const pendingScopeReview = rawPendingScopeReview && authorizedDomains.total === 0;
19669
19506
  const grantRoleMismatch = derivePeerGrantRoleMismatchView(peer);
19670
19507
  const scopeRejections = derivePeerScopeRejectionsView(peer);
19671
- const scope = peer.project_scope || {};
19672
- const projectNarrowing = derivePeerProjectNarrowingView(scope);
19673
- const includeList = listText(scope.include);
19674
- const excludeList = listText(scope.exclude);
19508
+ const projectNarrowing = derivePeerProjectNarrowingView(peer.project_scope || {});
19675
19509
  const primaryAddress = pickPrimaryAddress(peer.addresses);
19676
19510
  const peerAddresses = Array.isArray(peer.addresses) ? Array.from(new Set(peer.addresses.filter(Boolean).map((value) => String(value)))) : [];
19677
19511
  const rawHiddenAddressCount = Number(peer.address_count ?? 0);
@@ -19680,11 +19514,9 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19680
19514
  const assignmentSummary = peer.actor_display_name ? `This device belongs to ${peer.claimed_local_actor ? "you" : String(peer.actor_display_name)}.` : "This device is not assigned to anyone yet.";
19681
19515
  const lastSyncAt = String(peerStatus.last_sync_at || peerStatus.last_sync_at_utc || "");
19682
19516
  const lastPingAt = String(peerStatus.last_ping_at || peerStatus.last_ping_at_utc || "");
19683
- const discoverySummary = peer.discovered_via_group_id ? `Discovery: seen through coordinator group ${peer.discovered_via_group_id}. Discovery helps find devices; Sharing-domain grants above decide data access.` : peer.discovered_via_coordinator_id ? `Discovery: seen through coordinator ${peer.discovered_via_coordinator_id}. Discovery helps find devices; Sharing-domain grants above decide data access.` : null;
19684
- const scopeEditorOpen = openPeerScopeEditors.has(peerId);
19517
+ const discoverySummary = peer.discovered_via_group_id ? `Discovery: seen through Team ${peer.discovered_via_group_id}. Discovery helps find devices; Space access above decides data access.` : peer.discovered_via_coordinator_id ? `Discovery: seen through coordinator ${peer.discovered_via_coordinator_id}. Discovery helps find devices; Space access above decides data access.` : null;
19685
19518
  const scopeReviewRequested = consumePeerScopeReviewRequest(peerId);
19686
19519
  const cardRef = A$1(null);
19687
- const [scopeHost, setScopeHost] = d$2(null);
19688
19520
  const [renameValue, setRenameValue] = d$2(displayName);
19689
19521
  const [feedback, setFeedback] = d$2(() => state.syncPeerFeedbackById.get(peerId) ?? null);
19690
19522
  const [renameBusy, setRenameBusy] = d$2(false);
@@ -19695,10 +19527,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19695
19527
  const [selectedActorId, setSelectedActorId] = d$2(String(peer.actor_id || ""));
19696
19528
  const [applyActorBusy, setApplyActorBusy] = d$2(false);
19697
19529
  const [applyActorLabel, setApplyActorLabel] = d$2("Save assignment");
19698
- const [saveScopeBusy, setSaveScopeBusy] = d$2(false);
19699
- const [saveScopeLabel, setSaveScopeLabel] = d$2("Save scope");
19700
- const [resetScopeBusy, setResetScopeBusy] = d$2(false);
19701
- const [resetScopeLabel, setResetScopeLabel] = d$2("Reset to global scope");
19702
19530
  const actorSelectOptions = T$1(() => {
19703
19531
  const options = buildActorSelectOptions(selectedActorId);
19704
19532
  const hasSelected = options.some((option) => option.value === selectedActorId);
@@ -19715,15 +19543,12 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19715
19543
  state.lastSyncPeers,
19716
19544
  state.lastSyncViewModel
19717
19545
  ]);
19718
- const includeEditor = T$1(() => createChipEditor(includeList, "Add project", "All projects", state.knownProjects), [
19719
- peerId,
19720
- includeList.join("|"),
19721
- state.knownProjects.join("|")
19722
- ]);
19723
- const excludeEditor = T$1(() => createChipEditor(excludeList, "Add project", "No exclusions", state.knownProjects), [
19546
+ y$2(() => {
19547
+ if (rawPendingScopeReview && authorizedDomains.total > 0) clearPeerScopeReview(peerId);
19548
+ }, [
19549
+ authorizedDomains.total,
19724
19550
  peerId,
19725
- excludeList.join("|"),
19726
- state.knownProjects.join("|")
19551
+ rawPendingScopeReview
19727
19552
  ]);
19728
19553
  y$2(() => {
19729
19554
  setRenameValue(displayName);
@@ -19736,16 +19561,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19736
19561
  setSelectedActorId(String(peer.actor_id || ""));
19737
19562
  setApplyActorBusy(false);
19738
19563
  setApplyActorLabel("Save assignment");
19739
- setSaveScopeBusy(false);
19740
- setSaveScopeLabel("Save scope");
19741
- setResetScopeBusy(false);
19742
- setResetScopeLabel("Reset to global scope");
19743
19564
  }, [
19744
19565
  displayName,
19745
19566
  peer.actor_id,
19746
- peerId,
19747
- includeList.join("|"),
19748
- excludeList.join("|")
19567
+ peerId
19749
19568
  ]);
19750
19569
  y$2(() => {
19751
19570
  if (!scopeReviewRequested || !cardRef.current) return;
@@ -19783,10 +19602,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19783
19602
  async function sync() {
19784
19603
  if (pendingScopeReview) {
19785
19604
  if (!await openSyncConfirmDialog({
19786
- title: `Sync ${displayName} before scope review?`,
19787
- description: "This manual sync will use the current effective scope until you finish reviewing and saving the device scope.",
19605
+ title: `Sync ${displayName} before advanced rule review?`,
19606
+ description: "This manual sync will use the current Space access and advanced filters until you review them in Teams.",
19788
19607
  confirmLabel: "Sync anyway",
19789
- cancelLabel: "Review scope first"
19608
+ cancelLabel: "Review in Teams first"
19790
19609
  })) return;
19791
19610
  }
19792
19611
  setSyncBusy(true);
@@ -19835,36 +19654,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19835
19654
  setApplyActorBusy(false);
19836
19655
  }
19837
19656
  }
19838
- async function saveScope() {
19839
- if (!peerId) return;
19840
- setSaveScopeBusy(true);
19841
- setSaveScopeLabel("Saving…");
19842
- try {
19843
- const nextFeedback = await onSaveScope(peerId, includeEditor.values(), excludeEditor.values());
19844
- setFeedback(nextFeedback);
19845
- state.syncPeerFeedbackById.set(peerId, nextFeedback);
19846
- setSaveScopeLabel("Save scope");
19847
- } catch {
19848
- setSaveScopeLabel("Retry");
19849
- } finally {
19850
- setSaveScopeBusy(false);
19851
- }
19852
- }
19853
- async function resetScope() {
19854
- if (!peerId) return;
19855
- setResetScopeBusy(true);
19856
- setResetScopeLabel("Resetting…");
19857
- try {
19858
- const nextFeedback = await onResetScope(peerId);
19859
- setFeedback(nextFeedback);
19860
- state.syncPeerFeedbackById.set(peerId, nextFeedback);
19861
- setResetScopeLabel("Reset to global scope");
19862
- } catch {
19863
- setResetScopeLabel("Retry");
19864
- } finally {
19865
- setResetScopeBusy(false);
19866
- }
19867
- }
19868
19657
  const isExpanded = useExpandedPeer() === peerId && peerId !== "";
19869
19658
  const drawerId = `device-drawer-${peerId || "unknown"}`;
19870
19659
  const presenceState = presenceForPeer(peer);
@@ -19911,11 +19700,11 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19911
19700
  }),
19912
19701
  pendingScopeReview ? /* @__PURE__ */ u("span", {
19913
19702
  className: "badge actor-badge",
19914
- children: "Needs scope review"
19703
+ children: "Review advanced rules"
19915
19704
  }) : null,
19916
19705
  /* @__PURE__ */ u("span", {
19917
19706
  className: `badge ${authorizedDomains.isWarning ? "badge-offline" : "actor-badge"}`,
19918
- title: "Sharing domains are the hard access boundary; project filters only narrow inside them.",
19707
+ title: "Spaces are the hard access boundary; advanced filters only narrow inside them.",
19919
19708
  children: authorizedDomains.badgeLabel
19920
19709
  }),
19921
19710
  scopeRejections.badgeLabel ? /* @__PURE__ */ u("span", {
@@ -19925,7 +19714,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19925
19714
  }) : null,
19926
19715
  grantRoleMismatch.badgeLabel ? /* @__PURE__ */ u("span", {
19927
19716
  className: "badge badge-offline",
19928
- title: "Review whether explicit Sharing-domain grants match this device's intended role.",
19717
+ title: "Review whether explicit Space access matches this device's intended role.",
19929
19718
  children: grantRoleMismatch.badgeLabel
19930
19719
  }) : null,
19931
19720
  peer.discovered_via_group_id ? /* @__PURE__ */ u("span", {
@@ -19999,10 +19788,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19999
19788
  children: [
20000
19789
  scopeReviewRequested ? /* @__PURE__ */ u("div", {
20001
19790
  className: "peer-meta",
20002
- children: "Review this device's sharing rules now if the defaults are too broad."
19791
+ children: "Review this device's Space access and advanced rules in Teams if the defaults are too broad."
20003
19792
  }) : pendingScopeReview ? /* @__PURE__ */ u("div", {
20004
19793
  className: "peer-meta",
20005
- children: "Sharing rule review is still pending for this device."
19794
+ children: "Advanced rule review is still pending for this device."
20006
19795
  }) : null,
20007
19796
  /* @__PURE__ */ u("div", {
20008
19797
  className: "peer-scope-summary",
@@ -20022,15 +19811,15 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20022
19811
  }),
20023
19812
  /* @__PURE__ */ u("div", {
20024
19813
  className: "peer-scope-summary",
20025
- children: "Authorized Sharing domains"
19814
+ children: "Space access"
20026
19815
  }),
20027
19816
  /* @__PURE__ */ u("div", {
20028
19817
  className: "peer-meta",
20029
- children: authorizedDomains.total > 0 ? "These Sharing domains are the hard access boundary for this device." : authorizedDomains.emptyMessage
19818
+ children: authorizedDomains.total > 0 ? "These Spaces are the hard access boundary for this device." : authorizedDomains.emptyMessage
20030
19819
  }),
20031
19820
  authorizedDomains.domains.length > 0 ? /* @__PURE__ */ u("ul", {
20032
19821
  className: "peer-scope-chips",
20033
- "aria-label": "Authorized Sharing domains",
19822
+ "aria-label": "Authorized Spaces",
20034
19823
  children: authorizedDomains.domains.map((domain) => /* @__PURE__ */ u("li", {
20035
19824
  className: "peer-scope-chip",
20036
19825
  title: domain.detail,
@@ -20116,41 +19905,28 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20116
19905
  }),
20117
19906
  /* @__PURE__ */ u("div", {
20118
19907
  className: "peer-scope-summary",
20119
- children: "Project filters (narrowing only)"
19908
+ children: "Advanced sharing rules"
20120
19909
  }),
20121
19910
  /* @__PURE__ */ u("div", {
20122
19911
  className: "peer-meta",
20123
- children: [projectNarrowing.summary, " Review or tighten these filters when this device should receive fewer projects from its authorized Sharing domains."]
19912
+ children: [
19913
+ projectNarrowing.statusLabel,
19914
+ ". ",
19915
+ projectNarrowing.summary,
19916
+ " ",
19917
+ projectNarrowing.note
19918
+ ]
20124
19919
  }),
20125
- /* @__PURE__ */ u(PeerScopeCollapsible, {
20126
- contentHost: scopeHost,
20127
- initialOpen: scopeEditorOpen,
20128
- onOpenChange: (open) => {
20129
- if (open) openPeerScopeEditors.add(peerId);
20130
- else openPeerScopeEditors.delete(peerId);
20131
- },
20132
- children: /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ u("div", {
20133
- className: "peer-scope-row",
20134
- children: [/* @__PURE__ */ u(ExistingElementSlot$1, { element: includeEditor.element }), /* @__PURE__ */ u(ExistingElementSlot$1, { element: excludeEditor.element })]
20135
- }), /* @__PURE__ */ u("div", {
20136
- className: "peer-scope-actions",
20137
- children: [/* @__PURE__ */ u("button", {
20138
- type: "button",
20139
- className: "settings-button",
20140
- disabled: saveScopeBusy,
20141
- onClick: () => void saveScope(),
20142
- children: saveScopeLabel
20143
- }), /* @__PURE__ */ u("button", {
20144
- type: "button",
20145
- className: "settings-button",
20146
- disabled: resetScopeBusy,
20147
- onClick: () => void resetScope(),
20148
- children: resetScopeLabel
20149
- })]
20150
- })] })
19920
+ /* @__PURE__ */ u("div", {
19921
+ className: "peer-actions",
19922
+ children: /* @__PURE__ */ u("button", {
19923
+ type: "button",
19924
+ className: "settings-button",
19925
+ onClick: openTeamsAccessManagement,
19926
+ children: "Manage Spaces in Teams"
19927
+ })
20151
19928
  }),
20152
- /* @__PURE__ */ u(SyncInlineFeedback, { feedback }),
20153
- /* @__PURE__ */ u("div", { ref: setScopeHost })
19929
+ /* @__PURE__ */ u(SyncInlineFeedback, { feedback })
20154
19930
  ]
20155
19931
  })]
20156
19932
  })]
@@ -20249,8 +20025,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20249
20025
  if (!syncPeers) return;
20250
20026
  hideSkeleton("syncPeersSkeleton");
20251
20027
  const peers = state.lastSyncPeers;
20028
+ const peersArray = Array.isArray(peers) ? peers : [];
20029
+ if (shouldClearStalePeersFeedback(state.syncPeersSectionFeedback, peersArray)) state.syncPeersSectionFeedback = null;
20252
20030
  renderSyncPeersList(syncPeers, {
20253
- peers: Array.isArray(peers) ? peers : [],
20031
+ peers: peersArray,
20254
20032
  onRename: async (peerId, nextName) => {
20255
20033
  try {
20256
20034
  await renamePeer(peerId, nextName);
@@ -20279,7 +20057,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20279
20057
  tone: "warning"
20280
20058
  };
20281
20059
  else if (peerId && isPeerScopeReviewPending(peerId)) feedback = {
20282
- message: `Triggered sync for ${peer?.name || (peerId ? peerId.slice(0, 8) : "unknown")}. Review scope in this card if you want tighter sharing rules.`,
20060
+ message: `Triggered sync for ${peer?.name || (peerId ? peerId.slice(0, 8) : "unknown")}. Review Space access and advanced rules in Teams if this device needs tighter sharing.`,
20283
20061
  tone: "warning"
20284
20062
  };
20285
20063
  else feedback = {
@@ -20310,7 +20088,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20310
20088
  tone: "success"
20311
20089
  };
20312
20090
  state.syncPeerFeedbackById.delete(peerId);
20313
- state.syncPeersSectionFeedback = feedback;
20091
+ state.syncPeersSectionFeedback = {
20092
+ ...feedback,
20093
+ relatedPeerDeviceId: peerId
20094
+ };
20314
20095
  await _loadSyncData();
20315
20096
  return feedback;
20316
20097
  } catch (error) {
@@ -20334,38 +20115,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20334
20115
  tone: "warning"
20335
20116
  };
20336
20117
  }
20337
- },
20338
- onSaveScope: async (peerId, include, exclude) => {
20339
- try {
20340
- await updatePeerScope(peerId, include, exclude);
20341
- clearPeerScopeReview(peerId);
20342
- await _loadSyncData();
20343
- return {
20344
- message: "Device sync scope saved.",
20345
- tone: "success"
20346
- };
20347
- } catch (error) {
20348
- return {
20349
- message: friendlyError(error, "Failed to save device scope. The current sharing rules are still active."),
20350
- tone: "warning"
20351
- };
20352
- }
20353
- },
20354
- onResetScope: async (peerId) => {
20355
- try {
20356
- await updatePeerScope(peerId, null, null, true);
20357
- clearPeerScopeReview(peerId);
20358
- await _loadSyncData();
20359
- return {
20360
- message: "Device sync scope reset to global defaults.",
20361
- tone: "success"
20362
- };
20363
- } catch (error) {
20364
- return {
20365
- message: friendlyError(error, "Failed to reset device scope. The current sharing rules are still active."),
20366
- tone: "warning"
20367
- };
20368
- }
20369
20118
  }
20370
20119
  });
20371
20120
  }
@@ -20988,10 +20737,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20988
20737
  onClick: async () => {
20989
20738
  setBusy("review");
20990
20739
  setReviewLabel("Pairing…");
20740
+ setFeedback({
20741
+ message: `Pairing ${row.displayName}. Keep this page open while the device is approved and refreshed.`,
20742
+ tone: "success"
20743
+ });
20991
20744
  try {
20992
20745
  setFeedback(await onReview(row) || null);
20993
20746
  setReviewLabel(row.actionLabel || defaultReviewLabel);
20994
20747
  } catch {
20748
+ setFeedback({
20749
+ message: `Pairing ${row.displayName} failed. Try again.`,
20750
+ tone: "warning"
20751
+ });
20995
20752
  setReviewLabel("Retry");
20996
20753
  } finally {
20997
20754
  setBusy(null);
@@ -21366,7 +21123,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21366
21123
  actionMessage = "This device appears in multiple coordinator groups. Review team setup first or ask an admin to clean up the duplicate enrollment before approving it here.";
21367
21124
  mode = "ambiguous";
21368
21125
  } else if (pairedPeer && isPeerScopeReviewPending(deviceId)) {
21369
- actionMessage = `Finish this device's scope review in People & devices before you sync it.`;
21126
+ actionMessage = "Review this device's Space access and advanced rules in Teams before you sync it.";
21370
21127
  mode = "scope-pending";
21371
21128
  } else if (pairedPeer?.last_error) {
21372
21129
  noteParts.push(`error: ${String(pairedPeer.last_error)}`);
@@ -21554,14 +21311,41 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21554
21311
  const label = group.displayProject.toLowerCase();
21555
21312
  return label.includes("fatal:") || label.includes("not a git repository") || label === "unknown project" || group.identitySource === "unmapped";
21556
21313
  }
21314
+ function displayProjectTitle(group) {
21315
+ return needsProjectCleanup(group) ? "Unclear project identity" : group.displayProject;
21316
+ }
21557
21317
  function canReassignLegacyGroup(group) {
21558
21318
  return (group.reassignableMemoryCount ?? group.memoryCount) > 0;
21559
21319
  }
21560
- function groupSearchText(group) {
21320
+ function suggestedScopeText(group, targetScopes) {
21321
+ if (!group.suggestedScopeId) return "";
21322
+ return ` · suggested ${targetScopes.find((scope) => scope.scopeId === group.suggestedScopeId)?.label || "Space"}`;
21323
+ }
21324
+ function escapeRegExp(value) {
21325
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
21326
+ }
21327
+ function targetScopeLabel(scopeId, targetScopes) {
21328
+ return targetScopes.find((scope) => scope.scopeId === scopeId)?.label || "selected Space";
21329
+ }
21330
+ function authorityLabel(authorityType) {
21331
+ switch (authorityType) {
21332
+ case "coordinator": return "Team Space";
21333
+ case "local": return "Local Space";
21334
+ default: return "Other Space";
21335
+ }
21336
+ }
21337
+ function formatLegacyReviewError(error, scopeId, targetScopes) {
21338
+ let result = (error instanceof Error ? error.message : "Unable to reassign legacy review memories.").replace(/sharing domain/gi, "Space");
21339
+ if (scopeId) result = result.replace(new RegExp(`\\b${escapeRegExp(scopeId)}\\b`, "g"), targetScopeLabel(scopeId, targetScopes));
21340
+ return result;
21341
+ }
21342
+ function groupSearchText(group, targetScopes) {
21343
+ const suggestedScopeLabel = group.suggestedScopeId ? targetScopes.find((scope) => scope.scopeId === group.suggestedScopeId)?.label : "";
21561
21344
  return [
21562
21345
  group.displayProject,
21563
21346
  group.identitySource,
21564
21347
  group.suggestedScopeId ?? "",
21348
+ suggestedScopeLabel ?? "",
21565
21349
  group.suggestionReason ?? "",
21566
21350
  group.workspaceIdentity
21567
21351
  ].join(" ").toLowerCase();
@@ -21622,7 +21406,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21622
21406
  if (filter === "cleanup" && !cleanup) return false;
21623
21407
  if (filter === "no-suggestion" && (group.suggestedScopeId || cleanup)) return false;
21624
21408
  if (filter === "selected" && !selectedGroups[group.workspaceIdentity]) return false;
21625
- return !query.trim() || groupSearchText(group).includes(query.trim().toLowerCase());
21409
+ return !query.trim() || groupSearchText(group, targetScopes).includes(query.trim().toLowerCase());
21626
21410
  });
21627
21411
  async function applyGroup(group) {
21628
21412
  const selectedScopeId = selectedScopes[group.workspaceIdentity] || group.suggestedScopeId || "";
@@ -21647,7 +21431,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21647
21431
  } catch (error) {
21648
21432
  setErrors((current) => ({
21649
21433
  ...current,
21650
- [group.workspaceIdentity]: error instanceof Error ? error.message : "Unable to reassign legacy review memories."
21434
+ [group.workspaceIdentity]: formatLegacyReviewError(error, selectedScopeId, targetScopes)
21651
21435
  }));
21652
21436
  } finally {
21653
21437
  setBusyIdentity(null);
@@ -21711,7 +21495,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21711
21495
  } catch (error) {
21712
21496
  setErrors((current) => ({
21713
21497
  ...current,
21714
- [group.workspaceIdentity]: error instanceof Error ? error.message : "Unable to reassign legacy review memories."
21498
+ [group.workspaceIdentity]: formatLegacyReviewError(error, selectedScopeId, targetScopes)
21715
21499
  }));
21716
21500
  }
21717
21501
  }
@@ -21739,7 +21523,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21739
21523
  " older",
21740
21524
  " ",
21741
21525
  groupCount === 1 ? "project needs" : "projects need",
21742
- " a Sharing domain. They contain",
21526
+ " a Space. They contain",
21743
21527
  " ",
21744
21528
  item.memoryCount.toLocaleString(),
21745
21529
  " older shared memories total; review the projects, not individual memories.",
@@ -21812,7 +21596,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21812
21596
  children: busyIdentity === "bulk" ? "Previewing…" : `Preview ${selectedCount.toLocaleString()} selected`
21813
21597
  }) : onReassign && selectedReassignableCount > 0 ? /* @__PURE__ */ u("span", {
21814
21598
  className: "legacy-review-cleanup-note",
21815
- children: "Add or join a Sharing domain before bulk reassignment."
21599
+ children: "Add or join a Space before bulk reassignment."
21816
21600
  }) : null,
21817
21601
  selectedCount > 0 && groups.filter((group) => selectedGroups[group.workspaceIdentity] && canReassignLegacyGroup(group) && Boolean(selectedScopes[group.workspaceIdentity])).every((group) => pending[group.workspaceIdentity]) ? /* @__PURE__ */ u("span", {
21818
21602
  className: "legacy-review-cleanup-note",
@@ -21832,7 +21616,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21832
21616
  children: [/* @__PURE__ */ u("div", {
21833
21617
  className: "legacy-review-title-wrap",
21834
21618
  children: [/* @__PURE__ */ u("input", {
21835
- "aria-label": `Select ${group.displayProject}`,
21619
+ "aria-label": `Select ${displayProjectTitle(group)}`,
21836
21620
  checked: Boolean(selectedGroups[group.workspaceIdentity]),
21837
21621
  className: "cm-checkbox",
21838
21622
  disabled: !canReassignLegacyGroup(group),
@@ -21841,15 +21625,15 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21841
21625
  }), /* @__PURE__ */ u("div", { children: [
21842
21626
  /* @__PURE__ */ u("div", {
21843
21627
  className: "legacy-review-group-title",
21844
- children: group.displayProject
21628
+ children: displayProjectTitle(group)
21845
21629
  }),
21846
21630
  /* @__PURE__ */ u("div", {
21847
21631
  className: "legacy-review-group-meta",
21848
- children: [formatIdentitySource(group.identitySource), group.suggestedScopeId ? ` · suggested ${group.suggestedScopeId}` : ""]
21632
+ children: [formatIdentitySource(group.identitySource), suggestedScopeText(group, targetScopes)]
21849
21633
  }),
21850
21634
  !canReassignLegacyGroup(group) ? /* @__PURE__ */ u("div", {
21851
21635
  className: "legacy-review-cleanup-note",
21852
- children: "Peer-owned only. These older memories were received from another device, so this device cannot reassign them to a Sharing domain."
21636
+ children: "Peer-owned only. These older memories were received from another device, so this device cannot reassign them to a Space."
21853
21637
  }) : group.peerOwnedMemoryCount ? /* @__PURE__ */ u("div", {
21854
21638
  className: "legacy-review-cleanup-note",
21855
21639
  children: [
@@ -21867,7 +21651,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21867
21651
  }) : null,
21868
21652
  needsProjectCleanup(group) ? /* @__PURE__ */ u("div", {
21869
21653
  className: "legacy-review-cleanup-note",
21870
- children: "Unclear project identity. Inspect or correct the project before trusting a domain."
21654
+ children: "Inspect or correct the project identity before assigning old shared data to a Space."
21871
21655
  }) : null
21872
21656
  ] })]
21873
21657
  }), /* @__PURE__ */ u("span", {
@@ -21906,20 +21690,20 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21906
21690
  }) : null,
21907
21691
  targetScopes.length > 0 && onReassign && canReassignLegacyGroup(group) ? /* @__PURE__ */ u("label", {
21908
21692
  className: "legacy-review-target",
21909
- children: [/* @__PURE__ */ u("span", { children: "Destination Sharing domain" }), /* @__PURE__ */ u("select", {
21693
+ children: [/* @__PURE__ */ u("span", { children: "Destination Space" }), /* @__PURE__ */ u("select", {
21910
21694
  className: "peer-scope-input",
21911
21695
  disabled: busyIdentity != null,
21912
21696
  onChange: (event) => updateSelectedScope(group, event.currentTarget.value),
21913
21697
  value: selectedScopes[group.workspaceIdentity] || "",
21914
21698
  children: [/* @__PURE__ */ u("option", {
21915
21699
  value: "",
21916
- children: "Choose domain…"
21700
+ children: "Choose Space…"
21917
21701
  }), targetScopes.map((scope) => /* @__PURE__ */ u("option", {
21918
21702
  value: scope.scopeId,
21919
21703
  children: [
21920
21704
  scope.label,
21921
21705
  " · ",
21922
- scope.authorityType,
21706
+ authorityLabel(scope.authorityType),
21923
21707
  scope.scopeId === group.suggestedScopeId ? " · suggested" : ""
21924
21708
  ]
21925
21709
  }, scope.scopeId))]
@@ -22222,7 +22006,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
22222
22006
  try {
22223
22007
  const runtime = await loadRuntimeInfo();
22224
22008
  if (!runtime?.version) return;
22225
- setRuntimeLabel(runtime.version, "882d43d");
22009
+ setRuntimeLabel(runtime.version, "c8fe0f7");
22226
22010
  } catch {}
22227
22011
  }
22228
22012
  var lastAnnouncedRefreshState = null;