@codemem/server 0.46.0-beta.2 → 0.46.0-rc.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/dist/application/sync-status.d.ts +7 -0
- package/dist/application/sync-status.d.ts.map +1 -1
- package/dist/index.js +213 -30
- package/dist/index.js.map +1 -1
- package/dist/routes/device-rename.d.ts +77 -0
- package/dist/routes/device-rename.d.ts.map +1 -0
- package/dist/routes/diagnostics.d.ts +1 -1
- package/dist/routes/diagnostics.d.ts.map +1 -1
- package/dist/routes/sync.d.ts.map +1 -1
- package/package.json +2 -2
- package/static/app.js +46 -46
- package/static/app.js.br +0 -0
- package/static/app.js.gz +0 -0
- package/static/index.html +33 -1
|
@@ -34,6 +34,13 @@ export interface SyncStatusInput {
|
|
|
34
34
|
getSyncRuntimeStatus?: () => SyncRuntimeStatus | null;
|
|
35
35
|
operations: SyncStatusOperations;
|
|
36
36
|
}
|
|
37
|
+
interface PeerStatusReadModel {
|
|
38
|
+
items: Record<string, unknown>[];
|
|
39
|
+
byId: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
export declare function safeDaemonIssueCode(state: string, lastError: string | null | undefined): "coordinator_timeout" | "coordinator_error" | null;
|
|
42
|
+
export declare function latestFailedPeerIds(store: MemoryStore, activePeerIds: Set<string>, isRecentIso: (value: unknown) => boolean): Set<string>;
|
|
43
|
+
export declare function degradedDaemonState(peers: PeerStatusReadModel, failedPeerIds: Set<string>): string;
|
|
37
44
|
export declare function buildSyncStatusResponse(input: SyncStatusInput): Promise<Record<string, unknown>>;
|
|
38
45
|
export {};
|
|
39
46
|
//# sourceMappingURL=sync-status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-status.d.ts","sourceRoot":"","sources":["../../src/application/sync-status.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,yBAAyB,EAEzB,2BAA2B,EAE3B,KAAK,gCAAgC,EAErC,mBAAmB,EACnB,KAAK,WAAW,EAGhB,MAAM,eAAe,CAAC;AAKvB,MAAM,MAAM,iBAAiB,GAAG;IAC/B,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;
|
|
1
|
+
{"version":3,"file":"sync-status.d.ts","sourceRoot":"","sources":["../../src/application/sync-status.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
|
|
3
|
-
import { ACCESS_CLEANUP_OP_TYPE, CodememConfigMutationError, CoordinatorReciprocalApprovalRequestChangedError, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, LOCAL_SYNC_FEATURES, LegacyTeamSetupAdditiveConvergenceError, LegacyTeamSetupRosterCapacityError, MEMORY_FILTER_FIELD_TYPES, MEMORY_FILTER_NAMES, MEMORY_KIND_DESCRIPTIONS, MemoryStore, ObserverClient, PROMPT_TRANSPORT_PROTOCOL_RANGE, REMEMBER_MEMORY_KINDS, RawEventIngestValidationError, RecipientPolicyEdgeRequestError, RecipientPolicyTeamRenameError, RemoteCoordinatorRequestError, SCOPE_MEMBERSHIP_REVOCATION_LIMITATION, SYNC_AUTHORIZATION_REFRESH_HEADER, SYNC_CAPABILITY_HEADER, SYNC_FEATURES_HEADER, SYNC_SCOPE_QUERY_PARAM, VERSION, VERSION as VERSION$1, VIEWER_IDENTITY_TARGET_KEYS, VIEWER_SERVICE_DISCRIMINATOR, addSyncScopeToBoundary, analyzeProjectScopeMappingChangeGuardrails, analyzeProjectScopeMappingChangesGuardrails, analyzeProjectScopeMappingDeletionGuardrails, applyLegacyTeamSetupCompletionManifest, applyLegacyTeamSetupCompletionManifestAndReturnActivation, applyReplicationOps, areLegacyTeamSetupCompletionPolicyFactsAdditivelyCompatible, automaticRecallHealth, buildAuthHeaders, buildBaseUrl, buildDirectPeerAuthHeaders, buildDistillReport, buildFilterClausesWithContext, buildPiFlushSignalFromEvent, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildRawEventEnvelopeFromPiEvent, buildViewerIdentityTarget, canonicalCoordinatorLegacyTeamCompletionManifestJson, canonicalMemoryKind, canonicalRepositoryProjectIdentity, canonicalWorkspaceIdentity, claimRecipientPolicyActorMutations, claimRecipientPolicyPublicationMutation, cleanupNonces, clearLegacyTeamSetupDeviceDecision, clonePromptPackAttempt, coerceObserverCommand, commitDeviceIdentityBindings, commitRecipientPolicyEdges, containLegacyTeamSetupCompletionConflict, coordinatorArchiveGroupAction, coordinatorCreateAddDeviceInviteAction, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateLegacyTeamCompletionAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnableDeviceAction, coordinatorGetLegacyTeamCompletionAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListConsumedTeamInvitesAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListLegacyTeamCompletionsAction, coordinatorListReviewedRecipientInviteEvidenceAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorRenameGroupAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorStatusSnapshot, coordinatorUnarchiveGroupAction, coordinatorUpdateScopeAction, countShareableProjectMemories, createCoordinatorReciprocalApproval, decodeInvitePayload, dedupeOrderedIds, defaultSpaceScopeIdForGroup, deleteProjectScopeSettingsMapping, deriveLegacyTeamSetupCompletionManifest, detectInstallKind, deterministicPolicyTeamId, diagnoseStalePeerReceivedRows, discoverLegacyTeamCandidates, ensureDeviceIdentity, executeShareProvisioning, extractInvitePayload, extractReplicationOps, filterReplicationOpsForSyncWithStatus, fingerprintPublicKey, formatHostPort, friendlyDeviceName, fromJson, getCodememConfigPath, getCodememEnvOverrideValues, getCodememEnvOverrides, getCoordinatorEnrollmentReconciliationIssueSummary, getCoordinatorGroupPreference, getLegacyTeamSetupDraft, getRecipientPolicyAuthorityState, getSemanticIndexDiagnostics, getSyncResetState, getUpdateStatus, ingestRawEvents, inspectFreshLegacyTeamSetupActivation, inspectLegacyTeamSetupActivation, inviteTokenDigest, isAutomaticRecallMeasurement, isLegacyTeamCandidateSelectable, isLegacyTeamSetupProjectMappingIdentity, isPeerTrustBindingCompatible, isProjectSyncEnablementError, isScopedSyncCapability, judgeDistillReport, legacyTeamCandidateId, legacyTeamCandidateProjectInventory, legacyTeamCanonicalProjectRef, legacyTeamDeviceRef, legacyTeamResolvedProjectRef, legacyTeamSetupApiErrorCode, listAuthorizedScopesForPeer, listCoordinatorJoinRequests, listDeviceIdentityInventory, listInboundScopeRejections, listLegacyRecipientPolicyProjections, listMaintenanceJobs, listObserverProviderOptions, listPerPeerScopeSyncState, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listRecipientPolicyIntent, listRecipientPolicyReview, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, memoryFilterValueMatchesType, mergeAddresses, migrateRecipientPolicyIntent, mutateCodememConfigFile, negotiateSyncCapability, normalizeAddress, normalizeHumanPresentationName, normalizeSyncCapability, normalizeSyncFeatures, normalizeTeammateName, parseAcceptedProjectIntent, parsePositiveMemoryId, parseReassignScopePayload, parseRecipientPolicyEdgeCommitRequest, parseStrictInteger, parseSyncScopeRequest, persistShareOperation, personalScopeGrantStatusForPeer, planShareOperation, previewDeviceIdentityBindings, previewLegacyTeamSetupActivation, previewRecipientPolicyEdges, previewRecipientPolicyOnboarding, previewRecipientPolicyOnboardingFromReviewedIntent, probeAvailableCredentials, projectMatchesFilter, projectShareLifecycle, promptPackArtifactFingerprint, readCodememConfigFile, readCoordinatorSyncConfig, reassignProjectScopeInventoryProject, recipientInviteAuthoritativeIdentityId, recipientPolicyDigest, recipientReviewedIntentDigest, reconcileCoordinatorEnrollmentSnapshot, reconcileRecipientPolicyProject, reconcileShareOperationAcceptance, reconstructLegacyTeamSetupCompletionManifest, recordAutomaticRecall, recordHighestObservedDirectSignatureVersion, recordNonce, recordPromptPackArtifacts, recordPromptPackTerminal, refreshAuthorizedCoordinatorPeerTrust, refreshConfiguredScopeMembershipCache, refreshLegacyTeamCandidate, rejectInboundScopeFailures, renameRecipientPolicyTeam, replayLegacyTeamSetupActivation, repositoryIdentitiesByWorkspace, repositoryIdentityForWorkspace, requestJson, requireLegacyTeamSetupAccessDeltaWithinLimit, resolveDbPath, resolveObserverRuntime, resolveProject, resolveProjectRoot, resolveRecipientPolicyReview, resolveRecipientPolicyReviewBulk, runSyncPass, schema, serializeRecipientPolicyCoordinatorGroupMutation, serializeRecipientPolicyPublicationMutation, serializeRecipientPolicyTeamMutation, setLegacyTeamSetupDeviceAssignment, setLegacyTeamSetupDeviceDecision, setLegacyTeamSetupProjectMapping, storeVectors, summarizeInboundScopeRejections, summaryLikeSqlPredicate, supportsSyncFeature, syncScopeResetRequiredPayload, toJson, tryUpdateRetrievalDelivery, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMappings, validateLegacyTeamSetupCompletionManifest, validateLegacyTeamSetupCompletionManifestBinding, validateRawEvents, verifyDirectPeerSignature, verifyRecipientReviewedIntent, verifySignature, wakeRecipientPoliciesForIdentities, wakeRecipientPoliciesForProjectIdentities } from "@codemem/core";
|
|
3
|
+
import { ACCESS_CLEANUP_OP_TYPE, CodememConfigMutationError, CoordinatorReciprocalApprovalRequestChangedError, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, LOCAL_SYNC_FEATURES, LegacyTeamSetupAdditiveConvergenceError, LegacyTeamSetupRosterCapacityError, MEMORY_FILTER_FIELD_TYPES, MEMORY_FILTER_NAMES, MEMORY_KIND_DESCRIPTIONS, MemoryStore, ObserverClient, PROMPT_TRANSPORT_PROTOCOL_RANGE, REMEMBER_MEMORY_KINDS, RawEventIngestValidationError, RecipientPolicyEdgeRequestError, RecipientPolicyTeamRenameError, RemoteCoordinatorRequestError, SCOPE_MEMBERSHIP_REVOCATION_LIMITATION, SYNC_AUTHORIZATION_REFRESH_HEADER, SYNC_CAPABILITY_HEADER, SYNC_FEATURES_HEADER, SYNC_SCOPE_QUERY_PARAM, VERSION, VERSION as VERSION$1, VIEWER_IDENTITY_TARGET_KEYS, VIEWER_SERVICE_DISCRIMINATOR, addSyncScopeToBoundary, analyzeProjectScopeMappingChangeGuardrails, analyzeProjectScopeMappingChangesGuardrails, analyzeProjectScopeMappingDeletionGuardrails, applyLegacyTeamSetupCompletionManifest, applyLegacyTeamSetupCompletionManifestAndReturnActivation, applyReplicationOps, areLegacyTeamSetupCompletionPolicyFactsAdditivelyCompatible, automaticRecallHealth, buildAuthHeaders, buildBaseUrl, buildDirectPeerAuthHeaders, buildDistillReport, buildFilterClausesWithContext, buildPiFlushSignalFromEvent, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildRawEventEnvelopeFromPiEvent, buildViewerIdentityTarget, canonicalCoordinatorLegacyTeamCompletionManifestJson, canonicalMemoryKind, canonicalRepositoryProjectIdentity, canonicalWorkspaceIdentity, claimRecipientPolicyActorMutations, claimRecipientPolicyPublicationMutation, classifyRecordedSyncFailure, cleanupNonces, clearLegacyTeamSetupDeviceDecision, clonePromptPackAttempt, coerceObserverCommand, commitDeviceIdentityBindings, commitRecipientPolicyEdges, containLegacyTeamSetupCompletionConflict, coordinatorArchiveGroupAction, coordinatorCreateAddDeviceInviteAction, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateLegacyTeamCompletionAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnableDeviceAction, coordinatorGetLegacyTeamCompletionAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListConsumedTeamInvitesAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListLegacyTeamCompletionsAction, coordinatorListReviewedRecipientInviteEvidenceAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorRenameGroupAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorStatusSnapshot, coordinatorUnarchiveGroupAction, coordinatorUpdateScopeAction, countShareableProjectMemories, createCoordinatorReciprocalApproval, decodeInvitePayload, dedupeOrderedIds, defaultSpaceScopeIdForGroup, deleteProjectScopeSettingsMapping, deriveLegacyTeamSetupCompletionManifest, detectInstallKind, deterministicPolicyTeamId, diagnoseStalePeerReceivedRows, discoverLegacyTeamCandidates, ensureDeviceIdentity, executeShareProvisioning, extractInvitePayload, extractReplicationOps, filterReplicationOpsForSyncWithStatus, fingerprintPublicKey, formatHostPort, friendlyDeviceName, fromJson, getCodememConfigPath, getCodememEnvOverrideValues, getCodememEnvOverrides, getCoordinatorEnrollmentReconciliationIssueSummary, getCoordinatorGroupPreference, getLegacyTeamSetupDraft, getRecipientPolicyAuthorityState, getSemanticIndexDiagnostics, getSyncResetState, getUpdateStatus, ingestRawEvents, inspectFreshLegacyTeamSetupActivation, inspectLegacyTeamSetupActivation, inviteTokenDigest, isAutomaticRecallMeasurement, isLegacyTeamCandidateSelectable, isLegacyTeamSetupProjectMappingIdentity, isPeerTrustBindingCompatible, isProjectSyncEnablementError, isScopedSyncCapability, judgeDistillReport, legacyTeamCandidateId, legacyTeamCandidateProjectInventory, legacyTeamCanonicalProjectRef, legacyTeamDeviceRef, legacyTeamResolvedProjectRef, legacyTeamSetupApiErrorCode, listAuthorizedScopesForPeer, listCoordinatorJoinRequests, listDeviceIdentityInventory, listInboundScopeRejections, listLegacyRecipientPolicyProjections, listMaintenanceJobs, listObserverProviderOptions, listPerPeerScopeSyncState, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listRecipientPolicyIntent, listRecipientPolicyReview, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, memoryFilterValueMatchesType, mergeAddresses, migrateRecipientPolicyIntent, mutateCodememConfigFile, negotiateSyncCapability, normalizeAddress, normalizeHumanPresentationName, normalizeSyncCapability, normalizeSyncFeatures, normalizeTeammateName, parseAcceptedProjectIntent, parsePositiveMemoryId, parseReassignScopePayload, parseRecipientPolicyEdgeCommitRequest, parseStrictInteger, parseSyncScopeRequest, persistShareOperation, personalScopeGrantStatusForPeer, planShareOperation, previewDeviceIdentityBindings, previewLegacyTeamSetupActivation, previewRecipientPolicyEdges, previewRecipientPolicyOnboarding, previewRecipientPolicyOnboardingFromReviewedIntent, probeAvailableCredentials, projectMatchesFilter, projectShareLifecycle, promptPackArtifactFingerprint, readCodememConfigFile, readCoordinatorSyncConfig, reassignProjectScopeInventoryProject, recipientInviteAuthoritativeIdentityId, recipientPolicyDigest, recipientReviewedIntentDigest, reconcileCoordinatorEnrollmentSnapshot, reconcileRecipientPolicyProject, reconcileShareOperationAcceptance, reconstructLegacyTeamSetupCompletionManifest, recordAutomaticRecall, recordHighestObservedDirectSignatureVersion, recordNonce, recordPromptPackArtifacts, recordPromptPackTerminal, refreshAuthorizedCoordinatorPeerTrust, refreshConfiguredScopeMembershipCache, refreshLegacyTeamCandidate, rejectInboundScopeFailures, renameRecipientPolicyTeam, replayLegacyTeamSetupActivation, repositoryIdentitiesByWorkspace, repositoryIdentityForWorkspace, requestJson, requireLegacyTeamSetupAccessDeltaWithinLimit, resolveDbPath, resolveObserverRuntime, resolveProject, resolveProjectRoot, resolveRecipientPolicyReview, resolveRecipientPolicyReviewBulk, runSyncPass, schema, serializeRecipientPolicyCoordinatorGroupMutation, serializeRecipientPolicyPublicationMutation, serializeRecipientPolicyTeamMutation, setLegacyTeamSetupDeviceAssignment, setLegacyTeamSetupDeviceDecision, setLegacyTeamSetupProjectMapping, storeVectors, summarizeInboundScopeRejections, summaryLikeSqlPredicate, supportsSyncFeature, syncScopeResetRequiredPayload, toJson, tryUpdateRetrievalDelivery, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMappings, validateLegacyTeamSetupCompletionManifest, validateLegacyTeamSetupCompletionManifestBinding, validateRawEvents, verifyDirectPeerSignature, verifyRecipientReviewedIntent, verifySignature, wakeRecipientPoliciesForIdentities, wakeRecipientPoliciesForProjectIdentities } 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";
|
|
@@ -671,14 +671,9 @@ function syncSelect(options) {
|
|
|
671
671
|
${SYNC_OCCURRED_AT_SQL} AS occurred_at,
|
|
672
672
|
CASE WHEN ok <> 0 THEN 'succeeded' ELSE 'failed' END AS status,
|
|
673
673
|
ops_in AS metric_a, ops_out AS metric_b,
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
WHEN lower(error) LIKE '%version%' OR lower(error) LIKE '%capability%' THEN 'compatibility'
|
|
678
|
-
WHEN lower(error) LIKE '%connect%' OR lower(error) LIKE '%network%'
|
|
679
|
-
OR lower(error) LIKE '%dns%' THEN 'connectivity'
|
|
680
|
-
ELSE 'unspecified'
|
|
681
|
-
END AS category
|
|
674
|
+
-- Raw error text; syncEvent classifies it server-side and never returns it.
|
|
675
|
+
error AS category,
|
|
676
|
+
failure_category AS stored_category
|
|
682
677
|
FROM sync_attempts ${predicates.length ? `WHERE ${predicates.join(" AND ")}` : ""}
|
|
683
678
|
ORDER BY ${SYNC_OCCURRED_AT_SQL} DESC, id DESC
|
|
684
679
|
LIMIT @sourceLimit`;
|
|
@@ -712,7 +707,8 @@ function observerSelect(options) {
|
|
|
712
707
|
WHEN lower(COALESCE(observer_error_code, error_type)) LIKE '%schema%'
|
|
713
708
|
OR lower(COALESCE(observer_error_code, error_type)) LIKE '%parse%' THEN 'response format'
|
|
714
709
|
ELSE 'unspecified'
|
|
715
|
-
END AS category
|
|
710
|
+
END AS category,
|
|
711
|
+
NULL AS stored_category
|
|
716
712
|
FROM raw_event_flush_batches
|
|
717
713
|
WHERE status = '${status}' ${providerFilter} ${cursorFilter}
|
|
718
714
|
ORDER BY updated_at DESC, id DESC
|
|
@@ -729,7 +725,7 @@ function maintenanceSelect(options) {
|
|
|
729
725
|
return `SELECT 'maintenance' AS source_type, kind AS source_id,
|
|
730
726
|
'm:' || hex(kind) AS order_key, updated_at AS occurred_at,
|
|
731
727
|
status, progress_current AS metric_a, progress_total AS metric_b,
|
|
732
|
-
NULL AS category
|
|
728
|
+
NULL AS category, NULL AS stored_category
|
|
733
729
|
FROM maintenance_jobs WHERE status IN (${statuses.join(", ")})`;
|
|
734
730
|
}
|
|
735
731
|
function backlogSelect(options) {
|
|
@@ -763,7 +759,8 @@ function backlogSelect(options) {
|
|
|
763
759
|
'b:' || printf('%020d', 0) AS order_key, occurred_at,
|
|
764
760
|
CASE WHEN pending >= 1000 THEN 'error' ELSE 'warning' END AS status,
|
|
765
761
|
pending AS metric_a, sessions AS metric_b,
|
|
766
|
-
CASE WHEN candidate_count > 1000 THEN 'capped' ELSE NULL END AS category
|
|
762
|
+
CASE WHEN candidate_count > 1000 THEN 'capped' ELSE NULL END AS category,
|
|
763
|
+
NULL AS stored_category
|
|
767
764
|
FROM (
|
|
768
765
|
SELECT MAX(updated_at) AS occurred_at,
|
|
769
766
|
SUM(pending) AS pending,
|
|
@@ -805,11 +802,28 @@ function loadSourceRows(store, options) {
|
|
|
805
802
|
ORDER BY occurred_at DESC, order_key DESC
|
|
806
803
|
LIMIT @resultLimit`).all(params);
|
|
807
804
|
}
|
|
805
|
+
var SYNC_FAILURE_MESSAGES = {
|
|
806
|
+
connectivity: "Sync could not reach a paired device, or the device did not respond in time.",
|
|
807
|
+
trust: "Sync stopped because the pairing or identity check between two devices failed.",
|
|
808
|
+
scope: "Sync stopped because two devices disagree about access to a shared Space.",
|
|
809
|
+
compatibility: "Sync stopped because two devices run incompatible Codemem versions."
|
|
810
|
+
};
|
|
811
|
+
var SPECIFIC_STORED_SYNC_CATEGORIES = /* @__PURE__ */ new Set([
|
|
812
|
+
"trust",
|
|
813
|
+
"scope",
|
|
814
|
+
"connectivity",
|
|
815
|
+
"compatibility"
|
|
816
|
+
]);
|
|
817
|
+
function syncFailureCategory(row) {
|
|
818
|
+
const stored = row.stored_category;
|
|
819
|
+
if (stored && SPECIFIC_STORED_SYNC_CATEGORIES.has(stored)) return stored;
|
|
820
|
+
return classifyRecordedSyncFailure(row.category);
|
|
821
|
+
}
|
|
808
822
|
function syncEvent(row, includeTechnical) {
|
|
809
823
|
const succeeded = row.status === "succeeded";
|
|
810
824
|
const opsIn = Number(row.metric_a ?? 0);
|
|
811
825
|
const opsOut = Number(row.metric_b ?? 0);
|
|
812
|
-
const category =
|
|
826
|
+
const category = succeeded ? "other" : syncFailureCategory(row);
|
|
813
827
|
return {
|
|
814
828
|
id: opaqueId("sync-attempt", row.source_id),
|
|
815
829
|
orderKey: row.order_key,
|
|
@@ -817,7 +831,7 @@ function syncEvent(row, includeTechnical) {
|
|
|
817
831
|
severity: succeeded ? "info" : "error",
|
|
818
832
|
subsystem: "sync",
|
|
819
833
|
code: succeeded ? "sync_attempt_succeeded" : "sync_attempt_failed",
|
|
820
|
-
message: succeeded ? "A sync attempt completed." : "A sync attempt failed before all work completed.",
|
|
834
|
+
message: succeeded ? "A sync attempt completed." : SYNC_FAILURE_MESSAGES[category] ?? "A sync attempt failed before all work completed.",
|
|
821
835
|
recovery: succeeded ? void 0 : {
|
|
822
836
|
label: "Open advanced sync diagnostics",
|
|
823
837
|
href: "#advanced/sync/diagnostics"
|
|
@@ -4151,6 +4165,14 @@ async function reconcileRecipientPolicyProjectsOperation(store, options) {
|
|
|
4151
4165
|
}
|
|
4152
4166
|
//#endregion
|
|
4153
4167
|
//#region src/application/sync-status.ts
|
|
4168
|
+
var SAFE_RUNTIME_DETAILS = {
|
|
4169
|
+
starting: "Running initial sync in background",
|
|
4170
|
+
stopping: "Stopping sync daemon",
|
|
4171
|
+
error: "Background sync failed. Open diagnostics for details.",
|
|
4172
|
+
rebootstrapping: "Restoring sync baseline",
|
|
4173
|
+
needs_attention: "Sync needs attention",
|
|
4174
|
+
disabled: "Sync is off"
|
|
4175
|
+
};
|
|
4154
4176
|
function traceSync(label, operation) {
|
|
4155
4177
|
if (process.env.CODEMEM_TRACE_SYNC_STATUS !== "1") return operation();
|
|
4156
4178
|
const startedAt = Date.now();
|
|
@@ -4215,6 +4237,10 @@ function initialDaemonState(config, rows, daemonRunning) {
|
|
|
4215
4237
|
if (!daemonRunning) return "stopped";
|
|
4216
4238
|
return "ok";
|
|
4217
4239
|
}
|
|
4240
|
+
function safeDaemonIssueCode(state, lastError) {
|
|
4241
|
+
if (state !== "error" || !lastError?.includes("coordinator enrollment maintenance failed")) return null;
|
|
4242
|
+
return lastError.includes(":request_timeout") || lastError.endsWith(" (coordinator_timeout)") ? "coordinator_timeout" : "coordinator_error";
|
|
4243
|
+
}
|
|
4218
4244
|
function retentionPayload(config, rows, retainedFloor) {
|
|
4219
4245
|
const state = rows.retention;
|
|
4220
4246
|
return {
|
|
@@ -4282,8 +4308,9 @@ function readBaseStatus(input) {
|
|
|
4282
4308
|
state = runtime.phase;
|
|
4283
4309
|
statusPayload.daemon_state = state;
|
|
4284
4310
|
statusPayload.daemon_running = runtime.phase === "starting" || running;
|
|
4285
|
-
statusPayload.daemon_detail = runtime.detail ?? detail;
|
|
4311
|
+
statusPayload.daemon_detail = input.showDiagnostics ? runtime.detail ?? detail : SAFE_RUNTIME_DETAILS[runtime.phase] ?? null;
|
|
4286
4312
|
}
|
|
4313
|
+
statusPayload.daemon_issue_code = safeDaemonIssueCode(state, runtime?.phase === "error" ? null : rows.daemon?.last_error);
|
|
4287
4314
|
return {
|
|
4288
4315
|
config,
|
|
4289
4316
|
localDeviceId: rows.device?.device_id ?? null,
|
|
@@ -4340,16 +4367,35 @@ function readAttemptStatus(input) {
|
|
|
4340
4367
|
latestError: String(rows[0]?.error || "").trim()
|
|
4341
4368
|
};
|
|
4342
4369
|
}
|
|
4370
|
+
function latestFailedPeerIds(store, activePeerIds, isRecentIso) {
|
|
4371
|
+
const cutoff = (/* @__PURE__ */ new Date(Date.now() - 6e5)).toISOString();
|
|
4372
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4373
|
+
return traceSync("recentPeerFailures", () => {
|
|
4374
|
+
const rows = store.db.prepare(`SELECT peer_device_id, ok, error, finished_at
|
|
4375
|
+
FROM sync_attempts
|
|
4376
|
+
WHERE (CASE WHEN finished_at IS NULL THEN started_at ELSE finished_at END) BETWEEN ? AND ?
|
|
4377
|
+
ORDER BY (CASE WHEN finished_at IS NULL THEN started_at ELSE finished_at END) DESC, id DESC`).iterate(cutoff, now);
|
|
4378
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4379
|
+
const failed = /* @__PURE__ */ new Set();
|
|
4380
|
+
for (const row of rows) {
|
|
4381
|
+
if (!activePeerIds.has(row.peer_device_id) || seen.has(row.peer_device_id)) continue;
|
|
4382
|
+
if (!isRecentIso(row.finished_at)) continue;
|
|
4383
|
+
seen.add(row.peer_device_id);
|
|
4384
|
+
if (!row.ok && row.error) failed.add(row.peer_device_id);
|
|
4385
|
+
}
|
|
4386
|
+
return failed;
|
|
4387
|
+
});
|
|
4388
|
+
}
|
|
4343
4389
|
function peerStates(peers) {
|
|
4344
4390
|
return new Set(peers.items.map((peer) => String(peer.status?.peer_state ?? "")));
|
|
4345
4391
|
}
|
|
4346
4392
|
function allPeersOffline(peers) {
|
|
4347
4393
|
return peers.items.length > 0 && peers.items.every((peer) => String(peer.status?.peer_state ?? "") === "offline");
|
|
4348
4394
|
}
|
|
4349
|
-
function degradedDaemonState(
|
|
4395
|
+
function degradedDaemonState(peers, failedPeerIds) {
|
|
4350
4396
|
const states = peerStates(peers);
|
|
4351
4397
|
const allOffline = allPeersOffline(peers);
|
|
4352
|
-
if (
|
|
4398
|
+
if (failedPeerIds.size > 0) {
|
|
4353
4399
|
if (states.has("online") || states.has("degraded")) return "degraded";
|
|
4354
4400
|
if (allOffline) return "offline-peers";
|
|
4355
4401
|
if (peers.items.length > 0) return "stale";
|
|
@@ -4359,14 +4405,14 @@ function degradedDaemonState(input, peers, attempts) {
|
|
|
4359
4405
|
if (peers.items.length > 0 && !states.has("online")) return "stale";
|
|
4360
4406
|
return "ok";
|
|
4361
4407
|
}
|
|
4362
|
-
function applyDerivedDaemonState(
|
|
4408
|
+
function applyDerivedDaemonState(base, peers, attempts, failedPeerIds, statusBlock) {
|
|
4363
4409
|
let state = base.daemonState;
|
|
4364
4410
|
if (state === "ok" && attempts.latestError.startsWith("needs_attention:")) {
|
|
4365
4411
|
state = "needs_attention";
|
|
4366
4412
|
const detail = attempts.latestError.replace(/^needs_attention:/, "");
|
|
4367
4413
|
base.statusPayload.daemon_detail = detail;
|
|
4368
4414
|
statusBlock.daemon_detail = detail;
|
|
4369
|
-
} else if (state === "ok") state = degradedDaemonState(
|
|
4415
|
+
} else if (state === "ok") state = degradedDaemonState(peers, failedPeerIds);
|
|
4370
4416
|
base.statusPayload.daemon_state = state;
|
|
4371
4417
|
statusBlock.daemon_state = state;
|
|
4372
4418
|
}
|
|
@@ -4384,6 +4430,12 @@ async function buildSyncStatusResponse(input) {
|
|
|
4384
4430
|
const coordinator = traceSync("coordinator", () => input.operations.redactCoordinatorStatus(coordinatorSnapshot, input.showDiagnostics));
|
|
4385
4431
|
const peers = readPeerStatus(input, base.localDeviceId);
|
|
4386
4432
|
const attempts = readAttemptStatus(input);
|
|
4433
|
+
const activePeerIds = new Set(peers.items.map((peer) => String(peer.peer_device_id ?? "")));
|
|
4434
|
+
const failedPeerIds = latestFailedPeerIds(input.store, activePeerIds, input.operations.isRecentIso);
|
|
4435
|
+
for (const peer of peers.items) {
|
|
4436
|
+
const status = peer.status;
|
|
4437
|
+
status.recent_failed_attempt = failedPeerIds.has(String(peer.peer_device_id ?? ""));
|
|
4438
|
+
}
|
|
4387
4439
|
const statusBlock = {
|
|
4388
4440
|
...base.statusPayload,
|
|
4389
4441
|
background_maintenance: input.operations.summarizeMaintenanceJobs(listMaintenanceJobs(input.store.db), input.showDiagnostics),
|
|
@@ -4397,7 +4449,7 @@ async function buildSyncStatusResponse(input) {
|
|
|
4397
4449
|
const sharingReview = traceSync("sharingReview", () => input.store.sharingReviewSummary(input.project));
|
|
4398
4450
|
const recipientPolicyReconciliation = traceSync("recipientPolicyReconciliation", () => input.operations.listRecipientPolicyReconciliationStatus(input.store));
|
|
4399
4451
|
const joinRequests = await readJoinRequests(input, base.config);
|
|
4400
|
-
applyDerivedDaemonState(
|
|
4452
|
+
applyDerivedDaemonState(base, peers, attempts, failedPeerIds, statusBlock);
|
|
4401
4453
|
const response = {
|
|
4402
4454
|
...base.statusPayload,
|
|
4403
4455
|
status: statusBlock,
|
|
@@ -4458,6 +4510,126 @@ function snapshotPageRequest(query, localDeviceId) {
|
|
|
4458
4510
|
};
|
|
4459
4511
|
}
|
|
4460
4512
|
//#endregion
|
|
4513
|
+
//#region src/routes/device-rename.ts
|
|
4514
|
+
async function enrolledGroups(config, deviceId) {
|
|
4515
|
+
const remoteUrl = config.syncCoordinatorUrl || null;
|
|
4516
|
+
const adminSecret = config.syncCoordinatorAdminSecret || null;
|
|
4517
|
+
if (!remoteUrl || !adminSecret) throw new Error("coordinator_unavailable");
|
|
4518
|
+
const groups = await coordinatorListGroupsAction({
|
|
4519
|
+
remoteUrl,
|
|
4520
|
+
adminSecret
|
|
4521
|
+
});
|
|
4522
|
+
if (groups.length > 25) throw new Error("coordinator_evidence_too_large");
|
|
4523
|
+
const devices = (await Promise.all(groups.map((group) => coordinatorListDevicesAction({
|
|
4524
|
+
groupId: group.group_id,
|
|
4525
|
+
includeDisabled: true,
|
|
4526
|
+
remoteUrl,
|
|
4527
|
+
adminSecret
|
|
4528
|
+
})))).flat();
|
|
4529
|
+
if (devices.length > 500) throw new Error("coordinator_evidence_too_large");
|
|
4530
|
+
const matches = devices.filter((device) => device.device_id === deviceId);
|
|
4531
|
+
if (new Set(matches.map((device) => `${device.public_key}:${device.fingerprint}`)).size > 1) throw new Error("device_enrollment_conflict");
|
|
4532
|
+
return [...new Set(matches.map((device) => device.group_id))].sort();
|
|
4533
|
+
}
|
|
4534
|
+
async function renameEnrolledGroups(config, groups, deviceId, name) {
|
|
4535
|
+
let renamed = 0;
|
|
4536
|
+
for (const groupId of groups) try {
|
|
4537
|
+
if (!await coordinatorRenameDeviceAction({
|
|
4538
|
+
groupId,
|
|
4539
|
+
deviceId,
|
|
4540
|
+
displayName: name,
|
|
4541
|
+
remoteUrl: config.syncCoordinatorUrl || null,
|
|
4542
|
+
adminSecret: config.syncCoordinatorAdminSecret || null
|
|
4543
|
+
})) break;
|
|
4544
|
+
renamed += 1;
|
|
4545
|
+
} catch {
|
|
4546
|
+
break;
|
|
4547
|
+
}
|
|
4548
|
+
return renamed;
|
|
4549
|
+
}
|
|
4550
|
+
async function renameDevice(store, deviceId, name, provenance) {
|
|
4551
|
+
const config = readCoordinatorSyncConfig();
|
|
4552
|
+
if (provenance === "coordinator_enrollment" && !config.syncCoordinatorUrl) return {
|
|
4553
|
+
ok: false,
|
|
4554
|
+
error: "coordinator_device_names_unavailable",
|
|
4555
|
+
status: 503
|
|
4556
|
+
};
|
|
4557
|
+
let groups = [];
|
|
4558
|
+
if (config.syncCoordinatorUrl) {
|
|
4559
|
+
try {
|
|
4560
|
+
groups = await enrolledGroups(config, deviceId);
|
|
4561
|
+
} catch (error) {
|
|
4562
|
+
if (error instanceof Error && error.message === "device_enrollment_conflict") return {
|
|
4563
|
+
ok: false,
|
|
4564
|
+
error: "device_enrollment_conflict",
|
|
4565
|
+
status: 409
|
|
4566
|
+
};
|
|
4567
|
+
return {
|
|
4568
|
+
ok: false,
|
|
4569
|
+
error: "coordinator_device_names_unavailable",
|
|
4570
|
+
status: 503
|
|
4571
|
+
};
|
|
4572
|
+
}
|
|
4573
|
+
if (provenance === "coordinator_enrollment" && groups.length === 0) return {
|
|
4574
|
+
ok: false,
|
|
4575
|
+
error: "device_enrollment_unavailable",
|
|
4576
|
+
status: 409
|
|
4577
|
+
};
|
|
4578
|
+
}
|
|
4579
|
+
const renamedGroupCount = await renameEnrolledGroups(config, groups, deviceId, name);
|
|
4580
|
+
if (renamedGroupCount !== groups.length) return {
|
|
4581
|
+
ok: false,
|
|
4582
|
+
error: "coordinator_device_rename_incomplete",
|
|
4583
|
+
status: 503,
|
|
4584
|
+
renamedGroupCount
|
|
4585
|
+
};
|
|
4586
|
+
if (!store.db.transaction(() => {
|
|
4587
|
+
const result = store.db.prepare("UPDATE identity_devices SET display_name = ?, updated_at = ? WHERE device_id = ? AND status = 'active'").run(name, (/* @__PURE__ */ new Date()).toISOString(), deviceId);
|
|
4588
|
+
if (result.changes) store.db.prepare("UPDATE sync_peers SET name = ? WHERE peer_device_id = ?").run(name, deviceId);
|
|
4589
|
+
return result.changes;
|
|
4590
|
+
})()) return {
|
|
4591
|
+
ok: false,
|
|
4592
|
+
error: "device_not_found",
|
|
4593
|
+
status: 409
|
|
4594
|
+
};
|
|
4595
|
+
return {
|
|
4596
|
+
ok: true,
|
|
4597
|
+
display_name: name
|
|
4598
|
+
};
|
|
4599
|
+
}
|
|
4600
|
+
function deviceRenameRoutes(getStore) {
|
|
4601
|
+
const pendingDevices = /* @__PURE__ */ new Set();
|
|
4602
|
+
return new Hono().post("/api/sync/recipient-policy/v1/devices/:device_id/rename", async (c) => {
|
|
4603
|
+
const store = getStore();
|
|
4604
|
+
const deviceId = String(c.req.param("device_id") ?? "").trim();
|
|
4605
|
+
const binding = store.db.prepare("SELECT provenance FROM identity_devices WHERE device_id = ? AND status = 'active'").get(deviceId);
|
|
4606
|
+
if (!binding) return c.json({ error: "device_not_found" }, 404);
|
|
4607
|
+
let body;
|
|
4608
|
+
try {
|
|
4609
|
+
body = await c.req.json();
|
|
4610
|
+
} catch {
|
|
4611
|
+
return c.json({ error: "invalid_json" }, 400);
|
|
4612
|
+
}
|
|
4613
|
+
let name;
|
|
4614
|
+
try {
|
|
4615
|
+
name = normalizeHumanPresentationName(String(body.display_name ?? ""), "display_name");
|
|
4616
|
+
} catch {
|
|
4617
|
+
return c.json({ error: "display_name_invalid" }, 400);
|
|
4618
|
+
}
|
|
4619
|
+
if (pendingDevices.has(deviceId)) return c.json({ error: "device_rename_busy" }, 409);
|
|
4620
|
+
pendingDevices.add(deviceId);
|
|
4621
|
+
try {
|
|
4622
|
+
const result = await renameDevice(store, deviceId, name, binding.provenance);
|
|
4623
|
+
if (!result.ok) return c.json(result, result.status);
|
|
4624
|
+
return c.json(result);
|
|
4625
|
+
} catch {
|
|
4626
|
+
return c.json({ error: "device_rename_failed" }, 503);
|
|
4627
|
+
} finally {
|
|
4628
|
+
pendingDevices.delete(deviceId);
|
|
4629
|
+
}
|
|
4630
|
+
});
|
|
4631
|
+
}
|
|
4632
|
+
//#endregion
|
|
4461
4633
|
//#region src/routes/team-setup-view.ts
|
|
4462
4634
|
var enabled = {
|
|
4463
4635
|
enabled: true,
|
|
@@ -7429,6 +7601,21 @@ function recipientPolicyPresenceCapabilityExpiresAt(enrollment, observedAt) {
|
|
|
7429
7601
|
function recipientPolicyEnrollmentValueIsValid(value) {
|
|
7430
7602
|
return typeof value === "string" && value.length > 0 && value === value.trim();
|
|
7431
7603
|
}
|
|
7604
|
+
function recipientPolicyPresenceCapabilityExpiries(enrollments, observedAt) {
|
|
7605
|
+
return new Map(enrollments.map((enrollment) => [enrollment.device_id, recipientPolicyPresenceCapabilityExpiresAt(enrollment, observedAt)]));
|
|
7606
|
+
}
|
|
7607
|
+
function recipientPolicySnapshotUnavailable(stage, error) {
|
|
7608
|
+
console.warn(`[sync] recipient policy coordinator snapshot failed: stage=${stage} code=${coordinatorEnrollmentFailureCode(error)}`);
|
|
7609
|
+
throw new Error("recipient_policy_snapshot_not_fresh");
|
|
7610
|
+
}
|
|
7611
|
+
async function readRecipientPolicyCoordinatorSnapshot(read) {
|
|
7612
|
+
for (let attempt = 0;; attempt++) try {
|
|
7613
|
+
return await read();
|
|
7614
|
+
} catch (error) {
|
|
7615
|
+
if (!(error instanceof RemoteCoordinatorRequestError) || error.status !== 429 || attempt >= 2) throw error;
|
|
7616
|
+
await new Promise((resolve) => setTimeout(resolve, (attempt + 1) * 1e3));
|
|
7617
|
+
}
|
|
7618
|
+
}
|
|
7432
7619
|
function createRecipientPolicyReconcilerEffects(store, options = {}) {
|
|
7433
7620
|
const config = options.config ?? readCoordinatorSyncConfig();
|
|
7434
7621
|
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -7470,15 +7657,13 @@ function createRecipientPolicyReconcilerEffects(store, options = {}) {
|
|
|
7470
7657
|
now,
|
|
7471
7658
|
snapshot: async ({ scopeId }) => {
|
|
7472
7659
|
const targetOptions = coordinatorOptions(scopeId);
|
|
7473
|
-
const snapshotMemberships = (await coordinatorListScopeMembershipsAction({
|
|
7660
|
+
const snapshotMemberships = (await readRecipientPolicyCoordinatorSnapshot(() => coordinatorListScopeMembershipsAction({
|
|
7474
7661
|
groupId: targetOptions.groupId,
|
|
7475
7662
|
scopeId,
|
|
7476
7663
|
includeRevoked: true,
|
|
7477
7664
|
remoteUrl: targetOptions.remoteUrl,
|
|
7478
7665
|
adminSecret: targetOptions.adminSecret
|
|
7479
|
-
}).catch(() => {
|
|
7480
|
-
throw new Error("recipient_policy_snapshot_not_fresh");
|
|
7481
|
-
})).map((membership) => {
|
|
7666
|
+
})).catch((error) => recipientPolicySnapshotUnavailable("scope_memberships", error))).map((membership) => {
|
|
7482
7667
|
if (typeof membership.device_id !== "string" || membership.status !== "active" && membership.status !== "revoked") throw new Error("recipient_policy_snapshot_invalid");
|
|
7483
7668
|
const status = membership.status;
|
|
7484
7669
|
return {
|
|
@@ -7499,15 +7684,13 @@ function createRecipientPolicyReconcilerEffects(store, options = {}) {
|
|
|
7499
7684
|
listBoundaryEnrollments: async ({ scopeId }) => {
|
|
7500
7685
|
const targetOptions = coordinatorOptions(scopeId);
|
|
7501
7686
|
const observedAt = now();
|
|
7502
|
-
const enrollments = await listDevices({
|
|
7687
|
+
const enrollments = await readRecipientPolicyCoordinatorSnapshot(() => listDevices({
|
|
7503
7688
|
groupId: targetOptions.groupId,
|
|
7504
7689
|
includeDisabled: true,
|
|
7505
7690
|
remoteUrl: targetOptions.remoteUrl,
|
|
7506
7691
|
adminSecret: targetOptions.adminSecret
|
|
7507
|
-
}).catch(() =>
|
|
7508
|
-
|
|
7509
|
-
});
|
|
7510
|
-
const presenceCapabilityExpiries = new Map(enrollments.map((enrollment) => [enrollment.device_id, recipientPolicyPresenceCapabilityExpiresAt(enrollment, observedAt)]));
|
|
7692
|
+
})).catch((error) => recipientPolicySnapshotUnavailable("device_enrollments", error));
|
|
7693
|
+
const presenceCapabilityExpiries = recipientPolicyPresenceCapabilityExpiries(enrollments, observedAt);
|
|
7511
7694
|
const mapped = enrollments.map((enrollment) => {
|
|
7512
7695
|
if (enrollment.group_id !== targetOptions.groupId || !recipientPolicyEnrollmentValueIsValid(enrollment.device_id) || !recipientPolicyEnrollmentValueIsValid(enrollment.public_key) || !recipientPolicyEnrollmentValueIsValid(enrollment.fingerprint) || fingerprintPublicKey(enrollment.public_key) !== enrollment.fingerprint || enrollment.enabled !== 0 && enrollment.enabled !== 1 || enrollment.identity_id !== null && !recipientPolicyEnrollmentValueIsValid(enrollment.identity_id)) throw new Error("recipient_policy_snapshot_invalid");
|
|
7513
7696
|
return {
|
|
@@ -9959,7 +10142,7 @@ function syncRoutes(getStore, getSyncRuntimeStatus, options = {}) {
|
|
|
9959
10142
|
localDeviceId: store.deviceId
|
|
9960
10143
|
}));
|
|
9961
10144
|
});
|
|
9962
|
-
app.get("/api/sync/recipient-policy/v1/intent", (c) => {
|
|
10145
|
+
app.route("/", deviceRenameRoutes(getStore)).get("/api/sync/recipient-policy/v1/intent", (c) => {
|
|
9963
10146
|
const store = getStore();
|
|
9964
10147
|
return c.json(listRecipientPolicyIntent(store.db));
|
|
9965
10148
|
});
|