mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-21 07:41:28 +02:00
Repo-wide sweep of every user-facing string: frontend components, routes, config and stores; API details and route docs; shared definitions and models; stage config help; report prose; MCP, toolbox, interest and connector text; notification and worker messages. Descriptions that explained, reassured, justified or restated their title are deleted. Confirm dialogs name what is removed and stop. Failed actions read "<Noun> not <verbed>", successes "<Noun> <verbed>". No reader address, no product-as-subject, no em-dashes or parentheticals in prose. Mirrors updated on both sides: EPSS band help, compare refusal reasons, interest labels. Four tests asserting on old wording follow the new text. The rules are condensed into CLAUDE.md under Writing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SK5o8xR96cbSnAfjYSTPSe
51 lines
1.5 KiB
Python
51 lines
1.5 KiB
Python
"""Everything a tool is given: a session, who is asking, and what they may do."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from dataclasses import dataclass, field
|
|
from typing import TYPE_CHECKING
|
|
|
|
from mcp.capabilities import Capability
|
|
from mcp.errors import CapabilityError, ScopeError
|
|
|
|
if TYPE_CHECKING:
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TokenIdentity:
|
|
id: uuid.UUID
|
|
name: str
|
|
project_id: uuid.UUID | None
|
|
capabilities: frozenset[str]
|
|
issued_by: uuid.UUID | None = None
|
|
|
|
def allows(self, capability: str) -> bool:
|
|
return capability in self.capabilities
|
|
|
|
|
|
@dataclass
|
|
class ToolContext:
|
|
session: AsyncSession
|
|
token: TokenIdentity
|
|
ui_base_url: str
|
|
client: str = "unknown"
|
|
extras: dict = field(default_factory=dict)
|
|
|
|
def require(self, capability: str | Capability) -> None:
|
|
value = str(capability)
|
|
if not self.token.allows(value):
|
|
msg = f"This token lacks the {value} capability."
|
|
raise CapabilityError(msg)
|
|
|
|
def scoped_projects(self) -> list[uuid.UUID] | None:
|
|
"""None means every project."""
|
|
return None if self.token.project_id is None else [self.token.project_id]
|
|
|
|
def check_project(self, project_id: uuid.UUID) -> uuid.UUID:
|
|
if self.token.project_id is not None and project_id != self.token.project_id:
|
|
msg = "The project is outside this token's scope."
|
|
raise ScopeError(msg)
|
|
return project_id
|