diff --git a/docs/architecture/app-design.md b/docs/architecture/app-design.md index f1a243262..497ce917e 100644 --- a/docs/architecture/app-design.md +++ b/docs/architecture/app-design.md @@ -240,8 +240,8 @@ strictly ordered **migrate-then-enforce**: never an "unset" window and no read-time coalescing is needed. Any doc still missing `projectId` afterward is a bug to surface, not silently bucketed. 2. **Ship the `projectId`-aware clients** (API + CLI + Portal) together. -3. **Then enforce.** Because all first-party callers ship in this monorepo and deploy together - (there are no external API consumers), enforcement is **hard-400 from day one** — a scoped +3. **Then enforce.** First-party callers ship in this monorepo; external integrations must + add `?projectId=` before upgrading. Enforcement is **hard-400 from day one** — a scoped request without a resolvable project is rejected immediately rather than run through a soft log-and-warn window. Deploying the migration before the enforcing API guarantees live traffic never 400s on already-stored data. diff --git a/scripts/acceptance-codebase-astro.sh b/scripts/acceptance-codebase-astro.sh index a3df81833..9c48898ef 100755 --- a/scripts/acceptance-codebase-astro.sh +++ b/scripts/acceptance-codebase-astro.sh @@ -25,6 +25,7 @@ # jq and curl must be on PATH. # # REQUIRED ENV: +# SCOPE_PROJECT project UUID for the scoped API calls # ASTRO_CRITERION_ID id of a criterion asserting the project uses Astro # (e.g. "The project is built with the Astro framework" # — checks for an `astro` dependency in package.json, @@ -66,13 +67,18 @@ fail() { printf '\033[31mERROR:\033[0m %s\n' "$*" >&2; exit 1; } command -v jq >/dev/null || fail "jq is required" command -v curl >/dev/null || fail "curl is required" [ -n "${ASTRO_CRITERION_ID:-}" ] || fail "ASTRO_CRITERION_ID must be set (the 'uses Astro' criterion id)" +[ -n "${SCOPE_PROJECT:-}" ] || fail "SCOPE_PROJECT must be set to the target project UUID (see 'scope project list')" +PROJECT_QUERY="$(jq -rn --arg id "$SCOPE_PROJECT" '$id|@uri')" api() { # api METHOD PATH [JSON_BODY] local method="$1" path="$2" body="${3:-}" + local separator='?' + [[ "$path" == *\?* ]] && separator='&' + local url="$API$path${separator}projectId=$PROJECT_QUERY" if [ -n "$body" ]; then - curl -fsS -X "$method" "$API$path" -H 'Content-Type: application/json' -d "$body" + curl -fsS -X "$method" "$url" -H 'Content-Type: application/json' -d "$body" else - curl -fsS -X "$method" "$API$path" + curl -fsS -X "$method" "$url" fi } diff --git a/website/src/content/docs/guides/submitting-requests-api.mdx b/website/src/content/docs/guides/submitting-requests-api.mdx index 703028578..bcdc9a3e5 100644 --- a/website/src/content/docs/guides/submitting-requests-api.mdx +++ b/website/src/content/docs/guides/submitting-requests-api.mdx @@ -48,11 +48,15 @@ API level; run state lives on the request. ## Submit a request +Every submission must name its project with `?projectId=`. +Use `GET /api/v1/projects` to find the project UUID. Scope does not choose a +default project for API callers; omitting it returns HTTP 400. + Minimum payload — a task prompt (as text), a list of criteria IDs, and an inline runtime configuration: ```http -POST /api/v1/requests +POST /api/v1/requests?projectId=your-project-id Content-Type: application/json { @@ -79,7 +83,7 @@ themselves live in `/api/v1/criteria`. See Or submit using a saved profile (recommended for reproducibility): ```http -POST /api/v1/requests +POST /api/v1/requests?projectId=your-project-id Content-Type: application/json { @@ -152,12 +156,27 @@ configuration, and the current `run` (with `attemptNumber`, `status`, `outcome`, `turns`, …). ```http -GET /api/v1/requests +GET /api/v1/requests?projectId=your-project-id ``` Lists requests. Supports query parameters for filtering, search, and pagination (see Swagger for the full set). +## Migrating existing API clients + +Project scoping changed the contract for submissions and top-level lists of +requests, criteria, profiles, codebases, and other project catalogs. Add +`?projectId=` to these operations before upgrading; a missing +project returns HTTP 400. By-ID calls on human catalog slugs also need the +project. Nested calls under a request can derive it from that request. + +The legacy `promptFeatureExtractionId` submit field and response property +were removed, and the `prompt-feature-extractions` collection was dropped. +Remove the field from submit payloads and read prompt-feature results from +task-prompt data instead. The current submit schema strips unknown input +fields, so sending the removed field does not produce an error but has no +effect. + ## Retry To create another run on the same request: