feat(agent-connect): per-user API tokens + Team-gated /api/remember#11
Merged
Conversation
Team members connect agents to a hosted Engraphis instance and store memories
in the cloud v2 store instead of running locally.
- auth: per-user API tokens (api_tokens table) — SHA-256 hashed at rest, raw
token returned once; resolve rejects revoked + disabled-owner tokens.
- v2_team: POST /api/auth/token, GET /api/auth/tokens, DELETE /api/auth/token/{id},
GET /api/auth/connect-info (verify token + discover API base/snippet).
- dashboard_app._auth_gate: accept a per-user bearer token exactly like a cookie
session (bound to the member for role + personal-folder authz); try bearer then
cookie. Instance ENGRAPHIS_API_TOKEN bypass unchanged.
- v2_api: POST /api/remember gated by _paid('team') (402 without a Team license),
params mirroring the local engraphis_remember MCP tool; writes hit the same v2
store the dashboard reads.
- docs/AGENT_CONNECT.md; CHANGELOG [Unreleased].
- tests/test_agent_connect.py: 7 tests (token lifecycle, bearer write+recall,
402 without Team license, 401 without auth, disabled-user token rejected,
instance-token bypass). Suite: 701 passed, 3 skipped.
MCP-over-HTTP at /mcp is deferred (needs mcp_server service-injection to avoid a
second SQLite writer); agents use the HTTP API for now.
Owner
Author
Council Gate Verdict — APPROVE_WITH_NITSRisk level: high | Agreement: 0.746 | Council session: Per-model scores (rubric: correctness / safety / style / tests / complexity)
Engraphis referenceCouncil verdict persisted as
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Team members connect their agents to a hosted Engraphis instance and store memories in the cloud v2 store instead of running Engraphis locally. A Team license (the instance's) is required to write — a free/lapsed instance returns
402.This is the Phase 1 enabler from the team-hosting plan: the admin deploys one Railway instance (their account, their cost), activates a Team key, invites members; members sign in at
https://team.engraphis.com/, mint a bearer token, and point their agent at/api/remember. No local install for teammates.Changes
inspector/auth.py):api_tokenstable +create/resolve/list/revoke_api_token. Tokens are SHA-256 hashed at rest (raw token shown once);resolverejects revoked + disabled-owner tokens.routes/v2_team.py:POST /api/auth/token,GET /api/auth/tokens,DELETE /api/auth/token/{id},GET /api/auth/connect-info(verify a token + discover the API base/snippet).dashboard_app._auth_gate: accepts a per-user bearer token exactly like a cookie session (try bearer, then cookie), bound to the member for role + personal-folder authz. InstanceENGRAPHIS_API_TOKENbypass unchanged.routes/v2_api.py:POST /api/remembergated by_paid('team')(402 without a Team license); params mirror the localengraphis_rememberMCP tool; writes hit the same v2 store the dashboard reads (no agent/UI split).docs/AGENT_CONNECT.md+ CHANGELOG[Unreleased].Tests
tests/test_agent_connect.py— 7 tests: token lifecycle + connect-info, bearer write + recall, 402 without Team license, 401 without auth, disabled-user token rejected, instance-token bypass still works. Full suite: 701 passed, 3 skipped, 0 failed. Ruff clean.How 'they need a Team license to connect' works
The Team license is the instance's (admin activates one key; the relay enforces the seat cap server-side). Members present a seat (account) + token, never a license. The
402on/api/rememberfires only when the instance has no active Team key — i.e. a free/lapsed instance can't host team agents. Login is never license-gated (so a lapsed key never locks the UI).Deferred (follow-up PR)
MCP-over-HTTP at
/mcpis intentionally NOT in this PR: mounting the MCP server as-is would spin up a second writer to the same SQLite (WAL lock contention — the exact issuemcp_server_http.pywas written to avoid). It needs a service-injection refactor ofmcp_server.pyso it shares the dashboard'sMemoryService, plus an MCP-client integration test. Agents use the HTTP API in the meantime.Not in this PR
static/index.html).