Skip to content

docs(CLNT-754): document template edits on PUT /api/v1/template/ - #971

Merged
madisonvast merged 1 commit into
mainfrom
CLNT-754-docs-template-update-v1
Oct 21, 2026
Merged

madisonvast merged 1 commit into
mainfrom
CLNT-754-docs-template-update-v1

Conversation

@madisonvast

Copy link
Copy Markdown
Contributor

Summary

  • PUT /api/v0/template/ is being deprecated with a 410 (CLNT-754). The edit-template reference now documents PUT /api/v1/template/: id and hash_id are both required, edits create a new immutable version with a new id/hash_id, and the body must carry the full template rather than only changed fields.
  • Documents the v1 400/404 bodies, the no-edit fast path, the non-creator copy behavior, and the ******** credential placeholder round-trip.
  • Rewrites the Edit a Template section and identifier table in the templates API guide to match.
  • Regenerates the vastai update template and VastAI.update_template reference pages from the CLI branch that moves them to v1 (vast-ai/vast-cli CLNT-754-cli-update-template-v1); only the description, example, and summary lines change.

Rollout

Publish together with the CLI release. The backend 410 lands after both.

Test plan

  • python3 api-reference/openapi/build.py regenerated openapi.yaml; /api/v0/template now has only GET/POST/DELETE and /api/v1/template has PUT
  • mint openapi-check runs in CI (not installed locally)

Jira: https://vastai.atlassian.net/browse/CLNT-754

@mintlify

mintlify Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
vastai-80aa3a82 🟢 Ready View Preview Oct 20, 2026, 1:44 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@Azaeres

Azaeres commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

cc-review: PR #971 — Deprecate PUT /api/v0/template/ and document PUT /api/v1/template/ (CLNT-754)

Branch Strategy

Repository Base Branch Strategy Feature Branch Destination Branch Round
vast-ai/docs main independent, with a rollout dependency: publish with the CLI release; the backend 410 lands after both head 35111dc main 1

The merge-base is 97cf844, not the current main tip. Main has not changed any of the 5 touched files since, and the three-dot diff is clean.

Summary

The PR swaps the edit-template reference to v1 correctly: both id and hash_id are required, edits create a new version, a non-creator edit makes a copy, and masked credentials are handled. Two in-scope Majors remain.

  • The CLI and SDK guides still teach "include only what you want to change". Under v1 that sends null name and image.
  • The documented v1 404 cannot reach clients as written. The backend rewraps it into a 400 whose error is HTTPNotFound.

Ten Minors cover accuracy gaps in the new prose and schema, and one out-of-scope note is recorded.

Coverage limits: The 404-to-400 rewrap (Issue #2) is traced from the backend source and the Pyramid exception hierarchy, not exercised against a running backend. The ticket text was taken from its description and checklist; its comments were not read. The vast-frontend repo was checked only by branch and log search for the ticket key.

Test execution: deferred to the repo's CI/CD pipeline (repo setting); findings are by inspection and the CI result is not part of this review

1. Sources & Blade Sharpening

Inputs from Steps 1-5.

Sources consulted:

  • Jira (CLNT-754): description and checklist (FE replace with v1; API docs replace with v1; deprecate the endpoint with an error pointing to the new one; update public and internal docs). Comments and attachments were not looked up.
  • Prior PR comments: 1 comment, a preview bot. It is not gated on.
  • Specs (reviewed repo): the repo has no openspec/specs/ directory. Law is lifted from the repo's own conventions: OpenAPI sibling-spec consistency, the generator's path rendering, and operationId uniqueness.
  • Figma: not applicable.
  • Pre-change code: base 97cf844 for the edited files.
  • Configuration & ambient: docs.json navigation and permissions.mdx, checked by grep for the edit-template slug.
  • Cross-repo: backend web/views/templates.py and web/paths.py at origin/master; CLI branch CLNT-754-cli-update-template-v1 @ 8cbfc299f992 (unmerged); frontend repo swept for the ticket key only.
  • Diff: git diff 97cf8444...35111dc2 — 5 files, +400/-104.

Local universe enumeration:

  • Layer 0 (diff): 5 files
  • Layer 1 (semantic providers): 3 files — backend update_template_v1, validate_template_params, route table · read 3/3 ✅
  • Layer 2 (consumers): 6 sites — cli/templates.mdx, sdk/python/templates.mdx, create_template.yaml, permissions.mdx, the guide's CLI table, plus a repo-wide grep · read 6/6 ✅
  • Layer 3 (same-lifecycle): 1 file — CLI branch update__template · read 1/1 ✅
  • Layer 4 (config/ambient): 2 files — docs.json and permissions.mdx slug resolution · read 2/2 ✅
  • Layer 5 (specs): 0 (none exist in this repo)
  • Layer 6 (Jira): ticket + 0 adjacent
  • Layer 7 (prior reviews): 1 comment (preview bot)

guides/templates/* was swept by grep only. The backend was read at origin/master only; no backend branch or commit tagged CLNT-754 was found.

Cross-source reconciliations applied during lift:

  • Jira "deprecate v0 with HTTPGone" vs backend origin/master (no HTTPGone in templates.py) → by-design sequencing per the PR rollout note, graded Minor (Issue Updating serverless pyworker image #3).
  • Jira "remove references to the deprecated endpoint" vs the untouched CLI and SDK guides → surfaced as Issue Token #1.
  • PR body "documents v1 400/404 bodies" vs the backend rewrap → surfaced as Issue Fix redirect #2 (templates.py:1412-1418 and :1515-1523).

🔪 BLADE SHARPENED: ✅

2. Constraints Verified

Input from Step 5 (mesh + vertex tags) + Steps 7-8 (Status).

# Constraint Source · Vertex Status
C1 Docs state that v0 PUT is deprecated, returns 410, and points to v1 Jira CLNT-754 checklist item 3; guide mdx:361; edit_template.yaml:19 · [Intent] ⚠️
C2 The API reference replaces the v0 edit operation with the v1 operation, with a unique operationId and an unchanged slug Jira checklist item 2; openapi.yaml editTemplate (head :4180); permissions.mdx:180 · [Intent] ✅
C3 Public docs drop references to the deprecated edit semantics and point users at the replacement, including sibling guides Jira body "update public-facing docs"; cli/templates.mdx:198-206; sdk/python/templates.mdx:252-262 · [Intent] ❌
C4 v1 requires both id and hash_id (the docs claim) backend templates.py:1372-1397 · [Actuality] ✅
C5 The documented 404 (invalid_template, "error 404: Template not found") is what clients actually receive edit_template.yaml '404' block; backend templates.py:1412-1418 vs :1515-1523 · [Law] ❌
C6 The documented 400 coverage and example match backend behavior edit_template.yaml '400' block; backend templates.py:1373-1374, 1396-1397, 2309-2334 · [Law] ⚠️
C7 "Immutable; the previous version keeps its identifiers" is complete and accurate edit_template.yaml:13; guide mdx:289; backend templates.py:1487-1492 · [Law] ⚠️
C8 "Fields you leave out are not carried over" is accurate edit_template.yaml:13; backend templates.py:1423-1426, 1450 · [Law] ⚠️
C9 The 200 schema and no-edit description match the backend: response shape, "creates nothing", tag/image equivalence edit_template.yaml:141-164; guide mdx:355-357; backend templates.py:1439-1448 · [Law] ⚠️
C10 Non-creator edit makes a copy, and masked credentials round-trip as documented edit_template.yaml:15-17; backend templates.py:1454-1466; normalize_template_docker_pass · [Law] ⚠️
C11 CLI and SDK reference pages match the shipped CLI and SDK cli/reference/update-template.mdx:104-111; CLI branch update__template (@8cbfc299) · [Intent] ⚠️
C12 Sibling specs stay consistent with the new v1 contract create_template.yaml:125 (untouched) · [Law] ⚠️
C13 The diff touches only the intended files, with no duplicate path key and no leaked private identifiers diff stat; edit_template.yaml; openapi.yaml · [Actuality] ✅
C14 The v1 rate limit and auth statements (401, 429) match the backend edit_template.yaml '401'/'429'; backend templates.py:1370-1371 · [Law] ✅
C15 The PR rolls out CLI release first or together, and the backend 410 lands after both PR body Rollout · [Intent] ⚠️

Vertex tags: [Intent] prescriptive of what diff should produce; [Law] cross-cutting constraint; [Actuality] behavioral observation from diff.

3. Constraint Mesh Analysis

Input from Step 7 (Attack Matrix).

Constraint Attack Matrix

C1 — v0 deprecation/410 stated ⚠️

  • Contradiction: Backend origin/master update_template (templates.py:1164) still serves the full v0 update. No HTTPGone in templates.py; no backend branch or commit for CLNT-754 found.
  • Edge case: If docs merge before the backend change, readers are told a live endpoint returns 410.
  • Failure mode: A client migrates, then finds v0 still works silently and delays migration, or trusts the wording.
  • Assumption: The PR assumes "publish with the CLI release, backend 410 after". Disclosed in the PR body; merge ordering is not enforced anywhere.

C2 — v0 op replaced by v1 op ✅

  • Contradiction: None. A single editTemplate at head and the v1 path is present.
  • Edge case: None. The slug resolves via permissions.mdx:180.
  • Failure mode: None. The v0 PUT removal is intentional per the ticket.
  • Assumption: Navigation in docs.json was not re-read beyond the slug grep.

C3 — Public docs consistent with the replacement ❌

  • Contradiction: cli/templates.mdx:200 says "Include only the flags you want to change" with an example sending only --desc and --disk_space; the regenerated reference says "Send the full template".
  • Edge case: sdk/python/templates.mdx:254-262 gives the same advice and its signature block (HASH_ID, disk, -> str) is out of step with the regenerated reference.
  • Failure mode: The CLI branch builds the full dict from args, so omitted flags go as None ("name": args.name, "image": args.image, vast.py:7764-7781). validate_template_params has no required-field check (templates.py:2300-2329). Result: a new version stripped of name and image, or a failure.
  • Assumption: Relies on the CLI branch being the shipped CLI.

C4 — v1 requires id and hash_id ✅

  • Contradiction: None. Missing hash_id returns 400 at :1373-1374; missing id returns 400 at :1396-1397.
  • Edge case: None.
  • Failure mode: None. Assumption: None.

C5 — Documented 404 reachable ❌

  • Contradiction: HTTPNotFound is raised at templates.py:1414, 1416 and 1418, inside a try. Handlers are except exc.HTTPBadRequest (:1515) then except Exception (:1520). HTTPNotFound is not an HTTPBadRequest subclass, so the generic handler runs and raises HTTPBadRequest(json={"success": False, "error": type(e).__name__, "msg": str(e)}) (:1521-1523). The client gets 400 with error "HTTPNotFound", not 404 with invalid_template.
  • Edge case: Hits exactly the deleted-template, unknown-id and id/hash-mismatch cases.
  • Failure mode: A client coded to the documented 404 mis-handles these cases.
  • Assumption: Reasoned from the exception hierarchy and handler order, not run; backend tests have no v1 404 assertion for this handler.

C6 — 400 coverage and example ⚠️

  • Contradiction: The example message is "Template ID is required for update", while a missing hash_id returns "Template Hash ID is required for update" (:1374).
  • Edge case: Other reachable 400s are undocumented: docker username without token (:2310), length-limit invalid_params (:2334), masked placeholder with no stored value, unknown key "Invalid Column Names" (:1410), and the rewrapped not-found (C5).
  • Failure mode: Clients cannot enumerate their error cases from the docs.
  • Assumption: The description's "or invalid parameters" partly covers this.

C7 — Immutable / previous version keeps identifiers ⚠️

  • Contradiction: True for identifiers, but a creator edit also UPDATEs the previous version to recommended=False, autoscaler=False, vm=False, sort_order=None (:1487-1492), and copies those flags onto the new version (:1423-1426).
  • Edge case: The editor's own link to the previous version is also affected.
  • Failure mode: A previously featured version silently drops out of listings, which the ticket itself called out for v0.
  • Assumption: None.

C8 — "Fields you leave out are not carried over" ⚠️

  • Contradiction: recommended, autoscaler, sort_order and vm are always copied from the old row (:1423-1426). Omitted tags are kept (:1450). tags is accepted (_pop_template_tags, :1381) but missing from the request schema.
  • Edge case: None. Failure mode: Readers assume omission clears everything. Assumption: None.

C9 — 200 schema, no-edit path, tag/image equivalence ⚠️

  • Contradiction: The no-edit response is {success, hash_id, msg, template} (:1448). The schema omits the top-level hash_id, and "template: The new version" is the unchanged current version on that path.
  • Edge case: "Creates nothing" is slightly off: the path can still add a link for a caller with no relationship (:1440-1441) and reconcile tags for the creator (:1443-1445).
  • Edge case: tag "can also be included in the image field" reads as equivalence, but the hash is computed on raw params, so image: "x:latest" and image: "x", tag: "latest" hash differently and resubmitting in the other form forks a new version instead of a no-op.
  • Assumption: None.

C10 — Non-creator copy and masked credentials ⚠️

  • Contradiction: Non-creator copy is confirmed (:1454-1466). The mask paragraph covers only the creator case. Per normalize_template_docker_pass, a non-creator sending the mask gets both credentials set to None, and a creator sending the mask for a field with no stored value gets 400.
  • Edge case: "Only the template's creator can do this" is accurate but incomplete.
  • Failure mode: None beyond omission. Assumption: see first bullet.

C11 — CLI/SDK reference matches shipped tools ⚠️

  • Contradiction: The pages are regenerated from the unmerged branch @8cbfc299, which uses /api/v1/template/ (vast.py:7737). The epilog prose is not on CLI master; flags are unchanged. The --disk to --disk_space example fix is unrelated but correct.
  • Edge case: "Send the full template" is unclear for CLI users, who pass flags and get None or defaults for unpassed ones.
  • Failure mode: Docs publish before the CLI release and describe behavior the released CLI lacks. The PR's rollout note covers this.
  • Assumption: Generated pages could be overwritten by a later regeneration; the generator was not examined.

C12 — Sibling spec consistency ⚠️

  • Contradiction: create_template.yaml:125 says hash_id "Can be included when editing but will change based on new content". Under v1, hash_id is required and identifies the current version.
  • Edge case: None. Failure mode: minor reader confusion. Assumption: None.

C13 — Diff hygiene ✅

  • Contradiction: None. One put under the v1 path; editTemplate unique; remaining v0/template hits are GET/POST/DELETE.
  • Edge case: openapi.yaml renders the path without a trailing slash while the source yaml and backend route have one; the generator's existing convention (v0 rendered the same way).
  • Failure mode: None found. Assumption: None.

C14 — 401/429 ✅

  • Contradiction: None. ratelimitapimeth at :1370 and get_request_info_user_id(abort=True) at :1371.
  • Edge case: None. Failure mode: None. Assumption: None.

C15 — Rollout ordering ⚠️

  • Contradiction: The PR body states the ordering, but nothing gates the merge.
  • Edge case: A docs-first merge makes C1 and C11 false for the interval.
  • Failure mode: See C1 and C11. Assumption: The author coordinates the publish.

Cluster annotations
Staleness cluster [C3, C8, C11 — I=3 edges, D=1.0] chained → probe at the root: read both untouched guides at head, then the CLI branch to see what omitted flags send.
Error-contract cluster [C5, C6, C4 — I=3 edges, D=1.0] chained → probe at the root: trace from the raise site at templates.py:1414 to the catch-all at :1520.
Sequencing cluster [C1, C11, C15 — I=3 edges, D=1.0] chained → probe at the root: search backend and CLI repos for a 410 or a CLNT-754 branch (none found).

Operative Test

Could a wrong implementation accidentally satisfy this mesh?

  • Enforcement ⚠️: The docs have no tests of their own. The repo's CI (verify-openapi, Mintlify) checks YAML validity and rendering, not behavior. A documented-but-false 404 (C5) passes that CI. A missing regression test is not graded as a defect here, because the repo has no test-requirement spec. By inspection only; test execution is deferred to CI.
  • Dimensional Coverage ⚠️: WHY (the 410 intent) and WHERE (all sibling pages) are reached after the consumer sweep. HOW is partial: no-edit side effects, hash-affecting inputs and the edit-then-defeature order are not all documented. WHEN (backend-before-docs ordering) is named but not enforced.
  • Detectability ❌ (docs sense): A wrong status or error body in the OpenAPI reference produces no failing check, and the backend has no v1 404 assertion either, so neither side would flag Issue Fix redirect #2.
  • Domain-Risk (Performance/Security) N/A: no Domain-Risk:-tagged spec exists in this repo.

4. Implementation / Constraint Analysis

Input from Step 8 (QA) + Step 9 (Deep Spec Audit) + Step 9.1 (Portability) + AC Satisfaction cross-refs.

Severity Spread: Critical: 0 | Major: 2 | Minor: 10

Issues Found:

# Severity Description Location Source C_X
1 Major (in-scope) The CLI and SDK guides still instruct "include only what you want to change". The example sends only --desc and --disk_space (or name/onstart_cmd for the SDK). Under v1, which does not carry omitted fields over, the CLI branch sends null name and image, and validate_template_params accepts them. The guides also contradict the regenerated reference pages in this same PR. The SDK guide signature (HASH_ID, disk, -> str) is out of step with the regenerated SDK reference (hash_id, disk_space, -> dict). cli/templates.mdx:198-206; sdk/python/templates.mdx:252-262, 286-297 C3
2 Major (in-scope) The documented v1 404 (invalid_template, "error 404: Template not found") cannot reach clients. HTTPNotFound is raised inside a try whose except Exception rewraps it as 400 with error "HTTPNotFound" and the exception text. This hits exactly the unknown-id, deleted and id/hash-mismatch cases the docs describe. Either document the actual 400 body, or hold the 404 text until the backend returns a real 404. Reasoned from source, not run. edit_template.yaml '404' block (:183-199); openapi.yaml put '404' block (~:4160-4177); backend templates.py:1412-1418 vs :1515-1523 C5
3 Minor "PUT /api/v0/template/ is deprecated and returns 410 Gone" is written in the present tense, but no backend 410 exists on origin/master or any found branch. It holds only after the backend change lands, which the PR's own rollout note puts last. The v0 operation is also removed from openapi.yaml with no 410 response spec for the deprecated path. guide mdx:361; openapi.yaml:3985-3986; edit_template.yaml:19 C1, C15
4 Minor "Fields you leave out are not carried over" overclaims. recommended, autoscaler, sort_order and vm are always copied from the old row, and omitted tags are kept. tags is accepted by the backend but missing from the request schema. edit_template.yaml:13, 32-126; openapi.yaml:3966-3968; guide mdx:289 C8
5 Minor "Immutable / the previous version keeps its identifiers" omits the creator-edit side effects: the previous version is set to recommended=False, autoscaler=False, vm=False, sort_order=None, so it leaves featured listings. The editor's own link to the previous version is also affected. The ticket called out v0 clearing the recommended flag. edit_template.yaml:13; openapi.yaml:3964-3972; guide mdx:289 C7
6 Minor The 200 schema omits the top-level hash_id returned on the no-edit path. "template: The new version" is actually the unchanged current version on that path. The template object also carries tags and all fields. edit_template.yaml:141-164; openapi.yaml:4110-4130 C9
7 Minor "A body that hashes to the current hash_id creates nothing" is slightly off. The no-edit path can still add a user link for a caller with no relationship and reconcile tags for the creator. guide mdx:355-357; edit_template.yaml:15; openapi.yaml ~:3975-3977 C9
8 Minor The credential-mask paragraph covers only the creator case. A non-creator sending the mask has both credentials set to None, and a creator sending the mask for a field with no stored value gets 400 invalid_args. edit_template.yaml:17; openapi.yaml:3979-3981 C10
9 Minor The 400 description is incomplete: docker-username-without-token, length-limit invalid_params, unknown key "Invalid Column Names", mask-placeholder 400 and the rewrapped not-found are not listed. The example shows only the missing-id message, while a missing hash_id returns a different message. edit_template.yaml:165-181; openapi.yaml:4131-4146 C6
10 Minor The CLI and SDK reference pages are regenerated from the unmerged CLI branch @8cbfc299, and the new epilog prose is not on CLI master. The reference says "send the full template", which is unclear for CLI users who pass flags (unpassed flags go as null or defaults). It also omits the no-op and non-creator-copy cases. Publishing before the CLI release describes behavior the shipped CLI lacks. cli/reference/update-template.mdx:104-111; sdk/python/reference/update-template.mdx:6 C11, C15
11 Minor tag "can also be included in the image field" reads as equivalence, but the hash is computed on raw params. image: "x:latest" and image: "x" + tag: "latest" hash differently, so resubmitting in the other form creates a new version instead of the documented no-edit result. edit_template.yaml:52-54; guide Note mdx:356 C9
12 Minor Stale cross-reference: create_template.yaml says hash_id "can be included when editing but will change based on new content". Under v1, hash_id is required and identifies the current version. api-reference/openapi/yaml/create_template.yaml:125 C12

Out-of-scope follow-ups (never block this PR; carried at true severity):

# Severity Description Location Source C_X
13 Note (out-of-scope) The ticket also asks for internal documentation updates and a frontend switch to v1. The PR covers public docs only. No frontend branch or commit tagged for the ticket was found locally. Jira CLNT-754 checklist C3

Withdrawn on evidence:

  • Identifier tables in the CLI and SDK guides listing id as deleting-only: false positive. The CLI update command takes only hash_id and resolves the numeric id itself via a lookup (vast.py:7738-7765), and the SDK method takes only HASH_ID.
  • Guide Identifiers table hash_id row: stays true, since edit uses id and hash_id together.
  • On-disk CLI still calling the v0 route: folded into Issue regen openapi.json from combined-api.yaml #10; the branch at @8cbfc299 moves to /api/v1/template/, so the on-disk copy was stale.
  • additionalProperties: true, trailing slash, example inconsistencies and unverified backend claims: kept as Notes in section 7; none is a wrong claim in the diff.

AC Satisfaction:

  • AC1 — FE replace with v1: not_in_scope — separate repository; a branch and log sweep of the frontend repo found no tracked work for this ticket (only names searched).
  • AC2 — API docs replace with v1: ⚠️ partial — C2 and C4 hold for the API reference and guide (verify-openapi and Mintlify checks green on the head). C3, C5 and C6 show the replacement is incomplete (Issues Token #1 and Fix redirect #2).
  • AC3 — Deprecate the endpoint with an error message pointing to the new one: ⚠️ partial — the docs state the 410 and the pointer (C1), but the backend change does not exist yet on origin/master or any found branch. Deferred: backend 410, sequenced by the PR's rollout note.
  • AC4 — Update public-facing docs to remove references to the deprecated endpoint: ❌ gap — the CLI and SDK guides still describe the old partial-update behavior (C3, Issue Token #1).
  • AC5 — Update internal documentation: not_in_scope — not in this public docs repo; not checked elsewhere.

Test-citation note: this diff touches .mdx and .yaml, not test files. The repo's CI checks (verify-openapi, Mintlify preview) are the only automated evidence.

Deep Spec Audit: 0 specs verified · 0 violations · sibling-Requirement sweep: 0 amended specs, 0 cross-Requirement contradictions

  • (none): this repo has no openspec/specs/. ✅ examined: OpenAPI sibling-spec consistency (edit and create yaml), operationId uniqueness, generator path rendering, nav slug resolution. ⬜ not examined: docs.json navigation beyond slug resolution; the generator's behavior on regeneration.

Execution Tracing:

  • State transitions verified: Yes — traced update_template_v1 from validate through hash, existence/deleted/hash check, no-edit path, non-creator copy and creator insert with de-feature of the old row (templates.py:1366-1523).
  • Command/API semantics validated: Yes — the exception order that turns HTTPNotFound into a 400 (:1412-1418, :1515-1523), re-read directly; and the CLI branch's request body for omitted flags.
  • Environment assumptions documented: Partial — Pyramid exception semantics assumed from its documented hierarchy; not run.

Contradiction Analysis: 2 in-scope contradictions between the docs and traced source (C3, C5), plus 10 smaller accuracy gaps, across 15 constraints × 4 attack vectors = 60 cells checked.

Ecosystem Impact: Blast radius is the 2 untouched guides (CLI, SDK), the untouched create_template.yaml, the regenerated CLI and SDK reference pages, and clients that migrate to v1. Backend v1 and the CLI branch are the cross-repo boundaries; both were read.

Quality Standards: No governing spec exists in this repo. The new prose is dense and follows the existing style. Two sibling pages and one sibling spec were left unreconciled (Issues #1, #12).

5. Richness Score

Input from Step 9.5.

Richness: ●●●●●●●○ (Source · Q · C · Seq · Cond · Arch · Sem · Coverage)

  • Source Span ●: Intent (ticket checklist), Law (sibling-spec and generator conventions) and Actuality (diff) are all represented.
  • Quantitative ●: counts checked (one put and one editTemplate at head, 5 files, 15 constraints against 60 cells).
  • Causal ●: the raise-to-rewrap mechanism for the 404, and the edit-then-defeature mechanism.
  • Sequential ●: validate, hash, existence check, no-edit exit, copy or insert order; and the docs-before-backend rollout order.
  • Conditional ●: creator vs non-creator, no-edit vs edit, mask with and without a stored value.
  • Architectural ●: docs, API reference, CLI and SDK pages, and the backend and CLI repos as one contract.
  • Semantic ●: label-versus-computation checks on "not carried over", "creates nothing", "new version" and "returns 410".
  • Coverage ○: guides/templates/* swept by grep only, docs.json and the generator not read, vast-frontend not inspected.

6. Recommendation

Input from Section 4 (Severity Spread) + Section 5 (Richness).

VERDICT: REQUEST CHANGES

🛑 REQUEST CHANGES — Two in-scope Majors: the CLI and SDK guides still teach a partial-update example that now corrupts a template (Issue #1), and the documented 404 cannot reach clients as written (Issue #2).

To approve, the author should:

  1. Issue Token #1 (Major): update the Edit a Template sections in cli/templates.mdx and sdk/python/templates.mdx. Replace "include only what you want to change" and the partial examples with full-template examples, and align the SDK signature block with the regenerated reference. Check that the new CLI and SDK examples pass every field they intend to keep, as the regenerated reference now says.
  2. Issue Fix redirect #2 (Major): either change the 404 block in edit_template.yaml and the regenerated openapi.yaml to the actual response (400 with error HTTPNotFound), or hold the 404 text until the backend returns a real 404. Check by sending a PUT with a deleted or mismatched id/hash_id against the backend and comparing the status and body to the documented block, or ask the backend owner to confirm.

Optional:

7. Notes for Author

  • Rendering: the generator drops the trailing slash on the v1 path. The API reference shows PUT /api/v1/template while the prose and the backend route have the trailing slash. The v0 path was rendered the same way before, so this is the existing convention.
  • Unknown request keys: the schema keeps additionalProperties: true, but the backend drops unknown keys only after computing the hash. A body with an unknown key therefore gets a different hash_id and cannot hit the no-edit path. Consider one sentence on this.
  • Examples: the OpenAPI example uses recommended_disk_space: 16 and vastai/base-image, while the guide uses 64 and vllm/vllm-openai. Cosmetic, but one set would read more consistently.
  • Backend claims in the new prose that held when traced: required id and hash_id, non-creator copy, creator-only mask retention, the 429 rate limit and the no-edit message.
  • Rollout: the CLI and SDK reference pages describe the unmerged branch @8cbfc299. Keep the publish-with-the-CLI-release ordering in the PR body.

Generated by Constraint Cycle 2.7.0

@madisonvast
madisonvast merged commit 4bf00bb into main Oct 21, 2026
2 checks passed

This branch was successfully deployed

1 active deployment
staging — 35111dc2 Deployed Oct 20, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants