Conversation
c1i auth login can restrict the personal client it mints. The first interactive browser login to a tenant asks whether to keep all roles or choose; --choose-roles shows a menu of live roles after approval (one or more, or 0 for full permissions), and --scoped-role passes ids through for scripts. --display-name names the credential. Login states the resulting scope and names the credential a re-login leaves unrevoked. The device-flow token may only create a personal client, so the menu reads roles with a short-lived helper credential that is deleted on every exit path, including Ctrl-C, before the scoped one is created. The menu offers the union of C1.ai's personal-client and MCP-consent role pickers. Also: c1i roles list/get; verify new logins with auth/introspect, which a narrowly scoped credential can still call; client.NewWithCredentials (an in-memory-reused, never-cached bearer); keychain.StoredClientID; every login prompt now honors Ctrl-C. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A value that isn't a role id is matched by name, display name or a normalized form (basic-user, Basic User, system:user) against the tenant's roles, read with the same temporary credential as the menu. A miss or an ambiguous name is a usage error listing the choices, before the credential is created; ids alone still pass straight to the server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Match in tiers (id, then name, then display name) so a display name can't make a role's own name ambiguous; label duplicate display names with ids in errors and the scope line; dedupe bare ids; show the 404 hint only when ids went to the server unchecked; document the id format and mixed-input check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
c1i auth logincan now scope the personal client it mints to chosen roles (IGA-4372), with no server change.--choose-roles: after browser approval, a menu of live roles. Pick one or more, or0for full permissions. A blank answer re-prompts, so a stray Enter can't widen the scope.--scoped-role <role>(repeatable): for scripts, by ID or by name (basic-user,Basic User,system:user). IDs alone pass straight to the server (unknown →404plus a hint). With any name, every value is resolved against the tenant's roles: exact ID first, then the role's name, then its display name. A miss or an ambiguous name is a usage error that lists the choices, before your credential is created.--display-namenames the credential.c1i roles list/c1i roles get.Why a temporary helper credential
Verified live: the device-flow access token may only create a personal client. Introspect, roles, users and listing personal clients all return
403.PersonalClientService.Updatesilently ignoresscopedRoles. So the menu works like this:c1i login role lookup (temporary).If the delete fails, login warns with the helper's id.
Role set
The menu offers the union of C1.ai's two web pickers:
profile/personal-clients/list/create.tsx): API-only roles, Basic User, Read-Only Administrator.profile/ai-connections/approve.tsx): the roles you hold, or every role for a super or read-only administrator.Other changes
GET /api/v1/auth/introspect, notPOST /api/v1/search/users. A narrowly scoped credential gets 403 on user search (verified live), which used to make login reject and delete it.client.NewWithCredentials: the REST client for credentials that are never stored. Its token is reused in memory and never cached on disk.keychain.StoredClientID: the stored client id, ignoring env credentials.Review
Three independent adversarial reviews (design, code, help/docs; DRY included), then two re-review rounds on the fixes. Main issues found and fixed:
Test plan
go build,go vet,golangci-lint(0 issues),gosec,gitleaks,go mod tidy(clean tree)go test -count=1 -shuffle=on×3403 Apps.Create.--scoped-rolewith a bogus id, no TTY:404plus hint, exit 4, nothing stored.--scoped-role basic-user, no TTY: credential scoped to Basic User, helper deleted.basic-usr: exit 2 listing all roles, nothing stored.Follow-ups that need C1 server changes (EPD Triage)
PersonalClientService.Updatesilently dropsscopedRoles, and Create skips the delegation check.🤖 Generated with Claude Code