Connecting a token that lacks a scope names the scope, and the token form lists what a token needs #70
No reviewers
Labels
No labels
agent-work
agent-working
ultracode
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
trevato-apps/forge!70
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "tdobbertin-espo/forge:fix/token-scope-words"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Forgejo and Gitea answer a token that lacks a required scope with 403 and a body that names the scope:
token does not have at least one of required scope(s): [read:user]. The API client mapped every 403 to "the token may not do that on the origin" and did not read the body. Connect then said "That token was refused by the origin". That is the same sentence for a wrong token, an expired token and a narrow token, so a person could not tell which one they had. A narrow token is the usual case: Forgejo's token page asks for each scope, and a forge's whoami needs User: Read.ApiClientnow reads the body of a 403 (4 KB at most) and keeps only the words that look like scopes (missingScopes). Nothing else from the origin goes into a message. The failure carriesmissingScopes, and its message names them as Forgejo's token page does (scopeWords): "the token is missing User: Read". Sync errors say so too, for example a label import without the issue scope.Connecting with such a token answers
missing_scopes(422) with "This token is missing User: Read." and what a token needs.connectRefusalgives the API and the web form one code and one sentence for each refused connect. An OAuth grant that lacks a scope says so, instead of "the new token did not work".The token form lists what a Forgejo or Gitea token needs: User: Read; Repository: Read and write; Issue: Read and write; nothing else. When the instance is known, it links to Forgejo 15's
/user/settings/applications/tokens/newwith the name and the scopes already chosen. Gitea and older Forgejo get the list only.A token with all its scopes, a wrong token and an expired token behave as before. Every other refused connect keeps its code and its sentence.
connectOrigin's error is nowConnectError | ScopeRefusal, so seven test call sites that didnew Error(connected.error)now stringify it.Tests
bun 1.3.13, a scrubbed environment (no agent variables):
test/origin-token-scopes.test.ts: 5 pass, 0 fail: the body parser (a matching body, an unrelated body, junk inside the brackets), the scope words, connect and the API refusing a token withoutread:userwith nothing stored, and the form's list and link.test/fake-origin.tsgainsuserScopeMissing, which answers/useras Forgejo does.bun test --timeout 60000call: 431 pass, 0 fail across 32 files.bun scripts/gate.tsandtsc --noEmit: clean.the 32 files
origin-token-scopes, origins, origins-oauth, origins-operator, origins-reconnect, origins-security-auth, origins-security-provider, origins-security-push, origins-sync, origins-sync-settled, web-origins, web-origin-link, mcp-origins, mcp-origin-apps, push-through, trusted-hosts, trusted-hosts-ui, steps-lists, no-polling, refresh-meta, mirror-outbound, mirror-out, carried, migrate, migrate-after, tui-migrate, apps-feedback-mirror, and the five cross files reserved-names, studio, shards, check-list, hollow (each
test/<name>.test.ts).🤖 Generated with Claude Code
View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.