feat(integration): prepaid billing, engine UI, credits console, direct tasks, v2 final

- Prepaid credit system: org wallet, debit on usage, chat gate, admin credit console
- Engine UI: /manager, /tasks, /tasks/[id], /workforce, /dashboard, /traces pages
- Direct task creation (HTTP POST /tasks, MCP tasks_create) at pending_manager_review
- Pause/resume/cancel/answer actions in engine API and UI
- Employee cap (7 per org default), review pipeline guard (active reviewer required)
- Scheduler: wide window prevents org starvation; archived employees excluded from cap
- Tenant isolation: project-id cross-org 404, engine never uses another tenant's sandbox
- Order route fix: manager built with pipeline states + employee profiles
- Contract extension: ModelGrantPort.get_org_policy with DefaultOrgPolicy
- Engine event types in @agy/contracts (task.step, task.gate, run.log, run.tool, team.changed)
- api-engine.ts typed client; api-credit.ts client
- Alembic migration c4d5e6f7a8b9: prepaid credit + engine UI tables
- 859 tests passed, 1 skipped; ruff/mypy/tsc/eslint/vitest all green

Refs: PLAN-v2.md §9 (T1–T43), todo-v2-final.md
This commit is contained in:
mjalmoudy94
2026-10-14 23:19:05 +03:30
parent fef5a9deab
commit d532929189
117 changed files with 13119 additions and 640 deletions
+10 -5
View File
@@ -22,7 +22,7 @@ and nothing reaches production without a human click.
| 1 | `DockerSandboxAdapter` (hardened workspace + demo containers), `process.py` (the single hardened subprocess runner), orphan reaping, infra hidden from non-owners |
| 2 | `LocalGitWorkspaceAdapter` — the platform's own git: per-project gitdir, worktrees per task, per-repo lock, hooks disabled, credentials only ever as a *path* |
| 3 | Live CI/CD: pipeline runs/steps/releases/runtimes, build containers, blue/green demo deploy, live batched logs, remote polling |
| 4 | Owner domain console: list/attach/detach/resync routes, custom FQDNs behind a setting, MCP gateway system route |
| 4 | Owner domain console: list/attach/detach/resync routes, custom FQDNs behind a setting, MCP gateway as a read-only suggestion (`GET /suggested`; the `mcp` label is protected, so it cannot be attached) |
| 5 | Production deploy: `asyncssh` + `aioftp` adapters with host-key TOFU, atomic symlink switch, FTP backup-first, `production_deploys` ledger |
| 6 | The Application page (four tabs + live build console + production panel), `/admin/domains`, `/admin/sandbox`, `/projects* → /app` redirect, typed client + contracts |
@@ -98,7 +98,7 @@ All paths are under `/api`.
| Method | Path | Notes |
|---|---|---|
| GET | `` | every route, app routes and system routes |
| GET | `` | every attached app route. The MCP gateway host is a read-only suggestion (`/suggested`), not a route the owner can enable: the label `mcp` is protected |
| POST | `` | attach a host (label, or a custom FQDN when the setting is on) |
| DELETE | `/{domain_id}` | detach, host typed back as confirmation |
| POST | `/sync` | idempotent re-sync from the database |
@@ -125,9 +125,12 @@ All four endpoints (ports, domains create/list/delete) became platform-owner onl
## 5. Tables (all in `models_delivery.py`)
`pipeline_runs`, `pipeline_steps`, `releases`, `app_runtimes`,
`production_deploys`, `system_routes`. Migration
`production_deploys`. Migration
`a3b4c5d6e7f3_delivery_infra` (`down_revision = "a0f0e1d2c3b4"`).
The MCP gateway has no table: `GET /api/admin/domains/suggested` computes its
suggestion from settings.
---
## 6. Manual QA script
@@ -157,8 +160,8 @@ Run against a real docker + caddy host with
8. **Production, FTP**: the same against a `pure-ftpd` container; expect a
`ftp-backup-<ts>.tar.gz` and, on rollback, that archive re-uploaded.
9. **Domains**: as the owner attach a second label; re-sync twice and check the
second call reports `up_to_date: true` with no Caddy reload. Enable the MCP
system route; `mcp.<root>` must answer through the gateway port.
second call reports `up_to_date: true` with no Caddy reload. Check that
`GET /api/admin/domains/suggested` shows `mcp.<root>` as a suggestion (`enabled=false`).
10. **SSRF**: attempt a production deploy to `127.0.0.1`, `10.0.0.1` and
`169.254.169.254`. All three must be refused before any connection.
11. **Tenant isolation**: a member of org B gets 404 on every org-A delivery and
@@ -213,3 +216,5 @@ Run against a real docker + caddy host with
(D6), but it also means Agent 2's engine must go through `RepoWorkspacePort`
for all of it, and a git failure surfaces to the customer as a Persian message
rather than a git exit code.
- **No sandbox restart.** `/admin/sandbox` lists and stops containers; there is
no restart action (TODO 6.3 open).