@codemem/server 0.33.0-alpha.1 → 0.33.0-alpha.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAKX,WAAW,EAIX,MAAM,eAAe,CAAC;AAuFvB,OAAO,EAAgB,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAE3E,KAAK,YAAY,GAAG,MAAM,WAAW,CAAC;AACtC,KAAK,iBAAiB,GAAG;IACxB,KAAK,EACF,UAAU,GACV,SAAS,GACT,UAAU,GACV,OAAO,GACP,UAAU,GACV,iBAAiB,GACjB,iBAAiB,GACjB,IAAI,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAoBF,UAAU,wBAAwB;IACjC,cAAc,CAAC,EAAE;QAChB,OAAO,EAAE,0BAA0B,CAAC;QACpC,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,wBAAwB,EAAE,MAAM,CAAC;QACjC,4BAA4B,EAAE,MAAM,CAAC;KACrC,CAAC;CACF;AA+2DD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,GAAE,wBAA6B,8EAiZ7F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,QAAQ,EAAE,YAAY,EACtB,oBAAoB,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,8EAwqErD"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAKX,WAAW,EAIX,MAAM,eAAe,CAAC;AAuFvB,OAAO,EAAgB,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAE3E,KAAK,YAAY,GAAG,MAAM,WAAW,CAAC;AACtC,KAAK,iBAAiB,GAAG;IACxB,KAAK,EACF,UAAU,GACV,SAAS,GACT,UAAU,GACV,OAAO,GACP,UAAU,GACV,iBAAiB,GACjB,iBAAiB,GACjB,IAAI,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAoBF,UAAU,wBAAwB;IACjC,cAAc,CAAC,EAAE;QAChB,OAAO,EAAE,0BAA0B,CAAC;QACpC,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,wBAAwB,EAAE,MAAM,CAAC;QACjC,4BAA4B,EAAE,MAAM,CAAC;KACrC,CAAC;CACF;AAi3DD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,GAAE,wBAA6B,8EAiZ7F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,QAAQ,EAAE,YAAY,EACtB,oBAAoB,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,8EA0qErD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemem/server",
3
- "version": "0.33.0-alpha.1",
3
+ "version": "0.33.0-alpha.3",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  "drizzle-orm": "^0.45.2",
20
20
  "hono": "^4.12.21",
21
21
  "limiter": "^3.0.0",
22
- "@codemem/core": "^0.33.0-alpha.1"
22
+ "@codemem/core": "^0.33.0-alpha.3"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/better-sqlite3": "^7.6.13",
package/static/app.js CHANGED
@@ -14616,6 +14616,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
14616
14616
  ["needs_attention", "Needs review"],
14617
14617
  ["suggested", "Has suggestion"],
14618
14618
  ["local_only", "Stays on this device"],
14619
+ ["received", "Received from peers"],
14619
14620
  ["explicitly_mapped", "Already assigned"],
14620
14621
  ["legacy_review", "Older shared data"],
14621
14622
  ["unmapped", "Missing project identity"]
@@ -14645,6 +14646,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
14645
14646
  default: return "stays on this device";
14646
14647
  }
14647
14648
  }
14649
+ function isPeerReceivedProject(project) {
14650
+ return project.read_only === true && project.read_only_reason === "peer_received";
14651
+ }
14652
+ function isLocallyAssignableProject(project) {
14653
+ return project.identity_source !== "unmapped" && !isPeerReceivedProject(project);
14654
+ }
14655
+ function projectDomainLabel(project) {
14656
+ return isPeerReceivedProject(project) ? "Received from peers" : scopeSummary(project.resolved_scope_id);
14657
+ }
14658
+ function projectResolutionLabel(project) {
14659
+ return isPeerReceivedProject(project) ? "source-owned project" : formatResolution(project.resolution_reason);
14660
+ }
14648
14661
  function formatLatest(value) {
14649
14662
  if (!value) return "No recent sessions";
14650
14663
  const date = new Date(value);
@@ -14823,7 +14836,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
14823
14836
  }
14824
14837
  }
14825
14838
  async function saveProjectClusterMapping(projects, scopeId) {
14826
- const assignable = projects.filter((project) => project.identity_source !== "unmapped");
14839
+ const assignable = projects.filter(isLocallyAssignableProject);
14827
14840
  if (assignable.length === 0) return;
14828
14841
  try {
14829
14842
  await saveSharingDomainProjectMappings({ mappings: assignable.map((project) => ({
@@ -14911,6 +14924,13 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
14911
14924
  function renderProjectActions(project) {
14912
14925
  const actions = document.createElement("div");
14913
14926
  actions.className = "project-inventory-actions";
14927
+ if (isPeerReceivedProject(project)) {
14928
+ const note = document.createElement("div");
14929
+ note.className = "settings-note";
14930
+ note.textContent = "This project was received from a peer. Change its project or Space on the source device; this node keeps the received identity read-only.";
14931
+ actions.appendChild(note);
14932
+ return actions;
14933
+ }
14914
14934
  if (project.identity_source === "unmapped") {
14915
14935
  const note = document.createElement("div");
14916
14936
  note.className = "settings-note";
@@ -15055,13 +15075,19 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15055
15075
  header.appendChild(title);
15056
15076
  const domain = document.createElement("div");
15057
15077
  domain.className = "project-inventory-domain";
15058
- domain.textContent = scopeSummary(project.resolved_scope_id);
15078
+ domain.textContent = projectDomainLabel(project);
15059
15079
  header.appendChild(domain);
15060
15080
  row.appendChild(header);
15061
15081
  const meta = document.createElement("div");
15062
15082
  meta.className = "project-inventory-meta";
15063
- meta.textContent = `${formatResolution(project.resolution_reason)} · ${project.identity_source} · ${formatLatest(project.latest_session_at)}`;
15083
+ meta.textContent = `${projectResolutionLabel(project)} · ${project.identity_source} · ${formatLatest(project.latest_session_at)}`;
15064
15084
  row.appendChild(meta);
15085
+ if (isPeerReceivedProject(project)) {
15086
+ const receivedNote = document.createElement("div");
15087
+ receivedNote.className = "settings-note";
15088
+ receivedNote.textContent = "Received memories keep the source device's project and Space assignment. Local reassignment controls are disabled here to avoid split-brain sync state.";
15089
+ row.appendChild(receivedNote);
15090
+ }
15065
15091
  const signal = document.createElement("div");
15066
15092
  signal.className = "project-inventory-signal mono";
15067
15093
  signal.textContent = strongestSignal(project);
@@ -15072,7 +15098,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15072
15098
  suggestion.textContent = project.suggestion_reason ? `Suggestion: ${project.suggestion_reason}` : `Suggestion: assign this project to ${scopeSummary(project.suggested_scope_id)}.`;
15073
15099
  row.appendChild(suggestion);
15074
15100
  }
15075
- const warnings = project.guardrail_warnings.filter((warning) => warning.severity === "warning");
15101
+ const warnings = (project.guardrail_warnings ?? []).filter((warning) => warning.severity === "warning");
15076
15102
  if (warnings.length > 0) {
15077
15103
  const warningBox = document.createElement("div");
15078
15104
  warningBox.className = "settings-note project-attention-note";
@@ -15108,7 +15134,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15108
15134
  ["CWD", project.cwd],
15109
15135
  ["Git remote", project.git_remote],
15110
15136
  ["Git branch", project.git_branch],
15111
- ["Current Space", scopeSummary(project.resolved_scope_id)],
15137
+ ["Current Space", projectDomainLabel(project)],
15112
15138
  ["Suggested Space", project.suggested_scope_id ? scopeSummary(project.suggested_scope_id) : null],
15113
15139
  ["Advanced: current Space ID", project.resolved_scope_id],
15114
15140
  ["Advanced: suggested Space ID", project.suggested_scope_id],
@@ -15129,8 +15155,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15129
15155
  return row;
15130
15156
  }
15131
15157
  function clusterDomainLabel(projects) {
15132
- const uniqueScopes = [...new Set(projects.map((project) => project.resolved_scope_id))];
15133
- return uniqueScopes.length === 1 ? scopeSummary(uniqueScopes[0]) : "Mixed Spaces";
15158
+ const uniqueLabels = [...new Set(projects.map((project) => projectDomainLabel(project)))];
15159
+ return uniqueLabels.length === 1 ? uniqueLabels[0] : "Mixed Spaces";
15134
15160
  }
15135
15161
  function renderProjectCluster(projects) {
15136
15162
  if (projects.length === 1) return renderProjectRow(projects[0]);
@@ -15156,36 +15182,45 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15156
15182
  row.appendChild(meta);
15157
15183
  const actions = document.createElement("div");
15158
15184
  actions.className = "project-inventory-actions";
15159
- const hasGuardrailWarnings = projects.some((project) => project.guardrail_warnings.length > 0);
15160
- const suggestedScopes = new Set(projects.map((project) => project.suggested_scope_id).filter((scopeId) => Boolean(scopeId)));
15161
- const resolvedScopes = new Set(projects.map((project) => project.resolved_scope_id));
15162
- const select = document.createElement("select");
15163
- select.className = "project-domain-select";
15164
- select.setAttribute("aria-label", `Space for ${projectClusterLabel(projects[0])} group`);
15165
- const placeholder = document.createElement("option");
15166
- placeholder.value = "";
15167
- placeholder.textContent = "Choose Space…";
15168
- select.appendChild(placeholder);
15169
- appendAssignableScopeOptions(select);
15170
- select.value = "";
15171
- const save = document.createElement("button");
15172
- save.className = "settings-button";
15173
- save.type = "button";
15174
- save.textContent = `Save Space for ${projects.length} identities`;
15175
- save.disabled = true;
15176
- save.addEventListener("click", () => void saveProjectClusterMapping(projects, select.value));
15177
- select.addEventListener("change", () => {
15178
- save.disabled = !select.value || hasGuardrailWarnings;
15179
- });
15180
- select.addEventListener("blur", refreshSkippedProjectDataAfterSelectBlur);
15181
- actions.append(select, save);
15182
- if (suggestedScopes.size > 1 || resolvedScopes.size > 1 || hasGuardrailWarnings) {
15185
+ const assignableProjects = projects.filter(isLocallyAssignableProject);
15186
+ if (assignableProjects.length === 0) {
15183
15187
  const note = document.createElement("div");
15184
- note.className = "settings-note project-attention-note";
15185
- note.textContent = hasGuardrailWarnings ? "One or more identities in this group need individual review before bulk assignment." : "This group has mixed suggestions or current Spaces. Choose a Space explicitly before bulk assignment.";
15188
+ note.className = "settings-note";
15189
+ note.textContent = projects.every(isPeerReceivedProject) ? "These project identities were received from peers. Change project or Space assignments on their source devices." : "These project identities cannot be bulk assigned until they have stable local identities. Expand each identity for details.";
15186
15190
  actions.appendChild(note);
15191
+ row.appendChild(actions);
15192
+ } else {
15193
+ const hasGuardrailWarnings = assignableProjects.some((project) => (project.guardrail_warnings ?? []).length > 0);
15194
+ const suggestedScopes = new Set(assignableProjects.map((project) => project.suggested_scope_id).filter((scopeId) => Boolean(scopeId)));
15195
+ const resolvedScopes = new Set(assignableProjects.map((project) => project.resolved_scope_id));
15196
+ const select = document.createElement("select");
15197
+ select.className = "project-domain-select";
15198
+ select.setAttribute("aria-label", `Space for ${projectClusterLabel(projects[0])} group`);
15199
+ const placeholder = document.createElement("option");
15200
+ placeholder.value = "";
15201
+ placeholder.textContent = "Choose Space…";
15202
+ select.appendChild(placeholder);
15203
+ appendAssignableScopeOptions(select);
15204
+ select.value = "";
15205
+ const save = document.createElement("button");
15206
+ save.className = "settings-button";
15207
+ save.type = "button";
15208
+ save.textContent = `Save Space for ${assignableProjects.length} identit${assignableProjects.length === 1 ? "y" : "ies"}`;
15209
+ save.disabled = true;
15210
+ save.addEventListener("click", () => void saveProjectClusterMapping(assignableProjects, select.value));
15211
+ select.addEventListener("change", () => {
15212
+ save.disabled = !select.value || hasGuardrailWarnings;
15213
+ });
15214
+ select.addEventListener("blur", refreshSkippedProjectDataAfterSelectBlur);
15215
+ actions.append(select, save);
15216
+ if (suggestedScopes.size > 1 || resolvedScopes.size > 1 || hasGuardrailWarnings) {
15217
+ const note = document.createElement("div");
15218
+ note.className = "settings-note project-attention-note";
15219
+ note.textContent = hasGuardrailWarnings ? "One or more identities in this group need individual review before bulk assignment." : "This group has mixed suggestions or current Spaces. Choose a Space explicitly before bulk assignment.";
15220
+ actions.appendChild(note);
15221
+ }
15222
+ row.appendChild(actions);
15187
15223
  }
15188
- row.appendChild(actions);
15189
15224
  const details = document.createElement("details");
15190
15225
  details.className = "project-inventory-details";
15191
15226
  details.open = openProjectClusters.has(clusterKey);
@@ -18841,6 +18876,9 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18841
18876
  }
18842
18877
  //#endregion
18843
18878
  //#region src/tabs/sync/diagnostics/render/sync-attempts.ts
18879
+ function shouldShowSyncAttemptRedactionHint(attempt, redact) {
18880
+ return redact && attempt.error_redacted === true;
18881
+ }
18844
18882
  function renderSyncAttempts() {
18845
18883
  const syncAttempts = document.getElementById("syncAttempts");
18846
18884
  if (!syncAttempts) return;
@@ -18862,6 +18900,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18862
18900
  if (isError && attempt.error) {
18863
18901
  const errText = String(attempt.error);
18864
18902
  detailParts.push(redact ? redactIpOctets(errText) : errText);
18903
+ if (shouldShowSyncAttemptRedactionHint(attempt, redact)) detailParts.push("Turn off Redact in Advanced diagnostics to reveal the full error.");
18865
18904
  }
18866
18905
  if (!isError && (attempt.ops_in || attempt.ops_out)) detailParts.push(`${attempt.ops_in ?? 0} in · ${attempt.ops_out ?? 0} out`);
18867
18906
  if (!redact && attempt.address) detailParts.push(attempt.address);
@@ -19492,6 +19531,9 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19492
19531
  function openTeamsAccessManagement() {
19493
19532
  window.location.hash = "coordinator-admin";
19494
19533
  }
19534
+ function canManageSpacesInTeams(status = state.lastCoordinatorAdminStatus) {
19535
+ return status?.readiness === "ready" && status.has_admin_secret === true;
19536
+ }
19495
19537
  function SyncPeerCard({ peer, onAssignActor, onRemove, onRename, onSync }) {
19496
19538
  const peerId = String(peer.peer_device_id || "");
19497
19539
  const displayName = peer.name || (peerId ? peerId.slice(0, 8) : "unknown");
@@ -19600,11 +19642,12 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19600
19642
  }
19601
19643
  async function sync() {
19602
19644
  if (pendingScopeReview) {
19645
+ const canReviewInTeams = canManageSpacesInTeams();
19603
19646
  if (!await openSyncConfirmDialog({
19604
19647
  title: `Sync ${displayName} before advanced rule review?`,
19605
- description: "This manual sync will use the current Space access and advanced filters until you review them in Teams.",
19648
+ description: canReviewInTeams ? "This manual sync will use the current Space access and advanced filters until you review them in Teams." : "This manual sync will use the current Space access and advanced filters until a coordinator or manager reviews them in Teams.",
19606
19649
  confirmLabel: "Sync anyway",
19607
- cancelLabel: "Review in Teams first"
19650
+ cancelLabel: canReviewInTeams ? "Review in Teams first" : "Cancel"
19608
19651
  })) return;
19609
19652
  }
19610
19653
  setSyncBusy(true);
@@ -19657,6 +19700,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19657
19700
  const drawerId = `device-drawer-${peerId || "unknown"}`;
19658
19701
  const presenceState = presenceForPeer(peer);
19659
19702
  const syncMetaText = lastSyncAt ? `Sync: ${formatTimestamp(lastSyncAt)}` : "Sync: never";
19703
+ const canManageSpaces = canManageSpacesInTeams();
19660
19704
  const toggleLabel = `${isExpanded ? "Collapse" : "Expand"} device ${displayName}`;
19661
19705
  const handleOpenChange = (open) => {
19662
19706
  if (open) setExpandedPeer(peerId);
@@ -19787,7 +19831,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19787
19831
  children: [
19788
19832
  scopeReviewRequested ? /* @__PURE__ */ u("div", {
19789
19833
  className: "peer-meta",
19790
- children: "Review this device's Space access and advanced rules in Teams if the defaults are too broad."
19834
+ children: canManageSpaces ? "Review this device's Space access and advanced rules in Teams if the defaults are too broad." : "A coordinator or manager can review this device's Space access and advanced rules in Teams if the defaults are too broad."
19791
19835
  }) : pendingScopeReview ? /* @__PURE__ */ u("div", {
19792
19836
  className: "peer-meta",
19793
19837
  children: "Advanced rule review is still pending for this device."
@@ -19916,7 +19960,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19916
19960
  projectNarrowing.note
19917
19961
  ]
19918
19962
  }),
19919
- /* @__PURE__ */ u("div", {
19963
+ canManageSpaces ? /* @__PURE__ */ u("div", {
19920
19964
  className: "peer-actions",
19921
19965
  children: /* @__PURE__ */ u("button", {
19922
19966
  type: "button",
@@ -19924,6 +19968,9 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
19924
19968
  onClick: openTeamsAccessManagement,
19925
19969
  children: "Manage Spaces in Teams"
19926
19970
  })
19971
+ }) : /* @__PURE__ */ u("div", {
19972
+ className: "peer-meta",
19973
+ children: "Space access is managed in Teams by a coordinator or manager."
19927
19974
  }),
19928
19975
  /* @__PURE__ */ u(SyncInlineFeedback, { feedback })
19929
19976
  ]
@@ -20056,7 +20103,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20056
20103
  tone: "warning"
20057
20104
  };
20058
20105
  else if (peerId && isPeerScopeReviewPending(peerId)) feedback = {
20059
- 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.`,
20106
+ message: `Triggered sync for ${peer?.name || (peerId ? peerId.slice(0, 8) : "unknown")}. ${canManageSpacesInTeams() ? "Review Space access and advanced rules in Teams if this device needs tighter sharing." : "A coordinator or manager can review Space access and advanced rules in Teams if this device needs tighter sharing."}`,
20060
20107
  tone: "warning"
20061
20108
  };
20062
20109
  else feedback = {
@@ -20736,10 +20783,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
20736
20783
  onClick: async () => {
20737
20784
  setBusy("review");
20738
20785
  setReviewLabel("Pairing…");
20786
+ setFeedback({
20787
+ message: `Pairing ${row.displayName}. Keep this page open while the device is approved and refreshed.`,
20788
+ tone: "success"
20789
+ });
20739
20790
  try {
20740
20791
  setFeedback(await onReview(row) || null);
20741
20792
  setReviewLabel(row.actionLabel || defaultReviewLabel);
20742
20793
  } catch {
20794
+ setFeedback({
20795
+ message: `Pairing ${row.displayName} failed. Try again.`,
20796
+ tone: "warning"
20797
+ });
20743
20798
  setReviewLabel("Retry");
20744
20799
  } finally {
20745
20800
  setBusy(null);
@@ -21997,7 +22052,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
21997
22052
  try {
21998
22053
  const runtime = await loadRuntimeInfo();
21999
22054
  if (!runtime?.version) return;
22000
- setRuntimeLabel(runtime.version, "2eab49c");
22055
+ setRuntimeLabel(runtime.version, "242955b");
22001
22056
  } catch {}
22002
22057
  }
22003
22058
  var lastAnnouncedRefreshState = null;