feat: add created_by and last_updated_by user tracking to Entity#602
feat: add created_by and last_updated_by user tracking to Entity#602
Conversation
Track which cloud user created and last modified each entity. This enables
"last edited by {name}" display in team workspaces.
- Add created_by/last_updated_by columns to Entity model (nullable, null for local/CLI)
- Add fields to EntityResponseV2 Pydantic schema
- Add get_user_id callable to EntityService (default returns None)
- Set tracking fields in fast_write_entity, fast_edit_entity, create_entity, update_entity
- Preserve created_by on updates, only update last_updated_by
- Add alembic migration k4e5f6g7h8i9 (idempotent, supports both SQLite and Postgres)
- Add unit tests for all entity service write paths
- Add API test verifying fields appear in EntityResponseV2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a81b7a4329
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| self._project_permalink: Optional[str] = None | ||
| # Callable that returns the current user ID (cloud user_profile_id UUID as string). | ||
| # Default returns None for local/CLI usage. Cloud overrides this to read from UserContext. | ||
| self.get_user_id: Callable[[], Optional[str]] = lambda: None |
There was a problem hiding this comment.
Inject user ID provider into EntityService
This change introduces created_by/last_updated_by writes, but get_user_id is initialized to lambda: None and there is no production wiring in this commit to override it, so all write paths keep storing NULL for both fields. In practice, cloud requests won’t record attribution even though the schema/migration now expose these columns, which defeats the feature and silently loses audit data.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
This is intentional — basic-memory is the open-source library and doesn't have a user concept itself. The get_user_id callable is a hook designed to be injected by the host application.
The production wiring lives in basic-memory-cloud's cloud_deps.py, which overrides all three entity service factories to inject _get_cloud_user_id (reads from UserContext contextvar set during ASGI proxy/MCP transport calls):
https://github.com/basicmachines-co/basic-memory-cloud/pull/468
So the flow is:
- basic-memory (this PR): adds
get_user_idhook with safelambda: Nonedefault - basic-memory-cloud (PR Track: FastMCP 2.14.x outputSchema incompatibility with Claude Desktop #468): overrides entity services via
dependency_overridesto inject the cloud-specific user resolution
NULL is correct for local CLI usage (no users). Cloud writes will have attribution once both PRs land.
Summary
created_byandlast_updated_bycolumns to the Entity model for tracking which cloud user created and last modified each entityEntityResponseV2Pydantic schema so they appear in API responsesget_user_idcallable toEntityService(default returnsNonefor local/CLI; cloud overrides to read fromUserContext)fast_write_entity,fast_edit_entity,create_entity,update_entitycreated_byon updates — onlylast_updated_bychangesk4e5f6g7h8i9(idempotent, supports both SQLite and Postgres)Test plan
created_byandlast_updated_byfields appear inEntityResponseV2(null for local/CLI)🤖 Generated with Claude Code