feat(paperclip): add user-scoped memory isolation for GDPR compliance#1561
feat(paperclip): add user-scoped memory isolation for GDPR compliance#1561amirhmoradi wants to merge 8 commits into
Conversation
- Add userId parameter to BankContext for per-user memory isolation - Extend bankGranularity to support 'user' option for isolating memories by user - Add resolveUserIdFromActiveIssue() to extract user email from active issue - Add 'issues.read' capability to permissions for accessing active issue data - Update all bank ID derivations to include user ID when granularity includes 'user' - Update manifest description to mention GDPR compliance when user option is enabled This allows agents to maintain user-scoped memory in multi-user scenarios, ensuring that personal/scoped conversations don't leak between users.
feat(paperclip): add user-scoped memory isolation
|
Thanks @amirhmoradi, direction is right, per-user isolation in paperclip is a real gap worth fixing. but i pulled the branch and npm run typecheck fails with 4 errors: ctx.issues.getActive() doesn't exist in @paperclipai/plugin-sdk. I checked the pinned ^2026.403.0, the latest stable 2026.428.0, and the latest canary 2026.511.0-canary.8. |
…ve() method The getActive() method does not exist in the Paperclip plugin SDK. Instead, use ctx.issues.list() to retrieve the agent's issues, then extract the user email from the first (most active) issue's originId field. This fixes the TypeScript compilation errors reported in the PR review.
The previous fix still had the wrong type signature. The actual SDK
PluginIssuesClient.list() requires a {companyId, ...} input object.
Changes:
- Import PluginContext type from @paperclipai/plugin-sdk
- resolveUserIdFromActiveIssue now takes (ctx: PluginContext, companyId, agentId, config)
- Calls ctx.issues.list({ companyId, assigneeAgentId: agentId, status: 'in_progress', limit: 1 })
to find the agent's currently active issue
- All 4 call sites updated to pass companyId and agentId from their respective contexts
Verified: npm run typecheck passes with zero errors.
Feat/user scoped memory
|
thanks for updating. one quick check: when an agent has more than one in-progress issue, this picks an arbitrary one (whatever |
|
@amirhmoradi thanks for the original work here — per-user isolation in paperclip is a real feature we wanted, and your PR is what kicked it off. closing this one because it's picked up merge conflicts and the design question about multi-issue ordering (my comment from may 12) was never resolved. we've taken the concept and landed it in #1761 with a different approach: instead of you're credited in both the commit and the PR description. appreciate the contribution — if you spot anything off in #1761, feel free to comment there. |
Thanks a lot for your message and the push towards a better implementation. 🙏 |
…1761) * feat(paperclip): add per-user memory isolation via bankGranularity Add 'user' as a bankGranularity option so each user gets their own isolated memory bank. User identity is extracted from the specific issue being worked on (via originId email or creatorEmail), not from an arbitrary issue list query. - bank.ts: add userId to BankContext, extractUserFromIssue() helper - worker.ts: pass userId through all 4 bank-derivation sites, cache userId in plugin state so tool calls derive the same bank ID - manifest.ts: add 'user' to bankGranularity enum - tests: 6 new tests covering derivation, extraction, and integration Inspired by #1561 — thanks @amirhmoradi for the original concept and initial implementation. * feat(paperclip): add bankId/dynamicBankId for static shared banks Add bankId and dynamicBankId config fields matching the pattern used by openclaw, claude-code, and opencode. When bankId is set and dynamicBankId is not true, all agents share the same bank — useful for multi-agent cohorts that need collaborative memory. - bank.ts: static override check before dynamic derivation - manifest.ts: add dynamicBankId (boolean) and bankId (string) fields - worker.ts: add fields to PluginConfig type - tests: 5 new tests (static override, trimming, whitespace fallthrough, dynamicBankId=true bypass, integration routing) Inspired by #1589 — thanks @SeBru1 for the original concept. Closes #1589. * test(paperclip): add edge-case tests for bank feature interactions 19 additional tests covering: - Feature interaction: static bankId vs user granularity precedence - Static bankId edge cases: special chars, tabs/newlines, empty string - Dynamic derivation edge cases: empty granularity, user-only, duplicates - extractUserFromIssue: null fields, empty strings, multiple emails * style(paperclip): fix lint formatting drift
This allows agents to maintain user-scoped memory in multi-user scenarios,
ensuring that personal/scoped conversations don't leak between users.