@prmichaelsen/remember-mcp 3.0.0 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/AGENT.md +296 -250
  2. package/CHANGELOG.md +358 -0
  3. package/README.md +68 -45
  4. package/agent/commands/acp.clarification-create.md +382 -0
  5. package/agent/commands/acp.project-info.md +309 -0
  6. package/agent/commands/acp.project-remove.md +379 -0
  7. package/agent/commands/acp.project-update.md +296 -0
  8. package/agent/commands/acp.task-create.md +17 -9
  9. package/agent/commands/git.commit.md +13 -1
  10. package/agent/design/comment-memory-type.md +2 -2
  11. package/agent/design/local.collaborative-memory-sync.md +265 -0
  12. package/agent/design/local.content-flags.md +210 -0
  13. package/agent/design/local.ghost-persona-system.md +273 -0
  14. package/agent/design/local.group-acl-integration.md +338 -0
  15. package/agent/design/local.memory-acl-schema.md +352 -0
  16. package/agent/design/local.memory-collection-pattern-v2.md +348 -0
  17. package/agent/design/local.moderation-and-space-config.md +257 -0
  18. package/agent/design/local.v2-api-reference.md +621 -0
  19. package/agent/design/local.v2-migration-guide.md +191 -0
  20. package/agent/design/local.v2-usage-examples.md +265 -0
  21. package/agent/design/permissions-storage-architecture.md +11 -3
  22. package/agent/design/trust-escalation-prevention.md +9 -2
  23. package/agent/design/trust-system-implementation.md +12 -3
  24. package/agent/milestones/milestone-14-memory-collection-v2.md +182 -0
  25. package/agent/milestones/milestone-15-moderation-space-config.md +126 -0
  26. package/agent/progress.yaml +628 -49
  27. package/agent/scripts/acp.common.sh +2 -0
  28. package/agent/scripts/acp.install.sh +11 -1
  29. package/agent/scripts/acp.package-install-optimized.sh +454 -0
  30. package/agent/scripts/acp.package-install.sh +247 -300
  31. package/agent/scripts/acp.project-info.sh +218 -0
  32. package/agent/scripts/acp.project-remove.sh +302 -0
  33. package/agent/scripts/acp.project-update.sh +296 -0
  34. package/agent/scripts/acp.yaml-parser.sh +128 -10
  35. package/agent/tasks/milestone-14-memory-collection-v2/task-165-core-infrastructure-setup.md +171 -0
  36. package/agent/tasks/milestone-14-memory-collection-v2/task-166-update-remember-publish.md +191 -0
  37. package/agent/tasks/milestone-14-memory-collection-v2/task-167-update-remember-retract.md +186 -0
  38. package/agent/tasks/milestone-14-memory-collection-v2/task-168-implement-remember-revise.md +184 -0
  39. package/agent/tasks/milestone-14-memory-collection-v2/task-169-update-remember-search-space.md +179 -0
  40. package/agent/tasks/milestone-14-memory-collection-v2/task-170-update-remember-create-update.md +139 -0
  41. package/agent/tasks/milestone-14-memory-collection-v2/task-172-performance-testing-optimization.md +161 -0
  42. package/agent/tasks/milestone-14-memory-collection-v2/task-173-documentation-examples.md +258 -0
  43. package/agent/tasks/milestone-15-moderation-space-config/task-174-add-moderation-schema-fields.md +57 -0
  44. package/agent/tasks/milestone-15-moderation-space-config/task-175-create-space-config-service.md +64 -0
  45. package/agent/tasks/milestone-15-moderation-space-config/task-176-wire-moderation-publish-flow.md +45 -0
  46. package/agent/tasks/milestone-15-moderation-space-config/task-177-add-moderation-search-filters.md +70 -0
  47. package/agent/tasks/milestone-15-moderation-space-config/task-178-create-remember-moderate-tool.md +69 -0
  48. package/agent/tasks/milestone-15-moderation-space-config/task-179-documentation-integration-tests.md +58 -0
  49. package/agent/tasks/milestone-16-ghost-system/task-187-ghost-config-firestore.md +41 -0
  50. package/agent/tasks/milestone-16-ghost-system/task-188-trust-filter-integration.md +44 -0
  51. package/agent/tasks/milestone-16-ghost-system/task-189-ghost-memory-filtering.md +43 -0
  52. package/agent/tasks/milestone-16-ghost-system/task-190-ghost-config-tools.md +45 -0
  53. package/agent/tasks/milestone-16-ghost-system/task-191-escalation-firestore.md +38 -0
  54. package/agent/tasks/milestone-16-ghost-system/task-192-documentation-verification.md +39 -0
  55. package/agent/tasks/milestone-7-trust-permissions/task-180-access-result-permission-types.md +69 -0
  56. package/agent/tasks/milestone-7-trust-permissions/task-181-firestore-permissions-access-logs.md +56 -0
  57. package/agent/tasks/milestone-7-trust-permissions/task-182-trust-enforcement-service.md +68 -0
  58. package/agent/tasks/milestone-7-trust-permissions/task-183-access-control-service.md +70 -0
  59. package/agent/tasks/milestone-7-trust-permissions/task-184-permission-tools.md +79 -0
  60. package/agent/tasks/milestone-7-trust-permissions/task-185-wire-trust-into-search-query.md +55 -0
  61. package/agent/tasks/milestone-7-trust-permissions/task-186-documentation-verification.md +56 -0
  62. package/agent/tasks/task-76-fix-indexnullstate-schema-bug.md +197 -0
  63. package/dist/collections/composite-ids.d.ts +106 -0
  64. package/dist/collections/core-infrastructure.spec.d.ts +11 -0
  65. package/dist/collections/dot-notation.d.ts +106 -0
  66. package/dist/collections/tracking-arrays.d.ts +176 -0
  67. package/dist/constants/content-types.d.ts +1 -0
  68. package/dist/schema/v2-collections-comments.spec.d.ts +8 -0
  69. package/dist/schema/v2-collections.d.ts +210 -0
  70. package/dist/server-factory.d.ts +15 -0
  71. package/dist/server-factory.js +2798 -1029
  72. package/dist/server.js +2526 -1012
  73. package/dist/services/access-control.d.ts +103 -0
  74. package/dist/services/access-control.spec.d.ts +2 -0
  75. package/dist/services/credentials-provider.d.ts +24 -0
  76. package/dist/services/credentials-provider.spec.d.ts +2 -0
  77. package/dist/services/escalation.service.d.ts +22 -0
  78. package/dist/services/escalation.service.spec.d.ts +2 -0
  79. package/dist/services/ghost-config.service.d.ts +55 -0
  80. package/dist/services/ghost-config.service.spec.d.ts +2 -0
  81. package/dist/services/space-config.service.d.ts +23 -0
  82. package/dist/services/space-config.service.spec.d.ts +2 -0
  83. package/dist/services/trust-enforcement.d.ts +83 -0
  84. package/dist/services/trust-enforcement.spec.d.ts +2 -0
  85. package/dist/services/trust-validator.d.ts +43 -0
  86. package/dist/services/trust-validator.spec.d.ts +2 -0
  87. package/dist/tools/confirm-publish-moderation.spec.d.ts +8 -0
  88. package/dist/tools/confirm.d.ts +8 -1
  89. package/dist/tools/create-memory.d.ts +2 -1
  90. package/dist/tools/create-memory.spec.d.ts +10 -0
  91. package/dist/tools/create-relationship.d.ts +2 -1
  92. package/dist/tools/delete-memory.d.ts +2 -1
  93. package/dist/tools/delete-relationship.d.ts +2 -1
  94. package/dist/tools/deny.d.ts +2 -1
  95. package/dist/tools/find-similar.d.ts +2 -1
  96. package/dist/tools/get-preferences.d.ts +2 -1
  97. package/dist/tools/ghost-config.d.ts +27 -0
  98. package/dist/tools/ghost-config.spec.d.ts +2 -0
  99. package/dist/tools/moderate.d.ts +20 -0
  100. package/dist/tools/moderate.spec.d.ts +5 -0
  101. package/dist/tools/publish.d.ts +11 -3
  102. package/dist/tools/query-memory.d.ts +3 -1
  103. package/dist/tools/query-space.d.ts +4 -1
  104. package/dist/tools/retract.d.ts +29 -0
  105. package/dist/tools/revise.d.ts +45 -0
  106. package/dist/tools/revise.spec.d.ts +8 -0
  107. package/dist/tools/search-memory.d.ts +2 -1
  108. package/dist/tools/search-relationship.d.ts +2 -1
  109. package/dist/tools/search-space.d.ts +25 -5
  110. package/dist/tools/search-space.spec.d.ts +9 -0
  111. package/dist/tools/set-preference.d.ts +2 -1
  112. package/dist/tools/update-memory.d.ts +2 -1
  113. package/dist/tools/update-relationship.d.ts +2 -1
  114. package/dist/types/access-result.d.ts +48 -0
  115. package/dist/types/access-result.spec.d.ts +2 -0
  116. package/dist/types/auth.d.ts +46 -0
  117. package/dist/types/ghost-config.d.ts +36 -0
  118. package/dist/types/memory.d.ts +3 -1
  119. package/dist/types/preferences.d.ts +1 -1
  120. package/dist/utils/auth-helpers.d.ts +14 -0
  121. package/dist/utils/auth-helpers.spec.d.ts +2 -0
  122. package/dist/utils/test-data-generator.d.ts +124 -0
  123. package/dist/utils/test-data-generator.spec.d.ts +12 -0
  124. package/dist/v2-performance.e2e.d.ts +17 -0
  125. package/dist/v2-smoke.e2e.d.ts +14 -0
  126. package/dist/weaviate/client.d.ts +5 -8
  127. package/dist/weaviate/space-schema.d.ts +2 -2
  128. package/docs/performance/v2-benchmarks.md +80 -0
  129. package/jest.e2e.config.js +14 -3
  130. package/package.json +1 -1
  131. package/scripts/.collection-recreation-state.yaml +16 -0
  132. package/scripts/.gitkeep +5 -0
  133. package/scripts/README-collection-recreation.md +224 -0
  134. package/scripts/README.md +51 -0
  135. package/scripts/backup-collections.ts +543 -0
  136. package/scripts/delete-collection.ts +137 -0
  137. package/scripts/migrate-recreate-collections.ts +578 -0
  138. package/scripts/migrate-v1-to-v2.ts +1094 -0
  139. package/scripts/package-lock.json +1113 -0
  140. package/scripts/package.json +27 -0
  141. package/src/collections/composite-ids.ts +193 -0
  142. package/src/collections/core-infrastructure.spec.ts +353 -0
  143. package/src/collections/dot-notation.ts +212 -0
  144. package/src/collections/tracking-arrays.ts +298 -0
  145. package/src/constants/content-types.ts +20 -0
  146. package/src/schema/v2-collections-comments.spec.ts +141 -0
  147. package/src/schema/v2-collections.ts +433 -0
  148. package/src/server-factory.ts +89 -20
  149. package/src/server.ts +45 -17
  150. package/src/services/access-control.spec.ts +383 -0
  151. package/src/services/access-control.ts +291 -0
  152. package/src/services/credentials-provider.spec.ts +22 -0
  153. package/src/services/credentials-provider.ts +34 -0
  154. package/src/services/escalation.service.spec.ts +183 -0
  155. package/src/services/escalation.service.ts +150 -0
  156. package/src/services/ghost-config.service.spec.ts +339 -0
  157. package/src/services/ghost-config.service.ts +219 -0
  158. package/src/services/space-config.service.spec.ts +102 -0
  159. package/src/services/space-config.service.ts +79 -0
  160. package/src/services/trust-enforcement.spec.ts +309 -0
  161. package/src/services/trust-enforcement.ts +197 -0
  162. package/src/services/trust-validator.spec.ts +108 -0
  163. package/src/services/trust-validator.ts +105 -0
  164. package/src/tools/confirm-publish-moderation.spec.ts +240 -0
  165. package/src/tools/confirm.ts +869 -135
  166. package/src/tools/create-memory.spec.ts +126 -0
  167. package/src/tools/create-memory.ts +20 -27
  168. package/src/tools/create-relationship.ts +17 -8
  169. package/src/tools/delete-memory.ts +13 -6
  170. package/src/tools/delete-relationship.ts +15 -6
  171. package/src/tools/deny.ts +8 -1
  172. package/src/tools/find-similar.ts +21 -8
  173. package/src/tools/get-preferences.ts +10 -1
  174. package/src/tools/ghost-config.spec.ts +180 -0
  175. package/src/tools/ghost-config.ts +230 -0
  176. package/src/tools/moderate.spec.ts +277 -0
  177. package/src/tools/moderate.ts +219 -0
  178. package/src/tools/publish.ts +99 -41
  179. package/src/tools/query-memory.ts +28 -6
  180. package/src/tools/query-space.ts +39 -4
  181. package/src/tools/retract.ts +292 -0
  182. package/src/tools/revise.spec.ts +146 -0
  183. package/src/tools/revise.ts +283 -0
  184. package/src/tools/search-memory.ts +30 -7
  185. package/src/tools/search-relationship.ts +11 -2
  186. package/src/tools/search-space.spec.ts +341 -0
  187. package/src/tools/search-space.ts +323 -99
  188. package/src/tools/set-preference.ts +10 -1
  189. package/src/tools/update-memory.ts +16 -5
  190. package/src/tools/update-relationship.ts +10 -1
  191. package/src/types/access-result.spec.ts +193 -0
  192. package/src/types/access-result.ts +62 -0
  193. package/src/types/auth.ts +52 -0
  194. package/src/types/ghost-config.ts +46 -0
  195. package/src/types/memory.ts +9 -1
  196. package/src/types/preferences.ts +2 -2
  197. package/src/utils/auth-helpers.spec.ts +75 -0
  198. package/src/utils/auth-helpers.ts +25 -0
  199. package/src/utils/test-data-generator.spec.ts +317 -0
  200. package/src/utils/test-data-generator.ts +292 -0
  201. package/src/utils/weaviate-filters.ts +4 -4
  202. package/src/v2-performance.e2e.ts +173 -0
  203. package/src/v2-smoke.e2e.ts +401 -0
  204. package/src/weaviate/client.spec.ts +5 -5
  205. package/src/weaviate/client.ts +51 -36
  206. package/src/weaviate/schema.ts +11 -256
  207. package/src/weaviate/space-schema.spec.ts +24 -24
  208. package/src/weaviate/space-schema.ts +18 -6
@@ -7,6 +7,8 @@ import type { RelationshipUpdate } from '../types/memory.js';
7
7
  import { getMemoryCollection } from '../weaviate/schema.js';
8
8
  import { logger } from '../utils/logger.js';
9
9
  import { handleToolError } from '../utils/error-handler.js';
10
+ import { createDebugLogger } from '../utils/debug.js';
11
+ import type { AuthContext } from '../types/auth.js';
10
12
 
11
13
  /**
12
14
  * Tool definition for remember_update_relationship
@@ -89,9 +91,15 @@ export interface UpdateRelationshipResult {
89
91
  */
90
92
  export async function handleUpdateRelationship(
91
93
  args: UpdateRelationshipArgs,
92
- userId: string
94
+ userId: string,
95
+ authContext?: AuthContext
93
96
  ): Promise<string> {
97
+ const debug = createDebugLogger({ tool: 'remember_update_relationship', userId, operation: 'update relationship' });
98
+
94
99
  try {
100
+ debug.info('Tool invoked');
101
+ debug.trace('Arguments', { args });
102
+
95
103
  logger.info('Updating relationship', { userId, relationshipId: args.relationship_id });
96
104
 
97
105
  const collection = getMemoryCollection(userId);
@@ -184,6 +192,7 @@ export async function handleUpdateRelationship(
184
192
 
185
193
  return JSON.stringify(result, null, 2);
186
194
  } catch (error) {
195
+ debug.error('Tool failed', { error: error instanceof Error ? error.message : String(error) });
187
196
  handleToolError(error, {
188
197
  toolName: 'remember_update_relationship',
189
198
  operation: 'update relationship',
@@ -0,0 +1,193 @@
1
+ import type {
2
+ AccessResult,
3
+ AccessGranted,
4
+ AccessInsufficientTrust,
5
+ AccessBlocked,
6
+ AccessNoPermission,
7
+ AccessNotFound,
8
+ AccessDeleted,
9
+ AccessResultStatus,
10
+ } from './access-result.js';
11
+ import type { Memory } from './memory.js';
12
+ import { DEFAULT_GHOST_CONFIG, type GhostConfig, type TrustEnforcementMode } from './ghost-config.js';
13
+
14
+ // Minimal Memory fixture for testing type narrowing
15
+ const mockMemory: Memory = {
16
+ id: 'mem-1',
17
+ user_id: 'user-owner',
18
+ doc_type: 'memory',
19
+ content: 'Test memory',
20
+ type: 'note',
21
+ weight: 0.5,
22
+ trust: 0.5,
23
+ location: { gps: null, address: null, source: 'unavailable', confidence: 0, is_approximate: true },
24
+ context: { timestamp: '2026-01-01T00:00:00Z', source: { type: 'manual' } },
25
+ relationships: [],
26
+ access_count: 0,
27
+ created_at: '2026-01-01T00:00:00Z',
28
+ updated_at: '2026-01-01T00:00:00Z',
29
+ version: 1,
30
+ tags: [],
31
+ base_weight: 0.5,
32
+ } as Memory;
33
+
34
+ describe('AccessResult type narrowing', () => {
35
+ it('narrows to AccessGranted', () => {
36
+ const result: AccessResult = {
37
+ status: 'granted',
38
+ memory: mockMemory,
39
+ access_level: 'owner',
40
+ };
41
+ if (result.status === 'granted') {
42
+ expect(result.memory.id).toBe('mem-1');
43
+ expect(result.access_level).toBe('owner');
44
+ }
45
+ });
46
+
47
+ it('narrows to AccessGranted with trusted level', () => {
48
+ const result: AccessResult = {
49
+ status: 'granted',
50
+ memory: mockMemory,
51
+ access_level: 'trusted',
52
+ };
53
+ if (result.status === 'granted') {
54
+ expect(result.access_level).toBe('trusted');
55
+ }
56
+ });
57
+
58
+ it('narrows to AccessInsufficientTrust', () => {
59
+ const result: AccessResult = {
60
+ status: 'insufficient_trust',
61
+ memory_id: 'mem-1',
62
+ required_trust: 0.75,
63
+ actual_trust: 0.25,
64
+ attempts_remaining: 2,
65
+ };
66
+ if (result.status === 'insufficient_trust') {
67
+ expect(result.required_trust).toBe(0.75);
68
+ expect(result.actual_trust).toBe(0.25);
69
+ expect(result.attempts_remaining).toBe(2);
70
+ }
71
+ });
72
+
73
+ it('narrows to AccessBlocked', () => {
74
+ const result: AccessResult = {
75
+ status: 'blocked',
76
+ memory_id: 'mem-1',
77
+ reason: 'Repeated unauthorized attempts',
78
+ blocked_at: '2026-01-15T10:00:00Z',
79
+ };
80
+ if (result.status === 'blocked') {
81
+ expect(result.reason).toBe('Repeated unauthorized attempts');
82
+ expect(result.blocked_at).toBe('2026-01-15T10:00:00Z');
83
+ }
84
+ });
85
+
86
+ it('narrows to AccessNoPermission', () => {
87
+ const result: AccessResult = {
88
+ status: 'no_permission',
89
+ owner_user_id: 'user-owner',
90
+ accessor_user_id: 'user-accessor',
91
+ };
92
+ if (result.status === 'no_permission') {
93
+ expect(result.owner_user_id).toBe('user-owner');
94
+ expect(result.accessor_user_id).toBe('user-accessor');
95
+ }
96
+ });
97
+
98
+ it('narrows to AccessNotFound', () => {
99
+ const result: AccessResult = {
100
+ status: 'not_found',
101
+ memory_id: 'mem-missing',
102
+ };
103
+ if (result.status === 'not_found') {
104
+ expect(result.memory_id).toBe('mem-missing');
105
+ }
106
+ });
107
+
108
+ it('narrows to AccessDeleted', () => {
109
+ const result: AccessResult = {
110
+ status: 'deleted',
111
+ memory_id: 'mem-deleted',
112
+ deleted_at: '2026-01-10T08:00:00Z',
113
+ };
114
+ if (result.status === 'deleted') {
115
+ expect(result.memory_id).toBe('mem-deleted');
116
+ expect(result.deleted_at).toBe('2026-01-10T08:00:00Z');
117
+ }
118
+ });
119
+
120
+ it('switch statement covers all variants exhaustively', () => {
121
+ const results: AccessResult[] = [
122
+ { status: 'granted', memory: mockMemory, access_level: 'owner' },
123
+ { status: 'insufficient_trust', memory_id: 'mem-1', required_trust: 0.5, actual_trust: 0.1, attempts_remaining: 1 },
124
+ { status: 'blocked', memory_id: 'mem-1', reason: 'blocked', blocked_at: '2026-01-01T00:00:00Z' },
125
+ { status: 'no_permission', owner_user_id: 'owner', accessor_user_id: 'accessor' },
126
+ { status: 'not_found', memory_id: 'mem-1' },
127
+ { status: 'deleted', memory_id: 'mem-1', deleted_at: '2026-01-01T00:00:00Z' },
128
+ ];
129
+
130
+ const statuses: AccessResultStatus[] = [];
131
+ for (const result of results) {
132
+ switch (result.status) {
133
+ case 'granted':
134
+ statuses.push(result.status);
135
+ break;
136
+ case 'insufficient_trust':
137
+ statuses.push(result.status);
138
+ break;
139
+ case 'blocked':
140
+ statuses.push(result.status);
141
+ break;
142
+ case 'no_permission':
143
+ statuses.push(result.status);
144
+ break;
145
+ case 'not_found':
146
+ statuses.push(result.status);
147
+ break;
148
+ case 'deleted':
149
+ statuses.push(result.status);
150
+ break;
151
+ }
152
+ }
153
+
154
+ expect(statuses).toEqual([
155
+ 'granted',
156
+ 'insufficient_trust',
157
+ 'blocked',
158
+ 'no_permission',
159
+ 'not_found',
160
+ 'deleted',
161
+ ]);
162
+ });
163
+ });
164
+
165
+ describe('GhostConfig defaults', () => {
166
+ it('has correct default values', () => {
167
+ expect(DEFAULT_GHOST_CONFIG.enabled).toBe(false);
168
+ expect(DEFAULT_GHOST_CONFIG.public_ghost_enabled).toBe(false);
169
+ expect(DEFAULT_GHOST_CONFIG.default_friend_trust).toBe(0.25);
170
+ expect(DEFAULT_GHOST_CONFIG.default_public_trust).toBe(0);
171
+ expect(DEFAULT_GHOST_CONFIG.per_user_trust).toEqual({});
172
+ expect(DEFAULT_GHOST_CONFIG.blocked_users).toEqual([]);
173
+ expect(DEFAULT_GHOST_CONFIG.enforcement_mode).toBe('query');
174
+ });
175
+
176
+ it('GhostConfig accepts valid per_user_trust overrides', () => {
177
+ const config: GhostConfig = {
178
+ ...DEFAULT_GHOST_CONFIG,
179
+ enabled: true,
180
+ per_user_trust: { 'user-friend': 0.75, 'user-close': 1.0 },
181
+ };
182
+ expect(config.per_user_trust['user-friend']).toBe(0.75);
183
+ expect(config.per_user_trust['user-close']).toBe(1.0);
184
+ });
185
+
186
+ it('GhostConfig accepts all enforcement modes', () => {
187
+ const modes: TrustEnforcementMode[] = ['query', 'prompt', 'hybrid'];
188
+ for (const mode of modes) {
189
+ const config: GhostConfig = { ...DEFAULT_GHOST_CONFIG, enforcement_mode: mode };
190
+ expect(config.enforcement_mode).toBe(mode);
191
+ }
192
+ });
193
+ });
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Discriminated union for type-safe access control responses.
3
+ * See agent/design/access-control-result-pattern.md
4
+ */
5
+
6
+ import type { Memory } from './memory.js';
7
+
8
+ /** Access granted — owner or trusted cross-user access */
9
+ export interface AccessGranted {
10
+ status: 'granted';
11
+ memory: Memory;
12
+ access_level: 'owner' | 'trusted';
13
+ }
14
+
15
+ /** Trust level insufficient for this memory */
16
+ export interface AccessInsufficientTrust {
17
+ status: 'insufficient_trust';
18
+ memory_id: string;
19
+ required_trust: number;
20
+ actual_trust: number;
21
+ attempts_remaining: number;
22
+ }
23
+
24
+ /** Access blocked after repeated unauthorized attempts */
25
+ export interface AccessBlocked {
26
+ status: 'blocked';
27
+ memory_id: string;
28
+ reason: string;
29
+ blocked_at: string; // ISO 8601
30
+ }
31
+
32
+ /** No ghost/permission relationship exists */
33
+ export interface AccessNoPermission {
34
+ status: 'no_permission';
35
+ owner_user_id: string;
36
+ accessor_user_id: string;
37
+ }
38
+
39
+ /** Memory not found */
40
+ export interface AccessNotFound {
41
+ status: 'not_found';
42
+ memory_id: string;
43
+ }
44
+
45
+ /** Memory was deleted */
46
+ export interface AccessDeleted {
47
+ status: 'deleted';
48
+ memory_id: string;
49
+ deleted_at: string; // ISO 8601
50
+ }
51
+
52
+ /** Discriminated union of all access result variants */
53
+ export type AccessResult =
54
+ | AccessGranted
55
+ | AccessInsufficientTrust
56
+ | AccessBlocked
57
+ | AccessNoPermission
58
+ | AccessNotFound
59
+ | AccessDeleted;
60
+
61
+ /** All possible access result statuses */
62
+ export type AccessResultStatus = AccessResult['status'];
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Auth types for group membership validation and access control.
3
+ *
4
+ * These types define the contract for credentials providers and
5
+ * the AuthContext threaded through tool handlers.
6
+ */
7
+
8
+ export interface GroupPermissions {
9
+ can_read: boolean;
10
+ can_publish: boolean;
11
+ can_revise: boolean;
12
+ can_propose: boolean;
13
+ can_overwrite: boolean;
14
+ can_comment: boolean;
15
+ can_retract_own: boolean;
16
+ can_retract_any: boolean;
17
+ can_manage_members: boolean;
18
+ can_moderate: boolean;
19
+ }
20
+
21
+ export interface GroupMembership {
22
+ group_id: string;
23
+ permissions: GroupPermissions;
24
+ }
25
+
26
+ export interface UserCredentials {
27
+ user_id: string;
28
+ group_memberships: GroupMembership[];
29
+ }
30
+
31
+ /** Ghost conversation context — resolved server-side, never from tool args */
32
+ export interface GhostModeContext {
33
+ /** The ghost owner's user ID (whose memories are being searched) */
34
+ owner_user_id: string;
35
+ /** The accessor's user ID (who is chatting with the ghost) */
36
+ accessor_user_id: string;
37
+ /** Resolved trust level (looked up from GhostConfig, not user-supplied) */
38
+ accessor_trust_level: number;
39
+ }
40
+
41
+ export interface AuthContext {
42
+ accessToken: string | null;
43
+ credentials: UserCredentials | null;
44
+ /** Present when the server is running in ghost conversation mode */
45
+ ghostMode?: GhostModeContext;
46
+ }
47
+
48
+ export type WriteMode = 'owner_only' | 'group_editors' | 'anyone';
49
+
50
+ export interface CredentialsProvider {
51
+ getCredentials(accessToken: string, userId: string): Promise<UserCredentials>;
52
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Ghost/persona configuration types.
3
+ * See agent/design/local.ghost-persona-system.md
4
+ *
5
+ * GhostConfig is stored in Firestore at users/{ownerUserId}/ghost_config.
6
+ * Trust is owned by remember-mcp (not passed per-request) to prevent
7
+ * prompt injection tampering.
8
+ */
9
+
10
+ /** Trust enforcement mode — how memories are filtered for cross-user access */
11
+ export type TrustEnforcementMode = 'query' | 'prompt' | 'hybrid';
12
+
13
+ /**
14
+ * Per-user ghost configuration stored in Firestore.
15
+ *
16
+ * - query mode (default): memories above threshold never returned from Weaviate
17
+ * - prompt mode: all memories returned, formatted/redacted by trust level
18
+ * - hybrid mode: query filter for trust 0.0, prompt filter for rest
19
+ */
20
+ export interface GhostConfig {
21
+ /** Whether ghost conversations are enabled for this user (default: false) */
22
+ enabled: boolean;
23
+ /** Allow non-friends (strangers) to initiate ghost conversations (default: false) */
24
+ public_ghost_enabled: boolean;
25
+ /** Default trust level for friends (default: 0.25 — metadata only) */
26
+ default_friend_trust: number;
27
+ /** Default trust level for strangers (default: 0 — existence only) */
28
+ default_public_trust: number;
29
+ /** Per-user trust level overrides: userId → trust level (0-1) */
30
+ per_user_trust: Record<string, number>;
31
+ /** Users blocked from ghost access entirely */
32
+ blocked_users: string[];
33
+ /** How trust is enforced when filtering memories (default: 'query') */
34
+ enforcement_mode: TrustEnforcementMode;
35
+ }
36
+
37
+ /** Default GhostConfig values for a new user */
38
+ export const DEFAULT_GHOST_CONFIG: GhostConfig = {
39
+ enabled: false,
40
+ public_ghost_enabled: false,
41
+ default_friend_trust: 0.25,
42
+ default_public_trust: 0,
43
+ per_user_trust: {},
44
+ blocked_users: [],
45
+ enforcement_mode: 'query',
46
+ };
@@ -56,7 +56,10 @@ export type ContentType =
56
56
  | 'system'
57
57
  | 'action'
58
58
  | 'audit'
59
- | 'history';
59
+ | 'history'
60
+ // Cross-user & Threading
61
+ | 'ghost'
62
+ | 'comment';
60
63
 
61
64
  /**
62
65
  * GPS coordinates
@@ -201,6 +204,11 @@ export interface Memory {
201
204
  deleted_at?: Date | null; // Timestamp when memory was soft-deleted (null = not deleted)
202
205
  deleted_by?: string; // User ID who deleted the memory
203
206
  deletion_reason?: string; // Optional reason for deletion
207
+
208
+ // Publication Tracking (Memory Collection Pattern v2)
209
+ // Managed by remember_publish / remember_retract — do NOT modify directly
210
+ space_ids?: string[]; // Spaces this memory has been published to
211
+ group_ids?: string[]; // Groups this memory has been published to
204
212
  }
205
213
 
206
214
  /**
@@ -109,7 +109,7 @@ export const DEFAULT_PREFERENCES: Omit<UserPreferences, 'user_id' | 'created_at'
109
109
  share_with_memories: true,
110
110
  },
111
111
  privacy: {
112
- default_trust_level: 0.5,
112
+ default_trust_level: 0.25,
113
113
  allow_cross_user_access: false,
114
114
  auto_approve_requests: false,
115
115
  audit_logging: true,
@@ -169,7 +169,7 @@ export const PREFERENCE_DESCRIPTIONS = {
169
169
  share_with_memories: 'Include location data in memories (default: true)',
170
170
  },
171
171
  privacy: {
172
- default_trust_level: 'Default trust level for new memories, 0-1 (default: 0.5)',
172
+ default_trust_level: 'Default trust level for new memories, 0-1 (default: 0.25)',
173
173
  allow_cross_user_access: 'Allow other users to request access to memories (default: false)',
174
174
  auto_approve_requests: 'Automatically approve access requests (default: false)',
175
175
  audit_logging: 'Enable audit logging for preference changes (default: true)',
@@ -0,0 +1,75 @@
1
+ import { canModerate, canModerateAny } from './auth-helpers.js';
2
+ import type { AuthContext, GroupPermissions } from '../types/auth.js';
3
+
4
+ const BASE_PERMISSIONS: GroupPermissions = {
5
+ can_read: true,
6
+ can_publish: true,
7
+ can_revise: false,
8
+ can_propose: false,
9
+ can_overwrite: false,
10
+ can_comment: true,
11
+ can_retract_own: true,
12
+ can_retract_any: false,
13
+ can_manage_members: false,
14
+ can_moderate: false,
15
+ };
16
+
17
+ function makeAuthContext(groups: Array<{ group_id: string; can_moderate: boolean }>): AuthContext {
18
+ return {
19
+ accessToken: 'tok',
20
+ credentials: {
21
+ user_id: 'user-1',
22
+ group_memberships: groups.map(g => ({
23
+ group_id: g.group_id,
24
+ permissions: { ...BASE_PERMISSIONS, can_moderate: g.can_moderate },
25
+ })),
26
+ },
27
+ };
28
+ }
29
+
30
+ describe('canModerate', () => {
31
+ it('returns false for undefined authContext', () => {
32
+ expect(canModerate(undefined, 'group-1')).toBe(false);
33
+ });
34
+
35
+ it('returns false for null credentials', () => {
36
+ expect(canModerate({ accessToken: null, credentials: null }, 'group-1')).toBe(false);
37
+ });
38
+
39
+ it('returns false when user is not a member of the group', () => {
40
+ const auth = makeAuthContext([{ group_id: 'other-group', can_moderate: true }]);
41
+ expect(canModerate(auth, 'group-1')).toBe(false);
42
+ });
43
+
44
+ it('returns false when user is a member but not a moderator', () => {
45
+ const auth = makeAuthContext([{ group_id: 'group-1', can_moderate: false }]);
46
+ expect(canModerate(auth, 'group-1')).toBe(false);
47
+ });
48
+
49
+ it('returns true when user has can_moderate on the group', () => {
50
+ const auth = makeAuthContext([{ group_id: 'group-1', can_moderate: true }]);
51
+ expect(canModerate(auth, 'group-1')).toBe(true);
52
+ });
53
+ });
54
+
55
+ describe('canModerateAny', () => {
56
+ it('returns false for undefined authContext', () => {
57
+ expect(canModerateAny(undefined)).toBe(false);
58
+ });
59
+
60
+ it('returns false when no group has can_moderate', () => {
61
+ const auth = makeAuthContext([
62
+ { group_id: 'g1', can_moderate: false },
63
+ { group_id: 'g2', can_moderate: false },
64
+ ]);
65
+ expect(canModerateAny(auth)).toBe(false);
66
+ });
67
+
68
+ it('returns true when any group has can_moderate', () => {
69
+ const auth = makeAuthContext([
70
+ { group_id: 'g1', can_moderate: false },
71
+ { group_id: 'g2', can_moderate: true },
72
+ ]);
73
+ expect(canModerateAny(auth)).toBe(true);
74
+ });
75
+ });
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Auth helper utilities for permission checking.
3
+ */
4
+
5
+ import type { AuthContext } from '../types/auth.js';
6
+
7
+ /**
8
+ * Check if the user has can_moderate permission for a specific group.
9
+ */
10
+ export function canModerate(authContext: AuthContext | undefined, groupId: string): boolean {
11
+ if (!authContext?.credentials) return false;
12
+ const membership = authContext.credentials.group_memberships
13
+ .find(m => m.group_id === groupId);
14
+ return membership?.permissions.can_moderate ?? false;
15
+ }
16
+
17
+ /**
18
+ * Check if the user has can_moderate permission for ANY group.
19
+ * Useful for space-level moderation where there's no specific group context.
20
+ */
21
+ export function canModerateAny(authContext: AuthContext | undefined): boolean {
22
+ if (!authContext?.credentials) return false;
23
+ return authContext.credentials.group_memberships
24
+ .some(m => m.permissions.can_moderate);
25
+ }