@codemem/server 0.31.4 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +123 -7
- package/dist/index.js.map +1 -1
- package/dist/routes/sync.d.ts.map +1 -1
- package/package.json +3 -3
- package/static/app.js +394 -127
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { CODEMEM_CONFIG_ENV_OVERRIDES, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, MemoryStore, SYNC_SCOPE_QUERY_PARAM, VERSION, VERSION as VERSION$1, addSyncScopeToBoundary, analyzeProjectScopeMappingChangeGuardrails, applyReplicationOps, buildBaseUrl, buildFilterClausesWithContext, buildRawEventEnvelopeFromHook, canonicalMemoryKind, canonicalWorkspaceIdentity, cleanupNonces, coordinatorArchiveGroupAction, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnableDeviceAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorRenameGroupAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorStatusSnapshot, coordinatorUnarchiveGroupAction, coordinatorUpdateScopeAction, createCoordinatorReciprocalApproval, deleteProjectScopeSettingsMapping, ensureDeviceIdentity, extractReplicationOps, filterReplicationOpsForSyncWithStatus, fingerprintPublicKey, fromJson, getCodememConfigPath, getCodememEnvOverrides, getCoordinatorGroupPreference, getSemanticIndexDiagnostics, getSyncResetState, isSummaryLikeMemory, listCoordinatorJoinRequests, listInboundScopeRejections, listMaintenanceJobs, listObserverProviderOptions, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, mergeAddresses, negotiateSyncCapability, normalizeSyncCapability, parseStrictInteger, parseSyncScopeRequest, personalScopeGrantStatusForPeer, probeAvailableCredentials, readCodememConfigFile, readCoordinatorSyncConfig, reassignProjectScopeInventoryProject, recordNonce, rejectInboundScopeFailures, requestJson, resolveDbPath, runSyncPass, schema, stripJsonComments, stripPrivateObj, stripTrailingCommas, summarizeInboundScopeRejections, syncScopeResetRequiredPayload, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMapping, verifySignature, writeCodememConfigFile } from "@codemem/core";
|
|
3
|
+
import { CODEMEM_CONFIG_ENV_OVERRIDES, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, MemoryStore, SYNC_SCOPE_QUERY_PARAM, VERSION, VERSION as VERSION$1, addSyncScopeToBoundary, analyzeProjectScopeMappingChangeGuardrails, applyReplicationOps, buildBaseUrl, buildFilterClausesWithContext, buildRawEventEnvelopeFromHook, canonicalMemoryKind, canonicalWorkspaceIdentity, cleanupNonces, coordinatorArchiveGroupAction, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnableDeviceAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorRenameGroupAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorStatusSnapshot, coordinatorUnarchiveGroupAction, coordinatorUpdateScopeAction, createCoordinatorReciprocalApproval, defaultSpaceScopeIdForGroup, deleteProjectScopeSettingsMapping, ensureDeviceIdentity, extractReplicationOps, filterReplicationOpsForSyncWithStatus, fingerprintPublicKey, fromJson, getCodememConfigPath, getCodememEnvOverrides, getCoordinatorGroupPreference, getSemanticIndexDiagnostics, getSyncResetState, isSummaryLikeMemory, listCoordinatorJoinRequests, listInboundScopeRejections, listMaintenanceJobs, listObserverProviderOptions, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, mergeAddresses, negotiateSyncCapability, normalizeSyncCapability, parseStrictInteger, parseSyncScopeRequest, personalScopeGrantStatusForPeer, probeAvailableCredentials, readCodememConfigFile, readCoordinatorSyncConfig, reassignProjectScopeInventoryProject, recordNonce, rejectInboundScopeFailures, requestJson, resolveDbPath, runSyncPass, schema, stripJsonComments, stripPrivateObj, stripTrailingCommas, summarizeInboundScopeRejections, syncScopeResetRequiredPayload, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMapping, verifySignature, writeCodememConfigFile } from "@codemem/core";
|
|
4
4
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
import { createMiddleware } from "hono/factory";
|
|
@@ -1707,6 +1707,75 @@ function coordinatorAdminStatusPayload(config = readCoordinatorSyncConfig()) {
|
|
|
1707
1707
|
has_groups: hasGroups
|
|
1708
1708
|
};
|
|
1709
1709
|
}
|
|
1710
|
+
async function ensureDefaultSpaceForTeam(opts) {
|
|
1711
|
+
const coordinatorId = opts.config.syncCoordinatorUrl || null;
|
|
1712
|
+
if (!coordinatorId) throw new Error("coordinator_not_configured");
|
|
1713
|
+
const scopeId = defaultSpaceScopeIdForGroup(opts.groupId);
|
|
1714
|
+
const label = opts.displayName || opts.groupId;
|
|
1715
|
+
const scope = (await coordinatorListScopesAction({
|
|
1716
|
+
groupId: opts.groupId,
|
|
1717
|
+
includeInactive: false,
|
|
1718
|
+
remoteUrl: opts.config.syncCoordinatorUrl || null,
|
|
1719
|
+
adminSecret: opts.config.syncCoordinatorAdminSecret || null
|
|
1720
|
+
})).find((scope) => scope.scope_id === scopeId) ?? null ?? await coordinatorCreateScopeAction({
|
|
1721
|
+
groupId: opts.groupId,
|
|
1722
|
+
scopeId,
|
|
1723
|
+
label,
|
|
1724
|
+
kind: "team_default",
|
|
1725
|
+
authorityType: "coordinator",
|
|
1726
|
+
coordinatorId,
|
|
1727
|
+
membershipEpoch: 1,
|
|
1728
|
+
status: "active",
|
|
1729
|
+
remoteUrl: opts.config.syncCoordinatorUrl || null,
|
|
1730
|
+
adminSecret: opts.config.syncCoordinatorAdminSecret || null
|
|
1731
|
+
});
|
|
1732
|
+
const [deviceId] = ensureDeviceIdentity(opts.store.db);
|
|
1733
|
+
return {
|
|
1734
|
+
scope,
|
|
1735
|
+
membership: await coordinatorGrantScopeMembershipAction({
|
|
1736
|
+
groupId: opts.groupId,
|
|
1737
|
+
scopeId,
|
|
1738
|
+
deviceId,
|
|
1739
|
+
role: "admin",
|
|
1740
|
+
membershipEpoch: 1,
|
|
1741
|
+
coordinatorId,
|
|
1742
|
+
remoteUrl: opts.config.syncCoordinatorUrl || null,
|
|
1743
|
+
adminSecret: opts.config.syncCoordinatorAdminSecret || null
|
|
1744
|
+
}),
|
|
1745
|
+
preferences: upsertCoordinatorGroupPreference(opts.store.db, {
|
|
1746
|
+
coordinator_id: coordinatorId,
|
|
1747
|
+
group_id: opts.groupId,
|
|
1748
|
+
default_space_scope_id: scopeId,
|
|
1749
|
+
auto_grant_default_space_on_join: true
|
|
1750
|
+
})
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
async function maybeGrantDefaultSpaceOnJoin(opts) {
|
|
1754
|
+
const coordinatorId = opts.config.syncCoordinatorUrl || null;
|
|
1755
|
+
if (!coordinatorId) return null;
|
|
1756
|
+
const preferences = getCoordinatorGroupPreference(opts.store.db, coordinatorId, opts.groupId);
|
|
1757
|
+
if (!preferences?.auto_grant_default_space_on_join) return null;
|
|
1758
|
+
const scopeId = preferences.default_space_scope_id?.trim();
|
|
1759
|
+
if (!scopeId) return null;
|
|
1760
|
+
if (scopeId !== defaultSpaceScopeIdForGroup(opts.groupId)) return null;
|
|
1761
|
+
const defaultScope = (await coordinatorListScopesAction({
|
|
1762
|
+
groupId: opts.groupId,
|
|
1763
|
+
includeInactive: false,
|
|
1764
|
+
remoteUrl: opts.config.syncCoordinatorUrl || null,
|
|
1765
|
+
adminSecret: opts.config.syncCoordinatorAdminSecret || null
|
|
1766
|
+
})).find((scope) => scope.scope_id === scopeId) ?? null;
|
|
1767
|
+
if (!defaultScope || defaultScope.kind !== "team_default") return null;
|
|
1768
|
+
return await coordinatorGrantScopeMembershipAction({
|
|
1769
|
+
groupId: opts.groupId,
|
|
1770
|
+
scopeId,
|
|
1771
|
+
deviceId: opts.deviceId,
|
|
1772
|
+
role: "member",
|
|
1773
|
+
membershipEpoch: 1,
|
|
1774
|
+
coordinatorId,
|
|
1775
|
+
remoteUrl: opts.config.syncCoordinatorUrl || null,
|
|
1776
|
+
adminSecret: opts.config.syncCoordinatorAdminSecret || null
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1710
1779
|
function removeConfiguredCoordinatorGroup(groupId) {
|
|
1711
1780
|
const targetGroup = groupId.trim();
|
|
1712
1781
|
if (!targetGroup) return [];
|
|
@@ -3921,11 +3990,31 @@ function syncRoutes(getStore, getSyncRuntimeStatus) {
|
|
|
3921
3990
|
remoteUrl: config.syncCoordinatorUrl || null,
|
|
3922
3991
|
adminSecret: config.syncCoordinatorAdminSecret || null
|
|
3923
3992
|
});
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3993
|
+
try {
|
|
3994
|
+
const defaultSpace = await ensureDefaultSpaceForTeam({
|
|
3995
|
+
store: getStore(),
|
|
3996
|
+
config,
|
|
3997
|
+
groupId,
|
|
3998
|
+
displayName: displayName || group.display_name || null
|
|
3999
|
+
});
|
|
4000
|
+
return c.json({
|
|
4001
|
+
ok: true,
|
|
4002
|
+
group,
|
|
4003
|
+
default_space: defaultSpace,
|
|
4004
|
+
status
|
|
4005
|
+
});
|
|
4006
|
+
} catch (setupError) {
|
|
4007
|
+
return c.json({
|
|
4008
|
+
ok: true,
|
|
4009
|
+
group,
|
|
4010
|
+
default_space: null,
|
|
4011
|
+
setup_warning: {
|
|
4012
|
+
step: "default_space",
|
|
4013
|
+
error: setupError instanceof Error ? setupError.message : String(setupError)
|
|
4014
|
+
},
|
|
4015
|
+
status
|
|
4016
|
+
});
|
|
4017
|
+
}
|
|
3929
4018
|
} catch (error) {
|
|
3930
4019
|
return c.json({
|
|
3931
4020
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -4487,9 +4576,26 @@ function syncRoutes(getStore, getSyncRuntimeStatus) {
|
|
|
4487
4576
|
error: "join request not found",
|
|
4488
4577
|
status
|
|
4489
4578
|
}, 404);
|
|
4579
|
+
let defaultSpaceMembership = null;
|
|
4580
|
+
let setupWarning = null;
|
|
4581
|
+
try {
|
|
4582
|
+
defaultSpaceMembership = await maybeGrantDefaultSpaceOnJoin({
|
|
4583
|
+
store: getStore(),
|
|
4584
|
+
config,
|
|
4585
|
+
groupId: result.group_id,
|
|
4586
|
+
deviceId: result.device_id
|
|
4587
|
+
});
|
|
4588
|
+
} catch (grantError) {
|
|
4589
|
+
setupWarning = {
|
|
4590
|
+
step: "default_space_grant",
|
|
4591
|
+
error: grantError instanceof Error ? grantError.message : String(grantError)
|
|
4592
|
+
};
|
|
4593
|
+
}
|
|
4490
4594
|
return c.json({
|
|
4491
4595
|
ok: true,
|
|
4492
4596
|
request: result,
|
|
4597
|
+
default_space_membership: defaultSpaceMembership,
|
|
4598
|
+
setup_warning: setupWarning,
|
|
4493
4599
|
status
|
|
4494
4600
|
});
|
|
4495
4601
|
} catch (error) {
|
|
@@ -4859,6 +4965,8 @@ function syncRoutes(getStore, getSyncRuntimeStatus) {
|
|
|
4859
4965
|
projects_include: null,
|
|
4860
4966
|
projects_exclude: null,
|
|
4861
4967
|
auto_seed_scope: true,
|
|
4968
|
+
default_space_scope_id: null,
|
|
4969
|
+
auto_grant_default_space_on_join: false,
|
|
4862
4970
|
updated_at: null
|
|
4863
4971
|
},
|
|
4864
4972
|
status
|
|
@@ -4897,6 +5005,12 @@ function syncRoutes(getStore, getSyncRuntimeStatus) {
|
|
|
4897
5005
|
return cleaned.length === 0 ? null : cleaned;
|
|
4898
5006
|
};
|
|
4899
5007
|
const autoSeed = typeof body.auto_seed_scope === "boolean" ? body.auto_seed_scope : void 0;
|
|
5008
|
+
const autoGrantDefaultSpace = typeof body.auto_grant_default_space_on_join === "boolean" ? body.auto_grant_default_space_on_join : void 0;
|
|
5009
|
+
const defaultSpaceScopeId = body.default_space_scope_id === void 0 ? void 0 : optionalViewerString(body, "default_space_scope_id");
|
|
5010
|
+
if (autoGrantDefaultSpace === true && !defaultSpaceScopeId) return c.json({
|
|
5011
|
+
error: "default_space_scope_id_required_for_auto_grant",
|
|
5012
|
+
status
|
|
5013
|
+
}, 400);
|
|
4900
5014
|
const store = getStore();
|
|
4901
5015
|
try {
|
|
4902
5016
|
const preferences = upsertCoordinatorGroupPreference(store.db, {
|
|
@@ -4904,7 +5018,9 @@ function syncRoutes(getStore, getSyncRuntimeStatus) {
|
|
|
4904
5018
|
group_id: groupId,
|
|
4905
5019
|
projects_include: normalizeList(body.projects_include),
|
|
4906
5020
|
projects_exclude: normalizeList(body.projects_exclude),
|
|
4907
|
-
auto_seed_scope: autoSeed
|
|
5021
|
+
auto_seed_scope: autoSeed,
|
|
5022
|
+
default_space_scope_id: defaultSpaceScopeId,
|
|
5023
|
+
auto_grant_default_space_on_join: autoGrantDefaultSpace
|
|
4908
5024
|
});
|
|
4909
5025
|
return c.json({
|
|
4910
5026
|
preferences,
|