Skip to content

Commit b95f794

Browse files
authored
Default --credential-auto to true when --credential-provider is set alone (#152)
## Summary - `kernel auth connections create --domain foo.com --credential-provider my-1p` currently builds a `CredentialReference` of `{ provider: "my-1p" }` with no `path` and no `auto` flag. The API accepts that as a valid-but-inert reference, so the managed auth session never fetches credentials and dead-ends in `awaiting_input` (user gets prompted for manual input). - Default `auto: true` in that branch to match the dashboard's UX ([create-managed-auth-dialog.tsx](https://github.com/kernel/kernel/blob/main/packages/dashboard/src/components/create-managed-auth-dialog.tsx)), where picking a provider without a specific item always means "look up by domain". - Explicit `--credential-path` still pins the reference (no implicit auto). Explicit `--credential-auto` is now redundant but still honored. - Update the help text to document the new default. Companion API/workflow fix: kernel/kernel#1794 — without that PR, even a correctly-sent `auto: true` is ignored by the CUA managed auth path. ## Test plan - [x] `go build ./...` - [x] `go test ./cmd/ -count=1` (full suite passes; 4 new focused cases) - [x] New cases pin all four branches: - `--credential-provider` alone → `auto: true` defaulted - `--credential-provider` + `--credential-path` → no implicit auto - `--credential-provider` + `--credential-auto` → auto honored - `--credential-name` → unaffected by auto default - [ ] Smoke: against staging, run `kernel auth connections create --domain google.com --profile-name pn --credential-provider my-1p` and confirm the resulting connection resolves credentials without prompting. Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small CLI request-mapping change with targeted tests; primary risk is a behavior change for users who previously relied on provider-only meaning “no lookup,” which is unlikely/intended to be inert anyway. > > **Overview** > Fixes `kernel auth connections create` so that providing `--credential-provider` without `--credential-path` implicitly sets `credential.auto=true`, avoiding a valid-but-inert credential reference that would stall managed auth sessions. > > Updates the `--credential-auto` flag help text to document the new default, and adds focused regression tests covering provider-only, provider+path, explicit `--credential-auto`, and `--credential-name` branches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 39c0423. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent f83a233 commit b95f794

2 files changed

Lines changed: 125 additions & 1 deletion

File tree

cmd/auth_connections.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@ func (c AuthConnectionCmd) Create(ctx context.Context, in AuthConnectionCreateIn
151151
}
152152
if in.CredentialPath != "" {
153153
params.ManagedAuthCreateRequest.Credential.Path = kernel.Opt(in.CredentialPath)
154+
} else {
155+
// Default to domain auto-lookup when no explicit --credential-path is
156+
// given. This matches the dashboard's UX, where picking a provider
157+
// without a specific item always means "look up by domain". Without
158+
// this default, the server receives { provider } with no path or
159+
// auto flag, which is a valid-but-inert credential reference that
160+
// causes the managed auth session to never fetch credentials.
161+
params.ManagedAuthCreateRequest.Credential.Auto = kernel.Opt(true)
154162
}
155163
if in.CredentialAuto {
156164
params.ManagedAuthCreateRequest.Credential.Auto = kernel.Opt(true)
@@ -797,7 +805,7 @@ func init() {
797805
authConnectionsCreateCmd.Flags().String("credential-name", "", "Kernel credential name to use")
798806
authConnectionsCreateCmd.Flags().String("credential-provider", "", "External credential provider name")
799807
authConnectionsCreateCmd.Flags().String("credential-path", "", "Provider-specific path (e.g., VaultName/ItemName)")
800-
authConnectionsCreateCmd.Flags().Bool("credential-auto", false, "Lookup by domain from the specified provider")
808+
authConnectionsCreateCmd.Flags().Bool("credential-auto", false, "Lookup by domain from the specified provider (defaults to true when --credential-provider is set without --credential-path)")
801809
authConnectionsCreateCmd.Flags().String("proxy-id", "", "Proxy ID to use")
802810
authConnectionsCreateCmd.Flags().String("proxy-name", "", "Proxy name to use")
803811
authConnectionsCreateCmd.Flags().Bool("no-save-credentials", false, "Disable saving credentials after successful login")

cmd/auth_connections_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,122 @@ func TestAuthConnectionsList_JSONOutput_PrintsRawResponse(t *testing.T) {
205205
assert.Contains(t, out, "\"raf-leaseweb\"")
206206
}
207207

208+
// Regression test for the 1Password auto-lookup UX gap: before this fix,
209+
// `kernel auth connections create --credential-provider foo` sent a
210+
// CredentialReference of { provider } with no auto flag, which the API accepted
211+
// as valid-but-inert — the managed auth session would never fetch credentials
212+
// and would prompt the user for manual input. The dashboard already defaults
213+
// to auto: true for this case (see packages/dashboard/src/components/create-managed-auth-dialog.tsx);
214+
// the CLI now matches that UX.
215+
func TestAuthConnectionsCreate_ProviderWithoutPath_DefaultsAutoTrue(t *testing.T) {
216+
var captured kernel.AuthConnectionNewParams
217+
fake := &FakeAuthConnectionService{
218+
NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) {
219+
captured = body
220+
return &kernel.ManagedAuth{ID: "conn-new"}, nil
221+
},
222+
}
223+
224+
c := AuthConnectionCmd{svc: fake}
225+
err := c.Create(context.Background(), AuthConnectionCreateInput{
226+
Domain: "google.com",
227+
ProfileName: "my-profile",
228+
CredentialProvider: "my-1p",
229+
Output: "json",
230+
})
231+
require.NoError(t, err)
232+
233+
cred := captured.ManagedAuthCreateRequest.Credential
234+
require.True(t, cred.Provider.Valid())
235+
assert.Equal(t, "my-1p", cred.Provider.Value)
236+
assert.False(t, cred.Path.Valid(), "path should not be set when only --credential-provider is given")
237+
require.True(t, cred.Auto.Valid(), "auto should default to true when provider is set without path")
238+
assert.True(t, cred.Auto.Value)
239+
}
240+
241+
// Explicit --credential-path should keep the credential reference as a pinned
242+
// path lookup (no implicit auto).
243+
func TestAuthConnectionsCreate_ProviderWithPath_DoesNotSetAuto(t *testing.T) {
244+
var captured kernel.AuthConnectionNewParams
245+
fake := &FakeAuthConnectionService{
246+
NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) {
247+
captured = body
248+
return &kernel.ManagedAuth{ID: "conn-new"}, nil
249+
},
250+
}
251+
252+
c := AuthConnectionCmd{svc: fake}
253+
err := c.Create(context.Background(), AuthConnectionCreateInput{
254+
Domain: "google.com",
255+
ProfileName: "my-profile",
256+
CredentialProvider: "my-1p",
257+
CredentialPath: "Employees/Google Workspace",
258+
Output: "json",
259+
})
260+
require.NoError(t, err)
261+
262+
cred := captured.ManagedAuthCreateRequest.Credential
263+
require.True(t, cred.Provider.Valid())
264+
assert.Equal(t, "my-1p", cred.Provider.Value)
265+
require.True(t, cred.Path.Valid())
266+
assert.Equal(t, "Employees/Google Workspace", cred.Path.Value)
267+
assert.False(t, cred.Auto.Valid(), "auto should remain unset when --credential-path is explicit")
268+
}
269+
270+
// --credential-auto should still be honored (it was a no-op redundant flag
271+
// before the default changed, but callers may pass it for clarity).
272+
func TestAuthConnectionsCreate_ProviderWithExplicitAuto_SetsAuto(t *testing.T) {
273+
var captured kernel.AuthConnectionNewParams
274+
fake := &FakeAuthConnectionService{
275+
NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) {
276+
captured = body
277+
return &kernel.ManagedAuth{ID: "conn-new"}, nil
278+
},
279+
}
280+
281+
c := AuthConnectionCmd{svc: fake}
282+
err := c.Create(context.Background(), AuthConnectionCreateInput{
283+
Domain: "google.com",
284+
ProfileName: "my-profile",
285+
CredentialProvider: "my-1p",
286+
CredentialAuto: true,
287+
Output: "json",
288+
})
289+
require.NoError(t, err)
290+
291+
cred := captured.ManagedAuthCreateRequest.Credential
292+
require.True(t, cred.Auto.Valid())
293+
assert.True(t, cred.Auto.Value)
294+
}
295+
296+
// --credential-name references a Kernel-managed credential and should never
297+
// carry a provider/auto/path — the default-auto logic must not kick in here.
298+
func TestAuthConnectionsCreate_CredentialName_UnaffectedByAutoDefault(t *testing.T) {
299+
var captured kernel.AuthConnectionNewParams
300+
fake := &FakeAuthConnectionService{
301+
NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) {
302+
captured = body
303+
return &kernel.ManagedAuth{ID: "conn-new"}, nil
304+
},
305+
}
306+
307+
c := AuthConnectionCmd{svc: fake}
308+
err := c.Create(context.Background(), AuthConnectionCreateInput{
309+
Domain: "google.com",
310+
ProfileName: "my-profile",
311+
CredentialName: "my-google-creds",
312+
Output: "json",
313+
})
314+
require.NoError(t, err)
315+
316+
cred := captured.ManagedAuthCreateRequest.Credential
317+
require.True(t, cred.Name.Valid())
318+
assert.Equal(t, "my-google-creds", cred.Name.Value)
319+
assert.False(t, cred.Provider.Valid())
320+
assert.False(t, cred.Auto.Valid())
321+
assert.False(t, cred.Path.Valid())
322+
}
323+
208324
func TestAuthConnectionsUpdate_MapsParams(t *testing.T) {
209325
var captured kernel.AuthConnectionUpdateParams
210326
fake := &FakeAuthConnectionService{

0 commit comments

Comments
 (0)