7.78.0 — MCP : périmètre du propriétaire du jeton
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s

list_workspaces/get_workspace filtrés par user_workspace_ids ;
collections filtrées par workspace effectif ; hors périmètre =
introuvable, lectures et écritures. Test deux comptes.
This commit is contained in:
Spark
2026-10-22 09:22:19 -04:00
parent f6782ee5b3
commit 133156580c
4 changed files with 101 additions and 18 deletions
+34
View File
@@ -195,6 +195,40 @@ def test_mcp_client_bearer_sans_session_ni_csrf(client, jeton, donnees):
assert r.status_code == 401, r.text
def test_mcp_perimetre_du_jeton(client, jeton, donnees):
"""Régression 7.78.0 (cas réel de Bruno) : list_workspaces rendait
les 52 workspaces de la base, tous comptes confondus. Chaque jeton
ne voit que les workspaces de son propriétaire (ou ceux dont il
est membre) et les collections rattachées à ce périmètre."""
autre = "fd_token_autre_compte"
with get_conn() as conn:
conn.execute("INSERT OR IGNORE INTO users (id, login) VALUES (2, 'autre')")
conn.execute(
"INSERT INTO api_tokens (user_id, name, token_hash, token_prefix, revoked) "
"VALUES (2, 'autre', ?, ?, 0)",
(hashlib.sha256(autre.encode()).hexdigest(), autre[:12]))
cur = conn.execute(
"INSERT INTO workspaces (name, owner_id) VALUES ('Espace de lautre', 2)")
wid_autre = cur.lastrowid
cur = conn.execute(
"INSERT INTO collections (name, description, icon, workspace_id) "
"VALUES ('Base de lautre', '', '📋', ?)", (wid_autre,))
base_autre = cur.lastrowid
conn.commit()
# Bruno (jeton principal) ne voit ni le workspace ni la base de l'autre.
noms = [w["name"] for w in _appel(client, jeton, 80, "list_workspaces")]
assert "Espace de lautre" not in noms
res = _appel(client, jeton, 81, "get_workspace", {"id": wid_autre})
assert "introuvable" in res["erreur"]
cols = [c["name"] for c in _appel(client, jeton, 82, "list_collections")]
assert "Base de lautre" not in cols and "Projet Alpha" in cols
res = _appel(client, jeton, 83, "get_collection", {"id": base_autre})
assert "introuvable" in res["erreur"]
# Et l'autre ne voit pas le workspace de Bruno, mais voit le sien.
noms2 = [w["name"] for w in _appel(client, autre, 84, "list_workspaces")]
assert noms2 == ["Espace de lautre"]
def test_mcp_info_get(client, jeton):
r = client.get("/mcp")
assert r.status_code == 200