feat(pat): enforce scopes and resource restrictions, deny by default

A central rule table maps each route and method to the scope a token needs;
a route that is not listed cannot be called with a token, and a test fails
when a registered route is left unclassified. Token management, admin, team
management, sign-in, device pairing and OAuth handshakes are never token
reachable, and a token never carries the admin role.

A token restricted to specific agents, sources, prompts, tools or workflows
is held to its allowlist: ids are checked wherever a route carries them,
listings are filtered, creation is refused, and routes whose rows cannot be
tied to the allowlist are closed. Agent import checks the resolved target.
This commit is contained in:
arc53-machine committed 2026-09-19 23:39:58 +01:00
1 parent 3a74aa23f0
commit 82ec6cba0e
10 files changed
+1114 -4

No files matched your search

+3 -1
View File
@@ -5,6 +5,7 @@ from flask import current_app, jsonify, make_response, request
from flask_restx import fields, Namespace, Resource
from docsgpt.api import api
from docsgpt.api.pat.rules import filter_listing
from docsgpt.api.user.team_sharing import team_access_for, visible_with_access
from docsgpt.storage.db.repositories.prompts import PromptsRepository
from docsgpt.prompts.composer import compose_preset, is_composed_preset
@@ -91,7 +92,8 @@ class GetPrompts(Resource):
except Exception as err:
current_app.logger.error(f"Error retrieving prompts: {err}", exc_info=True)
return make_response(jsonify({"success": False}), 400)
return make_response(jsonify(list_prompts), 200)
# Presets (default/creative/strict) have no row id and stay visible to a restricted token.
return make_response(jsonify(filter_listing(request, "prompts", list_prompts)), 200)
@prompts_ns.route("/get_single_prompt")