Context
PR #156 introduced the multi-graph foundation (schema isolation, RBAC, session resolver, sync fan-out, MCP graph scoping, frontend graph picker). This issue tracks remaining work needed before the feature is production-ready.
Backend: Graph-Scoped Endpoints
The frontend now routes all graph-scoped data calls through graphRequest() which prefixes /graphs/{slug}/... for non-default graphs. However, only /graphs/{slug}/nodes has a backend implementation (graph_nodes.py). All other graph-scoped resource endpoints need to be added:
Strategy: Refactor existing endpoint handlers to accept session as a parameter, then create thin graph-scoped wrappers that use GraphContext for session routing. Same handler logic, different session source.
Backend: Worker Graph-ID Propagation
Workers now resolve graph_id to per-graph session factories, but the API dispatch points don't include graph_id in the workflow input yet. When dispatching from graph-scoped endpoints:
MCP: Per-User Graph Membership Check
MCP tools check OAuth token graph:{slug} scopes but don't verify the user's GraphMember membership. A user with an unrestricted token (no graph scopes) can access any graph by slug. Needs:
Frontend: Graph Picker UX
Operational
Architecture Notes
graphRequest() is wired but will 404 on non-default graphs until backend endpoints are added — this is expected and documented
GraphAwareMixin is on all Hatchet input models — workers resolve sessions but API dispatch needs to populate graph_id
- Schema-mode graph pool sizes are configurable via
graph_pool_size / graph_max_overflow settings
- Sync fan-out (
sync_dispatch_wf + sync_graph_wf) prevents cross-graph starvation
🤖 Generated with Claude Code
Context
PR #156 introduced the multi-graph foundation (schema isolation, RBAC, session resolver, sync fan-out, MCP graph scoping, frontend graph picker). This issue tracks remaining work needed before the feature is production-ready.
Backend: Graph-Scoped Endpoints
The frontend now routes all graph-scoped data calls through
graphRequest()which prefixes/graphs/{slug}/...for non-default graphs. However, only/graphs/{slug}/nodeshas a backend implementation (graph_nodes.py). All other graph-scoped resource endpoints need to be added:/graphs/{slug}/nodes/{id}/dimensions/graphs/{slug}/nodes/{id}/facts/graphs/{slug}/nodes/{id}/edges/graphs/{slug}/nodes/{id}/history/graphs/{slug}/nodes/{id}/convergence/graphs/{slug}/facts/graphs/{slug}/edges/graphs/{slug}/sources/graphs/{slug}/seeds/graphs/{slug}/edge-candidates/graphs/{slug}/conversations/graphs/{slug}/syntheses/graphs/{slug}/researchStrategy: Refactor existing endpoint handlers to accept session as a parameter, then create thin graph-scoped wrappers that use
GraphContextfor session routing. Same handler logic, different session source.Backend: Worker Graph-ID Propagation
Workers now resolve
graph_idto per-graph session factories, but the API dispatch points don't includegraph_idin the workflow input yet. When dispatching from graph-scoped endpoints:graph_idin workflow input dict for all dispatch calls from graph-scoped API endpointsgraph_id(e.g.,bottom_up_wf→node_pipeline_wf)MCP: Per-User Graph Membership Check
MCP tools check OAuth token
graph:{slug}scopes but don't verify the user'sGraphMembermembership. A user with an unrestricted token (no graph scopes) can access any graph by slug. Needs:GraphMemberrole for non-default graphs in_get_graph_factoryFrontend: Graph Picker UX
Operational
provisioningstatus (crash recovery)list_graphsnode_count — currently returns 0 for all graphs (requires cross-schema count query per graph)Architecture Notes
graphRequest()is wired but will 404 on non-default graphs until backend endpoints are added — this is expected and documentedGraphAwareMixinis on all Hatchet input models — workers resolve sessions but API dispatch needs to populategraph_idgraph_pool_size/graph_max_overflowsettingssync_dispatch_wf+sync_graph_wf) prevents cross-graph starvation🤖 Generated with Claude Code