antpath 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -14
- package/dist/_shared/http.d.ts +6 -1
- package/dist/_shared/http.js +3 -4
- package/dist/_shared/operations.d.ts +13 -8
- package/dist/_shared/operations.js +17 -12
- package/dist/_shared/stable.d.ts +14 -0
- package/dist/_shared/stable.js +14 -0
- package/dist/_shared/submission.d.ts +15 -0
- package/dist/cli.mjs +46 -57
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +13 -6
- package/dist/client.js +17 -16
- package/dist/client.js.map +1 -1
- package/docs/credentials.md +1 -3
- package/docs/quickstart.md +4 -7
- package/docs/release.md +57 -12
- package/examples/mcp-static-bearer.ts +1 -3
- package/examples/quickstart.ts +1 -3
- package/package.json +2 -3
- package/references/architecture-decisions.md +0 -473
- package/references/implementation-plan.md +0 -452
- package/references/research-sources.md +0 -41
- package/references/testing-strategy.md +0 -29
package/docs/credentials.md
CHANGED
package/docs/quickstart.md
CHANGED
|
@@ -4,18 +4,17 @@ title: antpath quickstart
|
|
|
4
4
|
|
|
5
5
|
# Quickstart
|
|
6
6
|
|
|
7
|
-
1. Get an antpath
|
|
7
|
+
1. Get an antpath SDK API token (`ant_…`).
|
|
8
8
|
2. Define a secret-free Template in TypeScript (or JSON / a `.mjs` default export).
|
|
9
|
-
3. Create `AntpathClient
|
|
9
|
+
3. Create `AntpathClient` — the workspace is derived server-side from the token.
|
|
10
10
|
4. Submit the run with an inline `secrets` bundle. Wait for terminal status. Fetch outputs.
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
13
|
import { AntpathClient, defineTemplate, string } from "antpath";
|
|
14
14
|
|
|
15
15
|
const client = new AntpathClient({
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
workspaceId: process.env.ANTPATH_WORKSPACE_ID!
|
|
16
|
+
apiToken: process.env.ANTPATH_API_TOKEN!
|
|
17
|
+
// baseUrl defaults to https://antpath.ai — set it for self-hosted deployments.
|
|
19
18
|
});
|
|
20
19
|
|
|
21
20
|
const template = defineTemplate({
|
|
@@ -40,8 +39,6 @@ Or from the shell:
|
|
|
40
39
|
```bash
|
|
41
40
|
antpath run ./template.json \
|
|
42
41
|
--api-token "$ANTPATH_API_TOKEN" \
|
|
43
|
-
--workspace "$ANTPATH_WORKSPACE_ID" \
|
|
44
|
-
--dashboard-url https://antpath.example.com \
|
|
45
42
|
--anthropic-api-key "$ANTHROPIC_API_KEY" \
|
|
46
43
|
--var topic="agent-first SDK design" \
|
|
47
44
|
--follow
|
package/docs/release.md
CHANGED
|
@@ -4,19 +4,64 @@ title: Release
|
|
|
4
4
|
|
|
5
5
|
# Release
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Releasing is **atomic** and **driven by `packages/sdk/package.json#version`**: bump the SDK version on `main` and the publish pipeline carries that exact version through npm → git tag → GitHub Release in one job. Any push to `main` that does not bump the version is a publish no-op.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## How to ship a release
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
1. On a branch, bump `packages/sdk/package.json#version` to the next semver. Land any companion code/doc changes in the same PR.
|
|
12
|
+
2. Merge into `main` (or push directly if you have the right). The pre-push hook (see [Local guard rails](#local-guard-rails)) refuses the push if the local version still matches what's on npm or has already been git-tagged.
|
|
13
|
+
3. CI (`.github/workflows/ci.yml`) runs the `version-gate` job on every PR and direct push to `main`. It diffs against the base ref using [`scripts/check-version-drift.mjs --strict`](../../scripts/check-version-drift.mjs) and fails fast if anything under `packages/{sdk,cli,shared}/src/` or the listed exact paths changed without a fresh version. **`--strict` treats unreachable npm as a hard failure** so we never publish on top of an existing version.
|
|
14
|
+
4. After merge, the `Publish package` workflow (`.github/workflows/publish.yml`) is triggered automatically on push to `main` and decides whether to ship.
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
2. Add a Trusted Publisher for this GitHub repository.
|
|
15
|
-
3. Set **Organization or user** to `weilueluo`.
|
|
16
|
-
4. Set **Repository** to `antpath`.
|
|
17
|
-
5. Set **Workflow filename** to `publish.yml`.
|
|
18
|
-
6. Leave **Environment name** empty unless the workflow uses a matching GitHub Actions environment.
|
|
19
|
-
7. Update `packages/sdk/package.json` version before publishing a release.
|
|
20
|
-
8. Publish a GitHub release for that version.
|
|
16
|
+
You don't tag locally and you don't open a GitHub Release manually — the workflow does both. If the workflow ends red after a successful `npm publish`, the npm version is the source of truth and a human can tag/release retroactively.
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
## Publish pipeline
|
|
19
|
+
|
|
20
|
+
The workflow has three jobs, in this order:
|
|
21
|
+
|
|
22
|
+
1. **`decide`** — compares the local `packages/sdk/package.json#version` with `npm view antpath@latest version`.
|
|
23
|
+
- If they match → output `proceed=false` and the rest of the pipeline no-ops. Documentation-only commits, refactors that ride along with a previous version, and any other non-publishable change pass through cleanly.
|
|
24
|
+
- If they differ → `proceed=true`, with the local version flowing forward as the canonical `v<version>` for tagging and release notes.
|
|
25
|
+
2. **`publish`** (gated on `proceed=true`) — single linear job:
|
|
26
|
+
- `pnpm install --frozen-lockfile`, `pnpm lint`, `pnpm test`, `pnpm build`.
|
|
27
|
+
- `pnpm --filter antpath pack` into `$RUNNER_TEMP`.
|
|
28
|
+
- **Pre-publish user-tests gate**: runs `apps/user-tests` `user-test:offline` against the packed tarball. A broken artifact (missing `bin`, broken shebang, leaked workspace dep, ESM-only contract violation, …) never reaches npm.
|
|
29
|
+
- **Final freshness check**: `npm view antpath@${VERSION} version` — guards the rare race where someone else publishes the same version between `decide` and here.
|
|
30
|
+
- `pnpm publish --provenance --no-git-checks` from `packages/sdk`. Auth is GitHub OIDC via `id-token: write` plus npm Trusted Publishers — there is no `NPM_TOKEN` secret.
|
|
31
|
+
- `git tag -a v${VERSION}` signed as the canonical commit identity, then `git push origin v${VERSION}`.
|
|
32
|
+
- `gh release create v${VERSION} --generate-notes`.
|
|
33
|
+
3. **`user-tests-post-publish`** (matrix `ubuntu-latest, windows-latest`) — waits for registry visibility with `scripts/wait-for-npm.mjs antpath <version>` (catches the "metadata says yes but CDN tarball 404s" case), then runs `user-test:offline` against the published version on both runners.
|
|
34
|
+
|
|
35
|
+
Atomicity boundary: **publish + tag + GitHub Release happen in the same job**. Until that job goes green, the release is not done — even if `npm publish` already succeeded. Post-publish user-tests are a follow-on signal, not part of the atomic act.
|
|
36
|
+
|
|
37
|
+
## What ships in the tarball
|
|
38
|
+
|
|
39
|
+
The published tarball is **self-contained**. It declares **zero `@antpath/*` runtime dependencies** and is installable from a clean `npm install antpath` with no workspace access:
|
|
40
|
+
|
|
41
|
+
- `@antpath/shared` lives in `packages/sdk/package.json#devDependencies` only. At build time, [`packages/sdk/scripts/inline-shared.mjs`](../scripts/inline-shared.mjs) copies `packages/shared/dist/**` (minus the test-only `testing/` directory and sourcemaps) into `packages/sdk/dist/_shared/` and rewrites `from "@antpath/shared"` to `from "./_shared/index.js"` across the SDK dist tree. A sanity check at the end of that script refuses to finish if any bare `@antpath/shared` specifier survives.
|
|
42
|
+
- `@antpath/cli` is bundled at build time by [`packages/sdk/scripts/bundle-cli.mjs`](../scripts/bundle-cli.mjs) into a single `dist/cli.mjs`, which is the `bin: antpath` entry in `packages/sdk/package.json`.
|
|
43
|
+
- This invariant is mechanically enforced by `apps/user-tests/test/offline/install.test.ts` ("declares no @antpath/* runtime dependencies") — the pre-publish gate fails before npm if any workspace dep leaks back into `dependencies`/`peerDependencies`/`optionalDependencies`.
|
|
44
|
+
|
|
45
|
+
## Local guard rails
|
|
46
|
+
|
|
47
|
+
Every contributor who pushes is expected to install the tracked pre-push hook from the repo root once:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
pnpm hooks:install
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The hook runs lint, tests, build, an SDK pack dry-run, and `check-version-drift.mjs` (advisory mode — unreachable npm is a warning so offline development still works). It catches "I bumped a runtime file but forgot to bump the version" or "the new version is already on npm" before the push leaves the laptop.
|
|
54
|
+
|
|
55
|
+
## Repository setup (one-time)
|
|
56
|
+
|
|
57
|
+
1. Reserve `antpath` on npm.
|
|
58
|
+
2. Add a Trusted Publisher for this repository (`npmjs.com` → *Settings* → *Publishing access*):
|
|
59
|
+
- **Organization or user**: `weilueluo`
|
|
60
|
+
- **Repository**: `antpath`
|
|
61
|
+
- **Workflow filename**: `publish.yml`
|
|
62
|
+
- **Environment name**: leave empty.
|
|
63
|
+
3. No `NPM_TOKEN` secret is required — OIDC handles auth.
|
|
64
|
+
|
|
65
|
+
## Rollback
|
|
66
|
+
|
|
67
|
+
There is no "unpublish" path: npm prevents reuse of a published version, and a bad release is fixed by publishing a higher version. If the atomic publish job dies between `npm publish` and `gh release create`, retag manually (`git tag -a v<version>`, push, `gh release create`); npm is already truthful.
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { AntpathClient, defineTemplate, requiredStaticBearer } from "antpath";
|
|
2
2
|
|
|
3
3
|
const client = new AntpathClient({
|
|
4
|
-
|
|
5
|
-
apiToken: process.env.ANTPATH_API_TOKEN!,
|
|
6
|
-
workspaceId: process.env.ANTPATH_WORKSPACE_ID!
|
|
4
|
+
apiToken: process.env.ANTPATH_API_TOKEN!
|
|
7
5
|
});
|
|
8
6
|
|
|
9
7
|
const template = defineTemplate({
|
package/examples/quickstart.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { AntpathClient, defineTemplate, string } from "antpath";
|
|
2
2
|
|
|
3
3
|
const client = new AntpathClient({
|
|
4
|
-
|
|
5
|
-
apiToken: process.env.ANTPATH_API_TOKEN!,
|
|
6
|
-
workspaceId: process.env.ANTPATH_WORKSPACE_ID!
|
|
4
|
+
apiToken: process.env.ANTPATH_API_TOKEN!
|
|
7
5
|
});
|
|
8
6
|
|
|
9
7
|
const template = defineTemplate({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "antpath",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "TypeScript SDK for running autonomous Claude Managed Agents sessions.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -22,8 +22,7 @@
|
|
|
22
22
|
"dist",
|
|
23
23
|
"README.md",
|
|
24
24
|
"docs",
|
|
25
|
-
"examples"
|
|
26
|
-
"references"
|
|
25
|
+
"examples"
|
|
27
26
|
],
|
|
28
27
|
"devDependencies": {
|
|
29
28
|
"@antpath/shared": "0.1.0"
|
|
@@ -1,473 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: antpath architecture decisions
|
|
3
|
-
status: accepted
|
|
4
|
-
scope: platform MVP
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# antpath architecture decisions
|
|
8
|
-
|
|
9
|
-
## Product framing
|
|
10
|
-
|
|
11
|
-
antpath is a TypeScript-first platform plus SDK for running autonomous sessions on provider-managed agent infrastructure. Claude Managed Agents remains the execution runtime. antpath provides the durable control plane around it: submit jobs, dispatch provider sessions, track tenant-scoped metadata, observe lifecycle state, capture configured outputs, enforce quotas, and retain or clean up provider resources according to run policy.
|
|
12
|
-
|
|
13
|
-
The platform is intentionally not a custom agent loop or sandbox runtime. The worker dispatches, observes, stores metadata, captures outputs, and applies retention/cleanup policy. It does not execute tools, approve tool calls, or participate in provider-side reasoning.
|
|
14
|
-
|
|
15
|
-
This supersedes the earlier SDK-only MVP boundary.
|
|
16
|
-
|
|
17
|
-
## Goals
|
|
18
|
-
|
|
19
|
-
- Stable start-to-finish lifecycle for provider-managed agent runs.
|
|
20
|
-
- Minimal tenant-scoped dashboard metadata for monitoring run execution.
|
|
21
|
-
- Durable worker recovery after restarts, deploys, crashes, or missed notifications.
|
|
22
|
-
- Horizontal worker scaling without duplicate run ownership.
|
|
23
|
-
- Provider cleanup by default after terminal states, with optional retention of Claude-side resources when configured per-request or per-deployment.
|
|
24
|
-
- Per-session BYO provider key custody: keys arrive inline with each run, are encrypted in Supabase Vault for the lifetime of that single run, and are deleted at cleanup. Persistent workspace-level provider key custody is backlog.
|
|
25
|
-
- Unconditional capture of every session-scoped Claude artifact into private Supabase Storage, bounded only by the workspace storage cap.
|
|
26
|
-
- Programmatic SDK access for submitting and observing platform runs.
|
|
27
|
-
- Test-driven implementation across SDK, dashboard, worker, database, storage, and provider adapters.
|
|
28
|
-
|
|
29
|
-
## Non-goals for platform MVP
|
|
30
|
-
|
|
31
|
-
- No custom agent loop.
|
|
32
|
-
- No antpath-managed sandbox.
|
|
33
|
-
- No runtime human approval/tool approval flow.
|
|
34
|
-
- No direct browser access to provider APIs.
|
|
35
|
-
- No direct browser Supabase data access.
|
|
36
|
-
- No raw prompt, raw model output, raw provider event payload, MCP credential, provider key, or output file content in normal application tables.
|
|
37
|
-
- No persistent workspace-level provider connections (no "saved Anthropic keys"). Every run carries its own secrets bundle; nothing about the user's Anthropic key persists past run cleanup. Persistent BYO custody is backlog.
|
|
38
|
-
- No user-configurable output capture: every artifact Claude exposes on the run's session is captured. There are no globs, no `capture: false`, no per-file or per-run user-visible caps.
|
|
39
|
-
- No provider Agent/Environment caching in MVP.
|
|
40
|
-
- No provider webhooks in MVP.
|
|
41
|
-
- No Supabase Realtime in MVP.
|
|
42
|
-
- No OpenAI or other provider integration in MVP.
|
|
43
|
-
|
|
44
|
-
## Core decisions
|
|
45
|
-
|
|
46
|
-
| Area | Decision |
|
|
47
|
-
| --- | --- |
|
|
48
|
-
| Product surface | Platform plus SDK. |
|
|
49
|
-
| Repository | Convert the repository to a pnpm TypeScript workspace. |
|
|
50
|
-
| SDK location | Move the existing SDK package to `packages/sdk`. |
|
|
51
|
-
| SDK role | The SDK submits runs and observes status, metadata, outputs, cancellation, and deletion through the platform API. |
|
|
52
|
-
| Dashboard | Build a first-party minimal dashboard. |
|
|
53
|
-
| Worker | Run a Railway persistent service, designed as ephemeral and horizontally scalable. |
|
|
54
|
-
| Database | Use Supabase Postgres as the source of truth. |
|
|
55
|
-
| Storage | Use private Supabase Storage buckets for captured outputs. |
|
|
56
|
-
| Auth | Use Auth.js for user authentication, not Supabase Auth. |
|
|
57
|
-
| Tenant model | Workspace is the tenant boundary. |
|
|
58
|
-
| Membership | Users access workspaces through `workspace_memberships`. |
|
|
59
|
-
| Authorization boundary | Vercel BFF/server actions validate Auth.js sessions or SDK API tokens and scope every DB operation by workspace membership/scope. |
|
|
60
|
-
| Browser data access | Browser code talks to the BFF/server actions, not directly to Supabase data APIs. |
|
|
61
|
-
| Service credentials | Supabase service-role credentials are server/worker only. |
|
|
62
|
-
| SDK auth | SDK uses hashed, workspace-scoped API tokens. Dashboard uses Auth.js sessions. |
|
|
63
|
-
| API token attribution | Token-authenticated runs are attributed to the token creator at submission time unless a future service-account model is introduced. |
|
|
64
|
-
| Provider key custody | BYO Anthropic key arrives inline with every run submission. The BFF stores the secrets bundle in Supabase Vault, attaches the secret id to the run row, and deletes the Vault entry as part of cleanup. Persistent workspace-level provider connections are backlog. |
|
|
65
|
-
| Secret lifetime | Worker resolves the per-run secrets bundle once per claimed lifecycle step, keeps the decoded payload only in memory for that step, and drops it before lease release. The Vault entry itself is destroyed when the run reaches terminal cleanup. |
|
|
66
|
-
| Provider resources | Create provider Agent, Environment, Vault/Credential, Session, and file resources per run in MVP. |
|
|
67
|
-
| Provider resource caching | Backlog; later cache Agent/Environment by Template/config hash. |
|
|
68
|
-
| Worker wakeup | Poll due rows from the runs table. Postgres `NOTIFY` is a latency optimization only. |
|
|
69
|
-
| Worker ownership | Use DB leases, `FOR UPDATE SKIP LOCKED`, lease tokens, and expiry for horizontally scaled workers. |
|
|
70
|
-
| Provider observation | Poll provider session status and list provider events since the last cursor/timestamp where available. |
|
|
71
|
-
| Event dedupe | Provider event id is the dedupe authority; cursor/timestamp is advisory. |
|
|
72
|
-
| Webhooks | Backlog only; if added, use as wakeup/reconciliation signals, not sole source of truth. |
|
|
73
|
-
| SSE | Not the primary monitoring mechanism in MVP. |
|
|
74
|
-
| MCP approvals | Disallow approval-required tools. Worker must not approve tools or return custom tool results. |
|
|
75
|
-
| Template boundary | Templates are code-first, secret-free snapshots with stable hashes. |
|
|
76
|
-
| Idempotency | Run submission idempotency is scoped by `(workspace_id, idempotency_key)` and request hash. Same key and same hash returns the existing run; same key and different hash returns conflict. |
|
|
77
|
-
| Quotas | Enforce workspace storage and concurrency quotas. Storage is the only user-visible cap on output capture. |
|
|
78
|
-
| Run caps | Plan-based caps cover duration, concurrency, polling, retries, and workspace storage. There are no user-visible per-file or per-run output caps. |
|
|
79
|
-
| Operational config | Exact cap/tier values are environment-configurable defaults with conservative fallbacks and run-level snapshots. |
|
|
80
|
-
| Boot-time env validation | Worker and dashboard validate required environment variables at startup through a shared role-scoped helper and exit/abort with an aggregated error when any are missing. No silent defaults for identity, credentials, or required URLs. |
|
|
81
|
-
| Output capture | Unconditional. Every file Claude exposes on the run's session is captured into private Supabase Storage. The workspace storage cap is the only user-visible quota; capture failures (quota exceeded, download failed) are persisted as `output_capture_failures` rows and surfaced in the dashboard alongside successful outputs. |
|
|
82
|
-
| Output access | BFF returns signed links only after workspace authorization. |
|
|
83
|
-
| Cleanup | Clean up Claude provider resources by default after terminal state and output capture; explicit run policy or worker default can retain Claude-side resources for inspection. The per-run Vault secret is always deleted at cleanup regardless of the Claude-side retention knob. |
|
|
84
|
-
| Delete semantics | User delete is soft/pending while execution, cleanup, or storage deletion is active. Hard purge happens only after cleanup/storage deletion succeeds. |
|
|
85
|
-
| Retention | Run metadata and stored outputs remain until user deletion in MVP. |
|
|
86
|
-
| Realtime | Defer from MVP; use BFF-mediated refresh/polling first. Revisit with custom Supabase JWT/RLS or a server-mediated realtime bridge. |
|
|
87
|
-
| Development workflow | Use test-driven development: write or update the failing test at the narrowest useful layer before implementation. |
|
|
88
|
-
|
|
89
|
-
## Workspace layout
|
|
90
|
-
|
|
91
|
-
Target structure:
|
|
92
|
-
|
|
93
|
-
```text
|
|
94
|
-
apps/
|
|
95
|
-
dashboard/
|
|
96
|
-
app/
|
|
97
|
-
server/
|
|
98
|
-
components/
|
|
99
|
-
auth/
|
|
100
|
-
db/
|
|
101
|
-
worker/
|
|
102
|
-
src/
|
|
103
|
-
main.ts
|
|
104
|
-
polling/
|
|
105
|
-
providers/
|
|
106
|
-
lifecycle/
|
|
107
|
-
cleanup/
|
|
108
|
-
storage/
|
|
109
|
-
observability/
|
|
110
|
-
packages/
|
|
111
|
-
sdk/
|
|
112
|
-
src/
|
|
113
|
-
shared/
|
|
114
|
-
src/
|
|
115
|
-
types/
|
|
116
|
-
status/
|
|
117
|
-
redaction/
|
|
118
|
-
templates/
|
|
119
|
-
db/
|
|
120
|
-
migrations/
|
|
121
|
-
schema/
|
|
122
|
-
queries/
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
`packages/shared` and `packages/db` may start small and grow only when invariants or schema/query helpers are shared by dashboard, worker, and SDK.
|
|
126
|
-
|
|
127
|
-
## Core data model
|
|
128
|
-
|
|
129
|
-
### Identity and tenancy
|
|
130
|
-
|
|
131
|
-
- Auth.js adapter tables: `users`, `accounts`, `sessions`, and `verification_token`
|
|
132
|
-
- Auth.js owns OAuth account linking and email magic-link verification persistence in the same Supabase Postgres database.
|
|
133
|
-
- Active application sessions use Auth.js JWT strategy; the `sessions` table exists for adapter compatibility but is not the active session store.
|
|
134
|
-
- Auth.js OAuth tokens remain confined to Auth.js adapter tables and never become antpath provider credentials.
|
|
135
|
-
- `app_users`
|
|
136
|
-
- Antpath-owned user identity row linked to Auth.js `users.id` through `auth_user_id`.
|
|
137
|
-
- Workspace membership, run attribution, API-token ownership, disable state, and JWT token-version checks use `app_users.id`.
|
|
138
|
-
- `disabled_at` and `token_version` are checked by privileged BFF routes to reject disabled or stale JWT users.
|
|
139
|
-
- No provider secrets.
|
|
140
|
-
- `workspaces`
|
|
141
|
-
- Tenant boundary.
|
|
142
|
-
- Plan, quota, status, and retention settings.
|
|
143
|
-
- `workspace_memberships`
|
|
144
|
-
- Workspace, `app_user_id`, role, and membership status.
|
|
145
|
-
- Every dashboard/API operation must prove membership/scope.
|
|
146
|
-
- `api_tokens`
|
|
147
|
-
- Workspace-scoped SDK credentials.
|
|
148
|
-
- Store hashed token material only, plus scopes, `creator_app_user_id`, last-used timestamp, and revoked timestamp.
|
|
149
|
-
- API-token submissions freeze the attributed user on the run row at creation time.
|
|
150
|
-
|
|
151
|
-
### Per-run secrets
|
|
152
|
-
|
|
153
|
-
There is no `provider_connections` table in MVP. Every run carries its own secrets.
|
|
154
|
-
|
|
155
|
-
- The submission contract has a top-level `secrets` block: `{ anthropic: { apiKey }, mcpServers?: [{ name, url, headers? }], skills?: [...] }`. The shared parser enforces that **no other field** carries secret-bearing keys; the `secrets` block is the single allowlisted carrier and never serializes into normal metadata, logs, events, audit rows, or stored snapshots.
|
|
156
|
-
- The dashboard BFF stores the JSON-encoded bundle in Supabase Vault at submission time and writes the resulting `vault_secret_id` into `runs.execution_secret_id`. The bundle is the only durable trace of the user's Anthropic key, MCP credentials, and skill references for that run.
|
|
157
|
-
- Worker code reads `runs.execution_secret_id` once per claimed step, decodes the bundle in memory, builds the Claude provider, and drops the decoded values before lease release.
|
|
158
|
-
- At terminal cleanup the worker deletes the Vault entry and clears `runs.execution_secret_id`. Cleanup of the Vault secret happens regardless of the Claude-side retention knob.
|
|
159
|
-
- If the user revokes (rotates) the Anthropic key on Anthropic's side mid-run, antpath has no knowledge of this until the next provider call fails. Active runs surface a `tenant_permanent` failure with a redacted reason; cleanup proceeds with the previously vaulted key while it remains valid and gives up gracefully if it does not.
|
|
160
|
-
|
|
161
|
-
### Runs
|
|
162
|
-
|
|
163
|
-
- `runs`
|
|
164
|
-
- User-visible logical run.
|
|
165
|
-
- Workspace, `creator_app_user_id`, template snapshot/hash, status, lifecycle phase, plan caps, timestamps.
|
|
166
|
-
- Submission idempotency key and request hash.
|
|
167
|
-
- Unique constraint: `(workspace_id, idempotency_key)`.
|
|
168
|
-
- `execution_secret_id` — Supabase Vault secret id for the per-run secrets bundle (Anthropic key + MCP credentials + skill references). Cleared at cleanup.
|
|
169
|
-
- Lease fields: `lease_owner`, `lease_token`, `lease_expires_at`, `attempt_count`, `next_check_at`, `priority`.
|
|
170
|
-
- Cancellation/deletion fields: `cancel_requested_at`, `pending_delete_at`, `deleted_at`.
|
|
171
|
-
- Provider observation cursor/watermark where available.
|
|
172
|
-
- `run_attempts`
|
|
173
|
-
- A logical run may have multiple provider attempts.
|
|
174
|
-
- Tracks provider session id, attempt state, start/end timestamps, and error classification.
|
|
175
|
-
- `provider_resources`
|
|
176
|
-
- Journal of intended and created provider resources.
|
|
177
|
-
- Resource type, local idempotency key, deterministic provider name/metadata tags, provider id when known, cleanup status.
|
|
178
|
-
- Insert an intended row before provider side effects whenever possible.
|
|
179
|
-
- `run_events`
|
|
180
|
-
- Metadata only.
|
|
181
|
-
- Provider event id/type, processed timestamp, redacted summary fields, usage metadata.
|
|
182
|
-
- Unique constraint on `(run_attempt_id, provider_event_id)`.
|
|
183
|
-
- No raw prompts, raw outputs, tool inputs/results, file contents, or credentials.
|
|
184
|
-
|
|
185
|
-
### Outputs and cleanup
|
|
186
|
-
|
|
187
|
-
- `output_objects`
|
|
188
|
-
- Workspace/run owner, storage bucket/path, size, checksum if available, content type, provider file id.
|
|
189
|
-
- One row per artifact successfully captured from the run's session into private Supabase Storage.
|
|
190
|
-
- Used for quota accounting and signed-link generation.
|
|
191
|
-
- `output_capture_failures`
|
|
192
|
-
- Workspace/run owner, provider file id, filename, byte size as reported by the provider, reason (`workspace_quota_exceeded`, `download_failed`, etc.), redacted error message.
|
|
193
|
-
- Surfaced in the dashboard alongside `output_objects` so the user can see exactly which session artifacts didn't make it to storage and why.
|
|
194
|
-
- `cleanup_attempts`
|
|
195
|
-
- Per-resource cleanup action, status, retry count, redacted error code/message, timestamps.
|
|
196
|
-
- `usage_ledger`
|
|
197
|
-
- Token/cost/storage attribution by workspace and attributed user.
|
|
198
|
-
- Written transactionally with source event/output rows to avoid drift.
|
|
199
|
-
- `audit_logs`
|
|
200
|
-
- Safe security audit trail for sign-in user upsert, API-token changes, run cancellation/deletion, signed-link creation, and cleanup failures.
|
|
201
|
-
- Stores safe identifiers, action names, redacted errors, and non-secret metadata only.
|
|
202
|
-
- `rate_limit_buckets`
|
|
203
|
-
- Durable token-bucket-style counters for abuse-sensitive BFF/API operations.
|
|
204
|
-
- Used before side effects for run submission, run cancellation/deletion, signed-link creation, API-token creation/revocation, and email-auth throttling where practical.
|
|
205
|
-
|
|
206
|
-
## Run lifecycle
|
|
207
|
-
|
|
208
|
-
1. SDK/dashboard submits a run to the BFF. The submission carries a top-level `secrets` bundle (Anthropic key, optional MCP credentials, optional skill references) plus the non-secret template/variables/cleanup payload.
|
|
209
|
-
2. BFF validates Auth.js session or SDK API token.
|
|
210
|
-
3. BFF resolves active workspace membership/scope.
|
|
211
|
-
4. BFF validates Template/request shape, plan limits, and idempotency key/request hash. The shared parser rejects every secret-bearing key outside the allowlisted `secrets` block.
|
|
212
|
-
5. BFF stores the JSON-encoded `secrets` bundle in Supabase Vault and writes a `runs` row with execution-affecting cap values snapshotted from plan/env defaults plus `execution_secret_id` pointing at the Vault entry.
|
|
213
|
-
6. BFF emits Postgres `NOTIFY` for fast wakeup.
|
|
214
|
-
7. Worker claims due runs with row locking, `SKIP LOCKED`, lease token, and lease expiry.
|
|
215
|
-
8. Worker resolves the per-run secrets bundle from Supabase Vault for the claimed step.
|
|
216
|
-
9. Worker validates platform constraints: no approval-required tools, no custom antpath-executed tools.
|
|
217
|
-
10. Worker pre-journals intended provider resources.
|
|
218
|
-
11. Worker creates provider resources and records provider IDs immediately after successful calls.
|
|
219
|
-
12. Worker creates provider session and sends the initial user event.
|
|
220
|
-
13. Worker schedules provider polling through `next_check_at`.
|
|
221
|
-
14. Worker later reclaims the run and polls provider session status plus event list.
|
|
222
|
-
15. Worker stores only metadata events and usage, deduped by provider event id.
|
|
223
|
-
16. Before every side effect, worker checks lease token and cancellation/deletion requests.
|
|
224
|
-
17. On terminal provider state or antpath timeout, worker lists session-scoped files via the Claude Files API and unconditionally captures every file the workspace storage quota still has room for, persisting `output_capture_failures` rows for any file that would exceed the cap.
|
|
225
|
-
18. Worker cleans up Claude-side provider resources by default, or records them as retained when the run/deployment policy asks to retain them. The per-run Vault entry is deleted regardless.
|
|
226
|
-
19. Worker marks the run terminal and releases the lease.
|
|
227
|
-
20. Dashboard/SDK read tenant-scoped metadata and signed output links through BFF APIs.
|
|
228
|
-
|
|
229
|
-
## Worker concurrency and recovery
|
|
230
|
-
|
|
231
|
-
The database is the coordination primitive. Worker instances are stateless and can be added or removed without losing correctness.
|
|
232
|
-
|
|
233
|
-
Claiming rules:
|
|
234
|
-
|
|
235
|
-
- Query due rows ordered by priority, fairness across workspaces, and `next_check_at`.
|
|
236
|
-
- Use `FOR UPDATE SKIP LOCKED`.
|
|
237
|
-
- Set `lease_owner`, `lease_token`, `lease_expires_at`, and attempt counters.
|
|
238
|
-
- Commit immediately.
|
|
239
|
-
- Execute one bounded lifecycle step outside long transactions.
|
|
240
|
-
- Persist result and either schedule next step or mark terminal.
|
|
241
|
-
|
|
242
|
-
Safety rules:
|
|
243
|
-
|
|
244
|
-
- Every status-mutating update includes `WHERE lease_token = $token AND lease_expires_at > now()` and verifies exactly one affected row.
|
|
245
|
-
- Every side-effecting step checks `cancel_requested_at` and `pending_delete_at`.
|
|
246
|
-
- Expired leases are reclaimable by any worker.
|
|
247
|
-
- `next_check_at` includes jitter.
|
|
248
|
-
- Claiming enforces per-workspace active-run caps and provider-key-scoped rate limits.
|
|
249
|
-
- Workers handle SIGTERM by stopping new claims and relying on bounded steps, idempotency, leases, and reconciliation for in-flight work.
|
|
250
|
-
- Polling is always enabled; `NOTIFY` only reduces latency.
|
|
251
|
-
|
|
252
|
-
## Provider observation
|
|
253
|
-
|
|
254
|
-
MVP source of truth:
|
|
255
|
-
|
|
256
|
-
- Provider session retrieve for status.
|
|
257
|
-
- Provider session events list for event metadata and usage.
|
|
258
|
-
|
|
259
|
-
Rules:
|
|
260
|
-
|
|
261
|
-
- Cursor/timestamp filters are used when available.
|
|
262
|
-
- Provider event id is always used for dedupe.
|
|
263
|
-
- Phase 5 must verify Claude Managed Agents event pagination/filter semantics.
|
|
264
|
-
- If no stable cursor or since filter exists, use a bounded re-list strategy with event-id dedupe instead of unbounded full-history scans.
|
|
265
|
-
|
|
266
|
-
Excluded from MVP:
|
|
267
|
-
|
|
268
|
-
- SSE as primary monitoring.
|
|
269
|
-
- Anthropic webhooks as primary monitoring.
|
|
270
|
-
|
|
271
|
-
## Auth and dashboard security
|
|
272
|
-
|
|
273
|
-
Auth.js handles interactive user sign-in. SDK API tokens handle programmatic access.
|
|
274
|
-
|
|
275
|
-
BFF/server actions must:
|
|
276
|
-
|
|
277
|
-
- validate Auth.js session or API token;
|
|
278
|
-
- resolve user identity and active workspace;
|
|
279
|
-
- check workspace membership or token scope;
|
|
280
|
-
- scope every query/mutation by workspace id;
|
|
281
|
-
- return only metadata allowed by the user's role/scope;
|
|
282
|
-
- keep Supabase service-role credentials out of browser bundles.
|
|
283
|
-
|
|
284
|
-
Auth.js and antpath authorization stay separate in the database. Auth.js owns `users`, `accounts`, `sessions`, and `verification_token`; antpath owns `app_users` and links each row to Auth.js `users.id`. JWT callbacks expose only safe identity fields such as `app_user_id` and token version. BFF routes must load the current `app_users` row and reject disabled users or stale token versions before privileged actions.
|
|
285
|
-
|
|
286
|
-
All platform and Auth.js tables have RLS enabled and `anon`/`authenticated` table privileges revoked. This is a defense-in-depth guard against accidental Supabase Data API exposure; direct `pg` repository code remains the primary BFF/worker authorization boundary for this phase.
|
|
287
|
-
|
|
288
|
-
Supabase Realtime is backlog until antpath either mints short-lived Supabase-compatible JWTs with RLS policies or exposes a server-mediated realtime bridge.
|
|
289
|
-
|
|
290
|
-
## Secret handling
|
|
291
|
-
|
|
292
|
-
- Provider keys arrive inline with each submission and are stored in Supabase Vault tied to a single run via `runs.execution_secret_id`.
|
|
293
|
-
- MCP credentials and any skill payloads referenced by the run live alongside the provider key inside the same per-run Vault bundle.
|
|
294
|
-
- Normal app tables store only the Vault secret id, not decoded provider keys, MCP credentials, or skill payloads.
|
|
295
|
-
- Worker resolves the decoded bundle only for a claimed lifecycle step and drops the decoded values before lease release.
|
|
296
|
-
- The shared submission parser keeps an allowlist of exactly one carrier (`secrets`) and rejects every other field that looks like a secret-bearing key (`apiKey`, `accessToken`, `password`, `mcpCredentials`, etc.).
|
|
297
|
-
- Secret values use explicit redacted wrappers in code so they cannot serialize into logs, metrics, errors, events, or fixtures.
|
|
298
|
-
- Secret redaction applies to logs, errors, run metadata, provider events, tests, fixtures, and docs.
|
|
299
|
-
- The per-run Vault entry is deleted as part of run cleanup. Cleanup of the Vault entry happens regardless of the Claude-side retention knob.
|
|
300
|
-
- If a provider key is revoked or rotated on the provider side mid-run, the next provider call fails with a `tenant_permanent` error. The worker fails the affected run, attempts cleanup with whatever credentials are still valid, and surfaces a redacted reason on the dashboard.
|
|
301
|
-
- There is no platform-side rotation/revocation flow because there is no persistent provider connection. To "rotate" the user simply submits the next run with a different key.
|
|
302
|
-
|
|
303
|
-
## Output storage and quotas
|
|
304
|
-
|
|
305
|
-
Output capture is unconditional. Every artifact the user's Claude session exposes is downloaded to private Supabase Storage. There are no user-facing knobs to opt out, no globs, and no per-file or per-run user-visible caps.
|
|
306
|
-
|
|
307
|
-
Output flow:
|
|
308
|
-
|
|
309
|
-
1. Worker lists files scoped to the run's Claude session: `GET /v1/files?scope_id=<session_id>`. Each entry includes `id`, `filename`, and `size_bytes`.
|
|
310
|
-
2. For each file, before downloading, the worker checks `(workspace.storage_used_bytes + size_bytes)` against the workspace storage cap.
|
|
311
|
-
3. If the file would exceed the cap, the worker writes an `output_capture_failures` row (`reason = "workspace_quota_exceeded"`, with filename and reported byte size) and moves on without downloading.
|
|
312
|
-
4. Otherwise the worker downloads via `GET /v1/files/{file_id}/content` with a hard streaming safety cap so a malformed listing response cannot OOM the worker, uploads to private Supabase Storage at a workspace-scoped path, and writes an `output_objects` row.
|
|
313
|
-
5. Other download/upload failures (network, storage, unexpected size) are recorded as `output_capture_failures` with the redacted reason.
|
|
314
|
-
6. Dashboard/SDK request signed links through the BFF for any `output_objects` row.
|
|
315
|
-
|
|
316
|
-
Quota rules:
|
|
317
|
-
|
|
318
|
-
- Workspace storage cap is the only hard enforcement boundary. Default is generous (configurable via env, see [`environment-variables.md`](./environment-variables.md)).
|
|
319
|
-
- There is no per-user quota. Per-user attribution still freezes on the run row at submission time for billing/audit purposes, but it is not a quota dimension.
|
|
320
|
-
- There are no user-visible per-file or per-run caps. A worker-internal streaming safety cap protects against malformed listings.
|
|
321
|
-
- Capture failures are first-class data: the dashboard renders `<filename> (<size>) — skipped: workspace quota exceeded` next to successful outputs so the user can see exactly what didn't make it.
|
|
322
|
-
|
|
323
|
-
## Cleanup and reconciliation
|
|
324
|
-
|
|
325
|
-
Claude provider-resource cleanup is mandatory by default after terminal provider state and output capture so antpath does not leave behind provider state. Retention is opt-in for **Claude-side resources only** through `cleanup.claudeSession = "retain"` or `ANTPATH_WORKER_CLAUDE_SESSION_CLEANUP_DEFAULT=retain`. Retained resources are recorded in `provider_resources.cleanup_status = retained` and remain reachable via the provider API. Antpath-side metadata, output objects, and the per-run Vault entry are not affected by this knob — Vault entries are always deleted at cleanup; metadata and outputs persist until the user explicitly deletes the run.
|
|
326
|
-
|
|
327
|
-
Explicit cleanup order:
|
|
328
|
-
|
|
329
|
-
1. Capture session-scoped files into private Supabase Storage (with quota pre-check; failures persisted).
|
|
330
|
-
2. Provider session files / session where supported.
|
|
331
|
-
3. Agent / archive.
|
|
332
|
-
4. Environment / archive or delete where allowed.
|
|
333
|
-
5. Skills uploaded for this session and any other ephemeral provider resources created for this run.
|
|
334
|
-
6. Provider Vault/Credentials created on Claude's side for MCP wiring.
|
|
335
|
-
7. The antpath per-run Vault entry: `vault.deleteSecret(runs.execution_secret_id)`, then clear the column.
|
|
336
|
-
8. Local output metadata/storage only when the user deletes a run.
|
|
337
|
-
|
|
338
|
-
Cleanup properties:
|
|
339
|
-
|
|
340
|
-
- Retried independently from run execution.
|
|
341
|
-
- Idempotent where provider APIs allow.
|
|
342
|
-
- Redacted errors recorded in `cleanup_attempts`.
|
|
343
|
-
- Runs can be terminal while cleanup remains pending or retryable-failed.
|
|
344
|
-
- User deletion sets `pending_delete_at` while cleanup/storage deletion is active.
|
|
345
|
-
|
|
346
|
-
Resource leak recovery:
|
|
347
|
-
|
|
348
|
-
- Every provider create starts from a local intended row with deterministic provider name/metadata where provider APIs allow.
|
|
349
|
-
- A reconciliation sweeper reviews unfinished intended rows, expired leases, and provider-listable resources tagged with antpath metadata.
|
|
350
|
-
- If provider create succeeded but provider id was not persisted before a crash, the sweeper attempts to match by deterministic name/metadata and attach the provider id for cleanup.
|
|
351
|
-
|
|
352
|
-
Workspace deletion:
|
|
353
|
-
|
|
354
|
-
- Workspace deletion blocks new runs, requests cancellation for active runs, drains cleanup, deletes stored outputs, then purges metadata.
|
|
355
|
-
- There is no separate "provider key revocation" flow because there is no persistent provider key. Submitting the next run with a different key is the rotation mechanism.
|
|
356
|
-
|
|
357
|
-
## Audit, rate limits, quotas, and deletion
|
|
358
|
-
|
|
359
|
-
- Abuse-sensitive actions are rate-limited before provider, Vault, Storage, or mutation side effects where practical.
|
|
360
|
-
- Audit logs must never include provider keys, OAuth tokens, MCP credentials, raw prompts, raw outputs, signed URLs, or service-role credentials.
|
|
361
|
-
- Workspace storage quota is enforced before output download/upload when file size is known, with streaming hard caps for unknown-size files.
|
|
362
|
-
- App-user deletion is soft/disable-first; hard deletion must not break historical run, usage, output, or audit references.
|
|
363
|
-
- Workspace deletion is pending-first: block new submissions, mark active runs pending-delete, allow cleanup/storage deletion to drain, then purge only safe metadata.
|
|
364
|
-
- Recovery operations should be driven by explicit cleanup/deletion state and audit logs, not manual DB guessing.
|
|
365
|
-
|
|
366
|
-
## Run state model
|
|
367
|
-
|
|
368
|
-
Suggested run statuses:
|
|
369
|
-
|
|
370
|
-
- `queued`
|
|
371
|
-
- `claiming`
|
|
372
|
-
- `provisioning`
|
|
373
|
-
- `session_created`
|
|
374
|
-
- `dispatched`
|
|
375
|
-
- `provider_running`
|
|
376
|
-
- `provider_idle`
|
|
377
|
-
- `provider_rescheduled`
|
|
378
|
-
- `cancelling`
|
|
379
|
-
- `capturing_outputs`
|
|
380
|
-
- `cleaning_up`
|
|
381
|
-
- `succeeded`
|
|
382
|
-
- `failed`
|
|
383
|
-
- `timed_out`
|
|
384
|
-
- `cancelled`
|
|
385
|
-
- `cleanup_failed`
|
|
386
|
-
- `pending_delete`
|
|
387
|
-
- `deleted`
|
|
388
|
-
|
|
389
|
-
Terminal user-facing run status is separate from cleanup state so a successful provider run can still show cleanup retry warnings.
|
|
390
|
-
|
|
391
|
-
Error classes:
|
|
392
|
-
|
|
393
|
-
- `transient_provider`: retry with backoff and jitter.
|
|
394
|
-
- `provider_permanent`: fail attempt/run and cleanup.
|
|
395
|
-
- `tenant_permanent`: invalid key, quota exceeded, invalid Template, approval-required event observed.
|
|
396
|
-
- `antpath_bug`: fail safely, alert, and preserve cleanup work.
|
|
397
|
-
- `cancelled_by_user`: cleanup and mark cancelled.
|
|
398
|
-
|
|
399
|
-
## Deployment baseline
|
|
400
|
-
|
|
401
|
-
- Dashboard: Vercel.
|
|
402
|
-
- Worker: Railway persistent service with configurable replicas.
|
|
403
|
-
- Database: Supabase Postgres.
|
|
404
|
-
- Storage: Supabase Storage private bucket.
|
|
405
|
-
- Secrets: Vercel/Railway environment variables plus Supabase Vault for tenant provider keys.
|
|
406
|
-
- CI: GitHub Actions with pnpm, default lint/test/build/package checks, and a separate local Supabase integration job.
|
|
407
|
-
- Local dev stack: `pnpm dev:stack` starts Supabase without printing local keys, validates local config, checks migrations, builds shared packages, and runs the dashboard and worker together. Missing Auth.js providers do not block local service startup unless `ANTPATH_DEV_STACK_REQUIRE_AUTH_PROVIDER=1` is set.
|
|
408
|
-
|
|
409
|
-
Required runtime config includes:
|
|
410
|
-
|
|
411
|
-
- database URL;
|
|
412
|
-
- Supabase service credentials;
|
|
413
|
-
- Supabase Storage bucket;
|
|
414
|
-
- Supabase Vault access function/schema;
|
|
415
|
-
- Auth.js secret/providers;
|
|
416
|
-
- SDK token hashing secret/pepper;
|
|
417
|
-
- worker identity;
|
|
418
|
-
- provider API base/version settings;
|
|
419
|
-
- dashboard BFF rate-limit defaults;
|
|
420
|
-
- worker polling/lease/metrics settings.
|
|
421
|
-
- dev stack ports for dashboard and worker.
|
|
422
|
-
|
|
423
|
-
Environment-configurable defaults include:
|
|
424
|
-
|
|
425
|
-
- max run duration;
|
|
426
|
-
- max active runs per workspace;
|
|
427
|
-
- max active runs per user/token;
|
|
428
|
-
- polling base interval;
|
|
429
|
-
- polling max interval;
|
|
430
|
-
- polling jitter;
|
|
431
|
-
- provider create/delete/poll token-bucket limits;
|
|
432
|
-
- provider retry backoff;
|
|
433
|
-
- lease duration;
|
|
434
|
-
- lease renewal threshold;
|
|
435
|
-
- max provider attempts;
|
|
436
|
-
- cleanup retry count;
|
|
437
|
-
- cleanup retry backoff;
|
|
438
|
-
- per-file output cap;
|
|
439
|
-
- per-run output cap;
|
|
440
|
-
- workspace storage cap;
|
|
441
|
-
- signed URL TTL;
|
|
442
|
-
- free user allowance;
|
|
443
|
-
- metadata retention toggles;
|
|
444
|
-
- audit/rate-limit windows for sensitive BFF actions.
|
|
445
|
-
- live e2e opt-in flags for provider sessions, public MCP endpoints, Anthropic skill IDs, and timeouts.
|
|
446
|
-
|
|
447
|
-
Missing optional env vars must fall back to conservative low limits. Missing required secret/connectivity env vars must fail service startup.
|
|
448
|
-
|
|
449
|
-
Live public MCP/skills e2e tests are intentionally opt-in because they depend on external provider and public MCP availability. Deterministic unit/component tests validate request wiring for MCP server declarations, tool policies, skill references, and secret non-leakage; the live e2e validates the real provider accepts and runs that configuration end to end.
|
|
450
|
-
|
|
451
|
-
No-cost provider resilience and load testing uses sanitized replay snapshots from real Managed Agents sessions. Replay tests inject network disconnects, transient HTTP failures, provider latency, slow SSE chunks, cleanup failures, and concurrent full-session load around those snapshots. Idempotent read/delete-style calls may retry with bounded backoff; provider create/send POST calls are not retried by default because their side effects may already have happened.
|
|
452
|
-
|
|
453
|
-
## Open implementation details
|
|
454
|
-
|
|
455
|
-
These are not architecture blockers, but must be pinned during implementation planning:
|
|
456
|
-
|
|
457
|
-
- Production plan tier values for duration, concurrency, storage, polling, and free user allowance.
|
|
458
|
-
- Provider metadata naming convention.
|
|
459
|
-
- Provider list/search capabilities and reconciliation coverage for each resource type.
|
|
460
|
-
- Exact Claude Managed Agents event pagination/filter semantics and bounded polling fallback.
|
|
461
|
-
|
|
462
|
-
## Backlog
|
|
463
|
-
|
|
464
|
-
- Persistent workspace-level provider connections (BYO Anthropic key custody across runs, with rotation, revocation, and re-use). The MVP submission contract carries the key inline per run instead.
|
|
465
|
-
- Provider webhooks as wakeup/reconciliation accelerator.
|
|
466
|
-
- SSE live event stream for richer UI.
|
|
467
|
-
- Supabase Realtime with explicit Auth.js-to-Supabase authorization design.
|
|
468
|
-
- Agent/Environment caching by Template/config hash.
|
|
469
|
-
- More providers.
|
|
470
|
-
- Runtime human approval flow if product scope changes.
|
|
471
|
-
- Advanced billing and plan management.
|
|
472
|
-
- Cloud Template registry.
|
|
473
|
-
- Curated MCP adapter catalog.
|