NODEDC_TASKMANAGER_CODEXAPI/README.md

176 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# NODE.DC Tasker Codex API
Отдельный модуль NODE.DC для безопасного подключения локальных Codex/AI-агентов к Tasker / Operational Core.
Модуль не является частью Plane fork и не должен становиться backend-расширением Tasker. Его роль — agent gateway: выдача ограниченных agent credentials, проверка прав, MCP/REST-контракт для внешних агентов, аудит и маршрутизация разрешённых операций в Tasker через узкий internal adapter.
## Documents
- [Architecture](docs/ARCHITECTURE.md)
- [UX flow](docs/UX_FLOW.md)
- [MCP tools contract](docs/MCP_TOOLS_CONTRACT.md)
- [Tasker API audit](docs/TASKER_API_AUDIT.md)
- [Threat model](docs/THREAT_MODEL.md)
- [Implementation plan](docs/IMPLEMENTATION_PLAN.md)
## Core rule
External Codex instances never receive Plane session cookies, raw Tasker API tokens, database access, or a generic HTTP proxy into Tasker.
All writes go through NODE.DC Agent Gateway, are scoped by agent grants, and are recorded as actions of a dedicated agent identity owned by a human platform user.
## Current implementation
- Fastify service with `/healthz`, `/readyz`, and capability metadata.
- Postgres migrations for agents, grants, token hashes, pairing codes, audit events, and idempotency keys.
- Internal REST endpoints for agent profile, grant, and token lifecycle.
- Lifecycle endpoints are protected by `NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN`; public agent traffic uses only issued agent tokens.
- Opaque agent tokens are generated once and stored only as SHA-256 hashes.
- Authenticated agent-session endpoint returns effective grants/scopes for future MCP calls.
- Agent setup endpoint returns an MCP config template and AGENTS.md instruction pack without echoing the raw token.
- Product tool endpoints validate agent token, scopes, and project grants before calling Tasker internal adapter.
- MCP JSON-RPC endpoint `/mcp` exposes the same tool runtime as REST product endpoints.
- Write tools require idempotency keys and replay successful duplicate requests without creating duplicate Tasker writes.
- Agent Gateway writes audit events for executed, replayed, and failed write-tool calls.
- Tool execution calls the real Tasker internal adapter; no fake Tasker storage exists in Gateway.
- Local real e2e smoke verifies Gateway -> MCP -> Tasker runtime writes.
## Local development
Product-like Docker run:
```bash
cp .env.example .env
docker compose --env-file .env -f docker-compose.local.yml up -d --build
curl http://127.0.0.1:4100/readyz
```
The `agent-gateway` container waits for local Postgres, runs migrations on startup, and exposes the same `:4100` internal endpoint used by Tasker (`PLANE_NODEDC_AGENT_GATEWAY_URL=http://host.docker.internal:4100` in local development). `HOST_BIND` and `HOST_PORT` control the host-side port for reverse proxy deployments; Synology should use `docker-compose.synology.yml` with `172.22.0.222:18190:4100` because `18090` is reserved for Tasker. The user-facing setup packet uses `NODEDC_AGENT_GATEWAY_PUBLIC_URL`; product defaults point to `https://ops-agents.nodedc.ru`, not localhost.
Synology deployment notes live in `docs/SYNOLOGY_DEPLOY.md`.
Direct Node.js development:
```bash
cp .env.example .env
docker compose --env-file .env -f docker-compose.local.yml up -d postgres
npm install
npm run migrate
npm run dev
```
Useful checks:
```bash
npm run check
npm run build
npm run smoke:mcp
npm run smoke:gateway
curl http://127.0.0.1:4100/readyz
curl http://127.0.0.1:4100/api/v1/meta/capabilities
```
Create a local test agent:
```bash
curl -X POST http://127.0.0.1:4100/api/v1/agents \
-H "Authorization: Bearer $NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"owner_user_id":"local-user","owner_email":"local@example.test","display_name":"Local Codex"}'
```
Create a token and inspect effective agent session:
```bash
TOKEN=$(curl -sS -X POST http://127.0.0.1:4100/api/v1/agents/<agent-id>/tokens \
-H "Authorization: Bearer $NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"Local Codex token"}' | jq -r .token)
curl http://127.0.0.1:4100/api/v1/agent-session \
-H "Authorization: Bearer $TOKEN"
```
Tasker UI should use the owner-scoped internal lifecycle API through its backend proxy:
```bash
curl http://127.0.0.1:4100/api/internal/v1/owners/<owner-user-id>/agents \
-H "Authorization: Bearer $NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN"
```
The internal API verifies the owner path against the stored agent owner before returning agent detail, grants, tokens, setup packets, or revoke responses.
Generate a local Codex setup packet:
```bash
curl http://127.0.0.1:4100/api/v1/agent-session/setup \
-H "Authorization: Bearer $TOKEN" | jq -r .setup.agents_md
```
The setup packet includes:
- MCP endpoint and header template with `<agent-token>` placeholder;
- available tools for the current grants;
- AGENTS.md rules for Tasker card writing, no-delete boundary, and required `idempotency_key`;
- no raw token echo.
Call MCP tools through the JSON-RPC endpoint:
```bash
curl -sS http://127.0.0.1:4100/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-06-18' \
-H "Authorization: Bearer $TOKEN" \
-d '{"jsonrpc":"2.0","id":"tools","method":"tools/list","params":{}}' | jq
```
## Local testing strategy
No fake Tasker storage is embedded into Agent Gateway.
Local verification is split into product layers:
1. `npm run smoke:mcp` verifies MCP initialize, tool listing, bearer token auth, scope checks, grant checks, idempotency requirement, and the Tasker boundary.
2. `npm run smoke:gateway` verifies the REST compatibility boundary and idempotency requirement over the same tool execution path.
3. `npm run smoke:e2e` verifies REST tool endpoints and idempotent replay against the real local Tasker runtime.
4. `npm run smoke:mcp:e2e` verifies MCP tool calls and idempotent replay against the real local Tasker runtime.
5. External-machine testing uses the same token and endpoint shape against staging HTTPS; no extra protocol or fake environment should be introduced.
Example real localhost MCP e2e:
```bash
TOKEN=$(python3 - <<'PY'
from pathlib import Path
for line in Path('/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/plane-app/plane.env').read_text().splitlines():
if line.startswith('NODEDC_INTERNAL_ACCESS_TOKEN=') or line.startswith('PLANE_NODEDC_ACCESS_TOKEN='):
value = line.split('=', 1)[1].strip().strip('"').strip("'")
if value:
print(value)
break
PY
)
DATABASE_URL='postgres://nodedc_agent_gateway:replace-with-local-postgres-password@localhost:54100/nodedc_agent_gateway' \
NODE_ENV=development \
LOG_LEVEL=silent \
NODEDC_TASKER_INTERNAL_URL='http://localhost:8090' \
NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN='replace-with-gateway-internal-token' \
NODEDC_INTERNAL_ACCESS_TOKEN="$TOKEN" \
SMOKE_WORKSPACE_SLUG='nodedc' \
SMOKE_PROJECT_ID='<project-id>' \
npm run smoke:mcp:e2e
```
Current Tasker internal adapter contract expected by Gateway:
- `POST /api/internal/nodedc/agent/projects/resolve`
- `GET /api/internal/nodedc/agent/projects/:projectId/context`
- `GET /api/internal/nodedc/agent/issues?project_id=...`
- `POST /api/internal/nodedc/agent/issues`
- `PATCH /api/internal/nodedc/agent/issues/:issueId`
- `POST /api/internal/nodedc/agent/issues/:issueId/move`
- `POST /api/internal/nodedc/agent/issues/:issueId/comments`
- `PUT /api/internal/nodedc/agent/issues/:issueId/labels`
- `PUT /api/internal/nodedc/agent/issues/:issueId/assignees`