andrewmusselman opened a new issue, #20:
URL: https://github.com/apache/tooling-gofannon/issues/20
### Summary
List endpoints for agents, demos, and deployments return all records in the
database without filtering by user or workspace. Phase B-1 (the workspace
membership model) is implemented; Phase B-3 (filtering resources by workspace)
is not. The codebase explicitly calls this out in `models/workspace.py`:
workspace filtering on those resources is introduced in B-3; B-1 only
establishes the membership model.
### Details
**Symptom:**
- Site admins observe each other's agents, demos, and deployments —
initially appeared to be admin-specific leakage but applies to all
authenticated users.
- A second user cannot see another user's run progress logs (a different gap
— see ISSUE-003).
- No "publish" / "share" concept gates this visibility today.
**Root cause:**
1. `routes.py:list_agents` (line 504) issues `db.list_all("agents")` with
zero filtering.
2. `routes.py:list_demo_apps` (line 942) and
`routes.py:list_deployments_route` (line 652) do the same.
3. The Agent model has no `user_id`, `workspace_id`, `created_by`,
`published`, or `visibility` field — nothing to filter on even if filtering
were added.
4. `routes.py:get_agent` (line 517) looks up any agent by id with no
membership check; same for PUT/DELETE.
5. `routes.py:list_data_store_namespaces` (line 1023) does filter by
`userId`, demonstrating the partial-scoping inconsistency.
Site admin status (`session.is_site_admin`) is not the issue — list
endpoints don't check that flag at all, so admins and non-admins hit the same
unfiltered query.
**Impact:**
- Hosted multi-tenant launch is unsafe with this state.
- No isolation between users sharing a deployment.
- Agent IDs are guessable (UUIDs in URLs), and any authenticated user can
read/write/delete any agent.
### Remediation
1. **Schema.** Add `workspace_id` and `created_by` to Agent, Demo,
DeployedApi models. Backfill existing rows into a `legacy:pre-b3` workspace;
operators migrate them manually.
2. **Writes carry workspace.** Create endpoints take the active workspace
from the request (header or query param) and validate the session has
membership.
3. **Reads filter by workspace.** Every list endpoint becomes
`db.find("agents", {"workspace_id": {"$in": session_workspace_ids}})`. Single
helper to enforce the pattern.
4. **Authorize by-id endpoints.** `get/update/delete` for each resource must
check the resource's workspace_id is one the session is a member of.
`require_workspace_member(resource, session, role)` helper.
5. **Site admin escape hatch (deliberate, opt-in).** `?include_all=true`
query parameter on list endpoints, or a separate `/admin/*` route — never
silent.
6. **Frontend.** Workspace switcher, "this agent belongs to <workspace>"
badge, share-into-workspace affordance.
### Acceptance Criteria
- [ ] Fixed: `Agent`, `Demo`, `DeployedApi` models include `workspace_id`
and `created_by` fields
- [ ] Fixed: existing DB rows backfilled to `legacy:pre-b3` workspace
- [ ] Fixed: all list endpoints filter by `workspace_id IN
(session.workspace_ids)`
- [ ] Fixed: get/update/delete endpoints check workspace membership
- [ ] Fixed: site-admin global view requires explicit `?include_all=true`
- [ ] Fixed: data-store namespace filtering converted from per-user to
per-workspace
- [ ] Test added: User A cannot list, read, update, or delete agents owned
by User B
- [ ] Test added: Site admin without `include_all` flag sees only their
workspaces
- [ ] Test added: Workspace member can access shared workspace resources
- [ ] Frontend: workspace selection UI exists in agent/demo creation flows
- [ ] Documentation: migration guide for existing deployments
### References
- File: `webapp/packages/api/user-service/routes.py:504,517,652,942,1023`
- File: `webapp/packages/api/user-service/models/agent.py`
- File: `webapp/packages/api/user-service/models/workspace.py` (existing
membership model — see docstring)
- Tracker: FIXES.md item #1
### Priority
**Critical** - Pre-launch blocker for hosted multi-tenant deployment.
Membership model already exists; only the filtering and authorization layers
are missing. Substantial design work but no architectural unknowns.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]