Skip to content

Adopt canonical unversioned API paths across SDKs - #49

Open
rkdud007 wants to merge 11 commits into
mainfrom
rkdud007/canonical-api-paths
Open

Adopt canonical unversioned API paths across SDKs#49
rkdud007 wants to merge 11 commits into
mainfrom
rkdud007/canonical-api-paths

Conversation

@rkdud007

@rkdud007 rkdud007 commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

for human reviewer: tldr, we def have newer version of api format that is /api/repos/{repo_name}/... which seem to be sdk is pretty staled from it - like it still calls /api/v1. im just trying to fix this

===========

Summary

The gateway serves every operation on canonical /api/repos/{repo_name}/... routes and marks the /api/v1 family deprecated (it auto-generates canonical aliases and emits deprecation pointers). This PR moves all three SDKs and the agent skill onto the canonical paths.

Behavior

  • Fetchers base requests at /api (previously /api/v{version}); repo-scoped calls embed the repository id as one percent-encoded path segment (owner/repoowner%2Frepo).
  • findOne / deleteRepo (and language equivalents) address repos/{id} instead of repo / repos/delete.
  • commit-pack and diff-commit streaming transports use the repo-scoped URLs.
  • Wire-shape deltas required by the canonical contract:
    • delete tag → DELETE repos/{id}/tags/{tag} with no request body;
    • create git credential → repos/{id}/git-credentials with repo_id dropped from the body.
  • Deliberate exception: update/delete git credential stay pinned to the legacy /api/v1/repos/git-credentials route — their options don't carry the repo name the canonical path requires. Migrating them is a public-API change (adding a repo identifier to the options) left for a follow-up. Hardcoded v1 in all three SDKs, with comments.
  • apiVersion / api_version / APIVersion options are deprecated and fully inert; they no longer affect request URLs.
  • skills/code-storage/SKILL.md: CODE_STORAGE_BASE_URL drops /v1, new REPO_NAME variable (URL-encoded single segment), all endpoint tables, section headers, and curl examples rewritten; a note records that legacy /api/v1 paths remain served but deprecated.

Public method signatures are unchanged in all three packages; no version bump (release separately). Legacy routes remain served by the backend, so previously released SDK versions keep working.

The backend serves every operation on canonical /api/repos/{repo_name}
routes and has deprecated the /api/v1 family. The SDK now emits the
canonical paths: the fetcher bases requests at /api, repo-scoped calls
embed the percent-encoded repository id in the path, findOne and
deleteRepo address repos/{id}, and the commit-pack and diff-commit
transports take the repo-scoped URL. Public method signatures are
unchanged.

Two operations change wire shape to match the canonical contract:
deleteTag sends DELETE repos/{id}/tags/{tag} with no body, and
createGitCredential drops repo_id from the body because the path
carries the repository. updateGitCredential and deleteGitCredential
stay pinned to the legacy v1 route because their options do not carry
the repo name the canonical path requires.

The apiVersion option is deprecated and inert; it no longer affects
request URLs. Legacy paths remain served by the backend, so previously
released SDK versions keep working.
The backend serves every operation on canonical /api/repos/{repo_name}
routes and has deprecated the /api/v1 family. The SDK now emits the
canonical paths through one build_api_url helper: repo-scoped calls
embed the percent-encoded repository id, find_one and delete_repo
address repos/{id}, and the commit transports use the repo-scoped
URLs. Public method signatures are unchanged.

Two operations change wire shape to match the canonical contract:
delete_tag sends DELETE repos/{id}/tags/{tag} with no body, and
create_git_credential drops repo_id from the body because the path
carries the repository. update_git_credential and
delete_git_credential stay pinned to the legacy v1 route because
their options do not carry the repo name the canonical path requires.

The api_version option is deprecated and inert; it no longer affects
request URLs. Legacy paths remain served by the backend, so previously
released SDK versions keep working.
The backend serves every operation on canonical /api/repos/{repo_name}
routes and has deprecated the /api/v1 family. The SDK now emits the
canonical paths: the fetcher bases requests at /api, repo-scoped calls
go through a repos/{PathEscape(id)} helper, FindOne and DeleteRepo
address repos/{id}, and the commit-pack and diff-commit transports use
the repo-scoped URLs. Public method signatures are unchanged.

Two operations change wire shape to match the canonical contract:
DeleteTag sends DELETE repos/{id}/tags/{tag} with no body, and
CreateGitCredential drops repo_id from the body because the path
carries the repository. UpdateGitCredential and DeleteGitCredential
stay pinned to the legacy v1 route because their options do not carry
the repo name the canonical path requires.

Options.APIVersion is deprecated and inert; it no longer affects
request URLs. Legacy paths remain served by the backend, so previously
released SDK versions keep working.
Rewrite the code-storage agent skill for the canonical
/api/repos/{repo_name} routes: CODE_STORAGE_BASE_URL drops the /v1
segment, a REPO_NAME variable carries the repository name as one
URL-encoded path segment, and every endpoint table row, section
header, and curl example uses the canonical shape.

Operations whose canonical contract moved identifiers into the path
are updated accordingly: get/delete repository at repos/{repo_name},
tag deletion at tags/{tag_name} with no body, and git credentials at
git-credentials/{git_credential_id} with identifiers dropped from
request bodies. A note records that legacy /api/v1 paths remain
served but are deprecated.
update_git_credential and delete_git_credential deliberately stay on
the legacy versioned route, but their URLs still interpolated the
deprecated api_version option, so a caller setting api_version=2
would request /api/v2/... and fail. Hardcode /api/v1 the way the
TypeScript and Go SDKs do, keeping api_version fully inert.
@rkdud007

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T01:03:53.749417Z b721f91 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 877398c709

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/code-storage-typescript/src/index.ts
Comment thread packages/code-storage-typescript/src/diff-commit.ts
Comment thread skills/code-storage/SKILL.md
Updating or deleting a git credential fails against the current
backend with 404 "repository not found": both methods mint a token
with the placeholder org repo claim, and the backend now resolves
that claim to a repository on the legacy route. The failure was
reproduced live; the same requests succeed with a repo-scoped token.

Add an optional repoId to UpdateGitCredentialOptions and
DeleteGitCredentialOptions. When set, the SDK mints the repo-scoped
token and calls the canonical
repos/{repo}/git-credentials/{credential} route (verified live:
update 200, delete 204). When omitted, the previous legacy request is
sent unchanged for compatibility with older backends, and the option
docs state the current backend requires repoId.
update_git_credential and delete_git_credential fail against the
current backend with 404 "repository not found": both mint a token
with the placeholder org repo claim, and the backend now resolves
that claim to a repository on the legacy route.

Add an optional repo_id keyword to both methods. When set, the SDK
mints the repo-scoped token and calls the canonical
repos/{repo}/git-credentials/{credential} route, sending no body on
delete. When omitted, the previous legacy request is sent unchanged
for compatibility with older backends, and the docstrings state the
current backend requires repo_id.
UpdateGitCredential and DeleteGitCredential fail against the current
backend with 404 "repository not found": both mint a token with the
placeholder org repo claim, and the backend now resolves that claim
to a repository on the legacy route.

Add an optional RepoID field to both option structs. When set, the
SDK mints the repo-scoped token and calls the canonical
repos/{repo}/git-credentials/{credential} route, sending no body on
delete and omitting the body id on update. When unset, the previous
legacy request is sent unchanged for compatibility with older
backends, and the field docs state the current backend requires
RepoID.
@rkdud007

rkdud007 commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator Author

Live verification performed against the production pierre tenant

Full workflow smoke (tests/full-workflow.js -e production -s pierre) — all steps passed on the canonical paths: createRepo, commit-pack ×3, diff-commit, listBranches/Commits/Files, grep ×3, getCommitDiff, getFileStream, feature branch, restoreCommit.

Targeted contract smoke (built dist, throwaway repos, all cleaned up):

  • findOne via GET /api/repos/{id}
  • tag create/list, then DELETE /api/repos/{id}/tags/release%2Fv1.0.0 with no body ✓ (encoded slash)
  • createGitCredential with the body repo_id dropped ✓
  • deleteRepo via DELETE /api/repos/{id}

Found and fixed a pre-existing bug (broken on main and all released versions, surfaced by the live run): update/delete git credential mint an org repo claim, and the backend now resolves that claim to a repository on the legacy route → 404 "repository not found". The last three commits add an optional repoId/repo_id/RepoID to those options; when set, the SDK uses the canonical repos/{repo}/git-credentials/{credential} route with a repo-scoped token — verified live (update 200, delete 204). When omitted, the previous legacy request is preserved for older backends.

The restoreCommit and createCommitFromDiff rules named the
repos/restore-commit and repos/diff-commit paths from the /api/v1 era.
The backend now serves those operations canonically at
repos/{repo_name}/restore-commit and repos/{repo_name}/diff-commit and
marks the /api/v1 family deprecated, so the literal old paths only
exist behind the deprecated prefix.

Owner-approved rule update accompanying the canonical-path migration:
name the canonical repo-scoped routes and keep the clause forbidding
automatic fallback to the legacy endpoints.
The credential section documents the canonical repo-scoped update and
delete routes, but the SDKs can only build those routes when the
caller passes the repository identifier; without it they fall back to
the deprecated legacy request the current backend rejects. Record
that requirement next to the endpoint documentation so agent-facing
docs match what the SDKs send.
@rkdud007

Copy link
Copy Markdown
Collaborator Author

AGENT.MD was also outdated

@rkdud007

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1f4387efd6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread skills/code-storage/SKILL.md
Following a procedure recipe after the environment setup left
REPO_NAME pointing at the setup placeholder while the recipe minted
its token for another repository; canonical routes require the path
segment to match the JWT repo claim, so the recipe requests would be
rejected. Export REPO_NAME next to each recipe's token mint, with the
fork recipe demonstrating slash encoding.
@rkdud007

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: b721f91c9e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@notion-workspace

Copy link
Copy Markdown

@necolas necolas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for moving these calls to the canonical routes. I left three focused comments on the credential contract. The version bump and combined changelog can stay in a separate release PR after #47, #49, and the related SDK work.

const resp = await this.api.post(
{ path: 'repos/git-credentials', body },
{
path: `repos/${encodeURIComponent(options.repoId)}/git-credentials`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use repoName here instead of repoId? PR #47 exposes repoId as the internal ID and repoName as the public name. This route and the JWT repo claim require the public name, so a caller who passes repo.repoId gets a 404. Please make the same change in Python and Go.

* canonical repo-scoped route. The current backend resolves the repository
* from the token, so omitting this is not compatible with it.
*/
repoId?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make this a required repoName (repo_name / RepoName) and remove the legacy fallback? The current backend rejects requests without a repository name, and the migration plan says not to keep /api/v1/*. Please apply the same rule to delete, Python, and Go. Monorepo PR pierredotco/monorepo#2397 can then document the required name after this SDK change lands.


`username` is optional for token-only providers. A repository can have one stored Git credential.
GitHub App sync does not use this endpoint.
SDK callers must pass the repository identifier (`repoId` / `repo_id` / `RepoID`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we call this the repository name and use repoName / repo_name / RepoName? “Repository identifier” can also mean the deprecated internal repo_id. The canonical route needs repo_name; once the field is required, this fallback note can go too.

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.

2 participants