docs(platform): add policy configs, runbooks, ops scripts and platform documentation
Config policies (16 files): alert_routing, architecture_pressure, backlog, cost_weights, data_governance, incident_escalation, incident_intelligence, network_allowlist, nodes_registry, observability_sources, rbac_tools_matrix, release_gate, risk_attribution, risk_policy, slo_policy, tool_limits, tools_rollout Ops (22 files): Caddyfile, calendar compose, grafana voice dashboard, deployments/incidents logs, runbooks for alerts/audit/backlog/incidents/sofiia/voice, cron jobs, scripts (alert_triage, audit_cleanup, migrate_*, governance, schedule), task_registry, voice alerts/ha/latency/policy Docs (30+ files): HUMANIZED_STEPAN v2.7-v3 changelogs and runbooks, NODA1/NODA2 status and setup, audit index and traces, backlog, incident, supervisor, tools, voice, opencode, release, risk, aistalk, spacebot Made-with: Cursor
This commit is contained in:
265
docs/tools/repo_tool.md
Normal file
265
docs/tools/repo_tool.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# RepoTool - Read-only Repository Access
|
||||
|
||||
## Overview
|
||||
|
||||
RepoTool provides read-only access to the DAARION repository filesystem for agents (primarily Sofiia). It allows viewing code, configs, and searching through the codebase without any write or execute capabilities.
|
||||
|
||||
## Integration
|
||||
|
||||
### Tool Definition
|
||||
|
||||
RepoTool is registered in `services/router/tool_manager.py` under `TOOL_DEFINITIONS`:
|
||||
|
||||
```python
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "repo_tool",
|
||||
"description": "📂 Read-only доступ до файловї системи репозиторію...",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["tree", "read", "search", "metadata"]
|
||||
},
|
||||
"path": {"type": "string"},
|
||||
"start_line": {"type": "integer"},
|
||||
"end_line": {"type": "integer"},
|
||||
"depth": {"type": "integer"},
|
||||
"glob": {"type": "string"},
|
||||
"query": {"type": "string"},
|
||||
"limit": {"type": "integer"},
|
||||
"max_bytes": {"type": "integer"}
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### RBAC Configuration
|
||||
|
||||
Added to `services/router/agent_tools_config.py` in `FULL_STANDARD_STACK` - available to all agents.
|
||||
|
||||
## Actions
|
||||
|
||||
### 1. tree - Directory Structure
|
||||
|
||||
Show directory tree starting from a path.
|
||||
|
||||
**Parameters:**
|
||||
- `path`: Starting path (default: ".")
|
||||
- `depth`: Maximum depth (default: 3, max: 10)
|
||||
- `glob`: Optional glob pattern to filter files
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"action": "tree",
|
||||
"path": "services",
|
||||
"depth": 2
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"result": {
|
||||
"tree": {
|
||||
"router": {"main.py": "[file]", "tool_manager.py": "[file]"},
|
||||
"gateway": {"main.py": "[file]"}
|
||||
},
|
||||
"path": "services"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. read - File Content
|
||||
|
||||
Read file contents with optional line limits.
|
||||
|
||||
**Parameters:**
|
||||
- `path`: File path (required)
|
||||
- `start_line`: Starting line (default: 1)
|
||||
- `end_line`: Ending line (optional)
|
||||
- `max_bytes`: Max bytes to read (default: 200KB, max: 1MB)
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"action": "read",
|
||||
"path": "services/router/main.py",
|
||||
"start_line": 1,
|
||||
"end_line": 50
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"result": {
|
||||
"path": "services/router/main.py",
|
||||
"content": "import asyncio\n...",
|
||||
"lines": 50,
|
||||
"start_line": 1,
|
||||
"end_line": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. search - Text Search
|
||||
|
||||
Search for text in files using grep.
|
||||
|
||||
**Parameters:**
|
||||
- `query`: Search query (required)
|
||||
- `path`: Starting path (default: ".")
|
||||
- `glob`: File pattern (e.g., "**/*.py")
|
||||
- `limit`: Max results (default: 50, max: 200)
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"action": "search",
|
||||
"query": "async def",
|
||||
"path": "services",
|
||||
"glob": "**/*.py",
|
||||
"limit": 20
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"result": {
|
||||
"query": "async def",
|
||||
"path": "services",
|
||||
"matches": [
|
||||
{"file": "router/main.py", "line": "45", "content": "async def handle_request"},
|
||||
{"file": "router/main.py", "line": "102", "content": "async def process_message"}
|
||||
],
|
||||
"count": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. metadata - Git Information
|
||||
|
||||
Get git repository metadata.
|
||||
|
||||
**Parameters:**
|
||||
- `path`: Path within repo (optional)
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"action": "metadata",
|
||||
"path": "."
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"result": {
|
||||
"path": ".",
|
||||
"repo_root": "/path/to/repo",
|
||||
"commit": "abc123def456",
|
||||
"branch": "main",
|
||||
"dirty": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Features
|
||||
|
||||
### Path Traversal Protection
|
||||
- Blocks `..` in paths
|
||||
- Rejects absolute paths outside repo root
|
||||
- Validates resolved path stays within repo root
|
||||
|
||||
### Symlink Escape Prevention
|
||||
- Uses `os.path.realpath()` to resolve symlinks
|
||||
- Ensures resolved path is still within repo root
|
||||
- Blocks access through symlinks to external locations
|
||||
|
||||
### Secret Masking
|
||||
Files and content containing secrets are automatically masked:
|
||||
|
||||
**Masked file patterns:**
|
||||
- `.env`, `.env.local`, `.env.production`
|
||||
- `*secrets*`, `*credentials*`, `*keys*`, `*tokens*`, `*passwords*`
|
||||
|
||||
**Masked content patterns:**
|
||||
```
|
||||
api_key = xxx → api_key = ***
|
||||
token = xxx → token = ***
|
||||
password = xxx → password = ***
|
||||
SECRET_KEY=xxx → SECRET_KEY=***
|
||||
Bearer xxx → Bearer ***
|
||||
-----BEGIN PRIVATE KEY----- → [MASKED]
|
||||
```
|
||||
|
||||
### Limits
|
||||
| Limit | Default | Max |
|
||||
|-------|---------|-----|
|
||||
| Tree depth | 3 | 10 |
|
||||
| Search results | 50 | 200 |
|
||||
| File size | 200KB | 1MB |
|
||||
| Lines per read | 1000 | - |
|
||||
| Search timeout | - | 10s |
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Sofiia Commands
|
||||
|
||||
```
|
||||
"Покажи структуру папки services"
|
||||
"Прочитай файл services/router/main.py перші 50 рядків"
|
||||
"Знайди всі файли з 'async def' в папці services"
|
||||
"Який останній коміт?"
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"result": null,
|
||||
"error": "Path traversal detected. Access denied."
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"result": null,
|
||||
"error": "File too large: 500000 bytes (max: 204800)"
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run tests:
|
||||
```bash
|
||||
cd /path/to/repo
|
||||
pytest tools/repo_tool/tests/test_repo_tool.py -v
|
||||
```
|
||||
|
||||
Test coverage:
|
||||
- Path traversal blocked
|
||||
- Symlink escape blocked
|
||||
- Absolute path blocked
|
||||
- Tree action works
|
||||
- Read action works with line limits
|
||||
- Search finds content
|
||||
- Metadata returns git info
|
||||
- Secret files (.env) masked
|
||||
- Inline secrets masked
|
||||
- Size limits enforced
|
||||
- Depth limits enforced
|
||||
Reference in New Issue
Block a user