From 7a435c9c75ce3b91d45bfe1b36ad8b70ad4d1d72 Mon Sep 17 00:00:00 2001 From: rgarcia <72655+rgarcia@users.noreply.github.com> Date: Wed, 7 Oct 2026 20:07:46 +0000 Subject: [PATCH 1/3] Update the Go SDK to v0.121.0 and stop creating datacenter proxies --- cmd/proxies/check.go | 2 +- cmd/proxies/check_test.go | 4 +- cmd/proxies/common_test.go | 10 ++--- cmd/proxies/create.go | 11 +----- cmd/proxies/create_test.go | 78 ++++++++++++-------------------------- cmd/proxies/get.go | 2 +- cmd/proxies/get_test.go | 2 +- cmd/proxies/list.go | 2 +- cmd/proxies/proxies.go | 14 +++---- cmd/proxies/update_test.go | 2 +- go.mod | 2 +- go.sum | 2 + 12 files changed, 46 insertions(+), 85 deletions(-) diff --git a/cmd/proxies/check.go b/cmd/proxies/check.go index 7381446d..b313b250 100644 --- a/cmd/proxies/check.go +++ b/cmd/proxies/check.go @@ -94,7 +94,7 @@ func getProxyCheckConfigRows(proxy *kernel.ProxyCheckResponse) [][]string { config := &proxy.Config switch proxy.Type { - case kernel.ProxyCheckResponseTypeDatacenter, kernel.ProxyCheckResponseTypeIsp: + case "datacenter", kernel.ProxyCheckResponseTypeIsp: if config.Country != "" { rows = append(rows, []string{"Country", config.Country}) } diff --git a/cmd/proxies/check_test.go b/cmd/proxies/check_test.go index 82de52f4..1a94fcd3 100644 --- a/cmd/proxies/check_test.go +++ b/cmd/proxies/check_test.go @@ -17,7 +17,7 @@ func TestProxyCheck_ShowsBypassHosts(t *testing.T) { return &kernel.ProxyCheckResponse{ ID: id, Name: "Proxy 1", - Type: kernel.ProxyCheckResponseTypeDatacenter, + Type: "datacenter", BypassHosts: []string{"localhost", "internal.service.local"}, Status: kernel.ProxyCheckResponseStatusAvailable, }, nil @@ -45,7 +45,7 @@ func TestProxyCheck_PassesURL(t *testing.T) { return &kernel.ProxyCheckResponse{ ID: id, Name: "Proxy 1", - Type: kernel.ProxyCheckResponseTypeDatacenter, + Type: "datacenter", Status: kernel.ProxyCheckResponseStatusAvailable, }, nil }, diff --git a/cmd/proxies/common_test.go b/cmd/proxies/common_test.go index a7796e24..427e6b96 100644 --- a/cmd/proxies/common_test.go +++ b/cmd/proxies/common_test.go @@ -57,21 +57,21 @@ func (f *FakeProxyService) Get(ctx context.Context, id string, opts ...option.Re if f.GetFunc != nil { return f.GetFunc(ctx, id, opts...) } - return &kernel.ProxyGetResponse{ID: id, Type: kernel.ProxyGetResponseTypeDatacenter}, nil + return &kernel.ProxyGetResponse{ID: id, Type: "datacenter"}, nil } func (f *FakeProxyService) New(ctx context.Context, body kernel.ProxyNewParams, opts ...option.RequestOption) (*kernel.ProxyNewResponse, error) { if f.NewFunc != nil { return f.NewFunc(ctx, body, opts...) } - return &kernel.ProxyNewResponse{ID: "new-proxy", Type: kernel.ProxyNewResponseTypeDatacenter}, nil + return &kernel.ProxyNewResponse{ID: "new-proxy", Type: "datacenter"}, nil } func (f *FakeProxyService) Update(ctx context.Context, id string, body kernel.ProxyUpdateParams, opts ...option.RequestOption) (*kernel.ProxyUpdateResponse, error) { if f.UpdateFunc != nil { return f.UpdateFunc(ctx, id, body, opts...) } - return &kernel.ProxyUpdateResponse{ID: id, Name: body.Name, Type: kernel.ProxyUpdateResponseTypeDatacenter}, nil + return &kernel.ProxyUpdateResponse{ID: id, Name: body.Name, Type: "datacenter"}, nil } func (f *FakeProxyService) Delete(ctx context.Context, id string, opts ...option.RequestOption) error { @@ -85,7 +85,7 @@ func (f *FakeProxyService) Check(ctx context.Context, id string, body kernel.Pro if f.CheckFunc != nil { return f.CheckFunc(ctx, id, body, opts...) } - return &kernel.ProxyCheckResponse{ID: id, Type: kernel.ProxyCheckResponseTypeDatacenter}, nil + return &kernel.ProxyCheckResponse{ID: id, Type: "datacenter"}, nil } // Helper function to create test proxy responses @@ -93,7 +93,7 @@ func createDatacenterProxy(id, name, country string) kernel.ProxyListResponse { return kernel.ProxyListResponse{ ID: id, Name: name, - Type: kernel.ProxyListResponseTypeDatacenter, + Type: "datacenter", Config: kernel.ProxyListResponseConfigUnion{ Country: country, }, diff --git a/cmd/proxies/create.go b/cmd/proxies/create.go index 68e46757..2f681edb 100644 --- a/cmd/proxies/create.go +++ b/cmd/proxies/create.go @@ -22,7 +22,7 @@ func (p ProxyCmd) Create(ctx context.Context, in ProxyCreateInput) error { var proxyType kernel.ProxyNewParamsType switch in.Type { case "datacenter": - proxyType = kernel.ProxyNewParamsTypeDatacenter + return fmt.Errorf("datacenter proxies are deprecated; use --type isp") case "isp": proxyType = kernel.ProxyNewParamsTypeIsp case "residential": @@ -48,15 +48,6 @@ func (p ProxyCmd) Create(ctx context.Context, in ProxyCreateInput) error { // Build config based on type switch proxyType { - case kernel.ProxyNewParamsTypeDatacenter: - config := kernel.ProxyNewParamsConfigDatacenter{} - if in.Country != "" { - config.Country = kernel.Opt(in.Country) - } - params.Config = kernel.ProxyNewParamsConfigUnion{ - OfDatacenter: &config, - } - case kernel.ProxyNewParamsTypeIsp: config := kernel.ProxyNewParamsConfigIsp{} if in.Country != "" { diff --git a/cmd/proxies/create_test.go b/cmd/proxies/create_test.go index 25950519..3fdb452f 100644 --- a/cmd/proxies/create_test.go +++ b/cmd/proxies/create_test.go @@ -13,25 +13,25 @@ import ( "github.com/stretchr/testify/require" ) -func TestProxyCreate_Datacenter_Success(t *testing.T) { +func TestProxyCreate_ISP_BypassHosts(t *testing.T) { buf := captureOutput(t) fake := &FakeProxyService{ NewFunc: func(ctx context.Context, body kernel.ProxyNewParams, opts ...option.RequestOption) (*kernel.ProxyNewResponse, error) { // Verify the request - assert.Equal(t, kernel.ProxyNewParamsTypeDatacenter, body.Type) - assert.Equal(t, "My DC Proxy", body.Name.Value) + assert.Equal(t, kernel.ProxyNewParamsTypeIsp, body.Type) + assert.Equal(t, "My ISP Proxy", body.Name.Value) assert.Equal(t, []string{"localhost", "internal.service.local"}, body.BypassHosts) // Check config - dcConfig := body.Config.OfDatacenter - assert.NotNil(t, dcConfig) - assert.Equal(t, "US", dcConfig.Country.Value) + ispConfig := body.Config.OfIsp + assert.NotNil(t, ispConfig) + assert.Equal(t, "US", ispConfig.Country.Value) return &kernel.ProxyNewResponse{ - ID: "dc-new", - Name: "My DC Proxy", - Type: kernel.ProxyNewResponseTypeDatacenter, + ID: "isp-new", + Name: "My ISP Proxy", + Type: "isp", BypassHosts: []string{"localhost", "internal.service.local"}, }, nil }, @@ -39,8 +39,8 @@ func TestProxyCreate_Datacenter_Success(t *testing.T) { p := ProxyCmd{proxies: fake} err := p.Create(context.Background(), ProxyCreateInput{ - Name: "My DC Proxy", - Type: "datacenter", + Name: "My ISP Proxy", + Type: "isp", Country: "US", BypassHosts: []string{"localhost", "internal.service.local"}, }) @@ -48,47 +48,19 @@ func TestProxyCreate_Datacenter_Success(t *testing.T) { assert.NoError(t, err) output := buf.String() - assert.Contains(t, output, "Creating datacenter proxy") + assert.Contains(t, output, "Creating isp proxy") assert.Contains(t, output, "Successfully created proxy") - assert.Contains(t, output, "dc-new") - assert.Contains(t, output, "My DC Proxy") + assert.Contains(t, output, "isp-new") + assert.Contains(t, output, "My ISP Proxy") assert.Contains(t, output, "Bypass Hosts") assert.Contains(t, output, "localhost") assert.Contains(t, output, "internal.service.local") } -func TestProxyCreate_Datacenter_WithoutCountry(t *testing.T) { - buf := captureOutput(t) - - fake := &FakeProxyService{ - NewFunc: func(ctx context.Context, body kernel.ProxyNewParams, opts ...option.RequestOption) (*kernel.ProxyNewResponse, error) { - // Verify the request - assert.Equal(t, kernel.ProxyNewParamsTypeDatacenter, body.Type) - assert.Equal(t, "My DC Proxy", body.Name.Value) - - // Check config - country should not be set (it should be zero/nil) - dcConfig := body.Config.OfDatacenter - assert.NotNil(t, dcConfig) - - return &kernel.ProxyNewResponse{ - ID: "dc-new", - Name: "My DC Proxy", - Type: kernel.ProxyNewResponseTypeDatacenter, - }, nil - }, - } - - p := ProxyCmd{proxies: fake} - err := p.Create(context.Background(), ProxyCreateInput{ - Name: "My DC Proxy", - Type: "datacenter", - // Country is now optional - }) - - assert.NoError(t, err) - output := buf.String() - assert.Contains(t, output, "Creating datacenter proxy") - assert.Contains(t, output, "Successfully created proxy") +func TestProxyCreate_DatacenterDeprecated(t *testing.T) { + p := ProxyCmd{proxies: &FakeProxyService{}} + err := p.Create(context.Background(), ProxyCreateInput{Name: "Legacy", Type: "datacenter"}) + assert.EqualError(t, err, "datacenter proxies are deprecated; use --type isp") } func TestProxyCreate_Residential_Success(t *testing.T) { @@ -163,7 +135,7 @@ func TestProxyCreate_Residential_InvalidOS(t *testing.T) { func TestProxyCreate_MissingName(t *testing.T) { p := ProxyCmd{proxies: &FakeProxyService{}} err := p.Create(context.Background(), ProxyCreateInput{ - Type: "datacenter", + Type: "isp", Country: "US", }) @@ -356,7 +328,7 @@ func TestProxyCreate_Protocol_Valid(t *testing.T) { return &kernel.ProxyNewResponse{ ID: "test-proxy", Name: "Test Proxy", - Type: kernel.ProxyNewResponseTypeDatacenter, + Type: "datacenter", }, nil }, } @@ -364,7 +336,7 @@ func TestProxyCreate_Protocol_Valid(t *testing.T) { p := ProxyCmd{proxies: fake} err := p.Create(context.Background(), ProxyCreateInput{ Name: "Test Proxy", - Type: "datacenter", + Type: "isp", Country: "US", Protocol: tt.protocol, }) @@ -379,7 +351,7 @@ func TestProxyCreate_Protocol_Invalid(t *testing.T) { p := ProxyCmd{proxies: fake} err := p.Create(context.Background(), ProxyCreateInput{ Name: "Test Proxy", - Type: "datacenter", + Type: "isp", Country: "US", Protocol: "ftp", }) @@ -394,7 +366,7 @@ func TestProxyCreate_BypassHosts_Normalized(t *testing.T) { assert.Equal(t, []string{"localhost", "internal.service.local"}, body.BypassHosts) return &kernel.ProxyNewResponse{ ID: "test-proxy", - Type: kernel.ProxyNewResponseTypeDatacenter, + Type: "datacenter", }, nil }, } @@ -402,7 +374,7 @@ func TestProxyCreate_BypassHosts_Normalized(t *testing.T) { p := ProxyCmd{proxies: fake} err := p.Create(context.Background(), ProxyCreateInput{ Name: "Test Proxy", - Type: "datacenter", + Type: "isp", Country: "US", BypassHosts: []string{" localhost ", "", "internal.service.local"}, }) @@ -422,7 +394,7 @@ func TestProxyCreate_APIError(t *testing.T) { p := ProxyCmd{proxies: fake} err := p.Create(context.Background(), ProxyCreateInput{ Name: "Test", - Type: "datacenter", + Type: "isp", Country: "US", }) diff --git a/cmd/proxies/get.go b/cmd/proxies/get.go index e5a7aa8f..130044a4 100644 --- a/cmd/proxies/get.go +++ b/cmd/proxies/get.go @@ -72,7 +72,7 @@ func getProxyConfigRows(proxy *kernel.ProxyGetResponse) [][]string { config := &proxy.Config switch proxy.Type { - case kernel.ProxyGetResponseTypeDatacenter, kernel.ProxyGetResponseTypeIsp: + case "datacenter", kernel.ProxyGetResponseTypeIsp: if config.Country != "" { rows = append(rows, []string{"Country", config.Country}) } diff --git a/cmd/proxies/get_test.go b/cmd/proxies/get_test.go index 55af3014..8b81b169 100644 --- a/cmd/proxies/get_test.go +++ b/cmd/proxies/get_test.go @@ -19,7 +19,7 @@ func TestProxyGet_Datacenter(t *testing.T) { return &kernel.ProxyGetResponse{ ID: "dc-1", Name: "US Datacenter", - Type: kernel.ProxyGetResponseTypeDatacenter, + Type: "datacenter", BypassHosts: []string{"localhost", "internal.service.local"}, Config: kernel.ProxyGetResponseConfigUnion{ Country: "US", diff --git a/cmd/proxies/list.go b/cmd/proxies/list.go index 1efb5f34..8ecc6db1 100644 --- a/cmd/proxies/list.go +++ b/cmd/proxies/list.go @@ -109,7 +109,7 @@ func (p ProxyCmd) List(ctx context.Context, in ProxyListInput) error { func formatProxyConfig(proxy *kernel.ProxyListResponse) string { config := &proxy.Config switch proxy.Type { - case kernel.ProxyListResponseTypeDatacenter, kernel.ProxyListResponseTypeIsp: + case "datacenter", kernel.ProxyListResponseTypeIsp: if config.Country != "" { return fmt.Sprintf("Country: %s", config.Country) } diff --git a/cmd/proxies/proxies.go b/cmd/proxies/proxies.go index 12827f70..35245985 100644 --- a/cmd/proxies/proxies.go +++ b/cmd/proxies/proxies.go @@ -38,17 +38,13 @@ Proxy types (from best to worst for bot detection): - mobile: Mobile carrier proxies - residential: Residential IP proxies - isp: ISP proxies (supported countries: US, GB, FR, DE, SG) -- datacenter: Datacenter proxies - custom: Your own proxy server Country targeting: -- datacenter and isp default to US when --country is omitted +- isp defaults to US when --country is omitted - residential and mobile use the global pool without country targeting when --country is omitted Examples: - # Create a datacenter proxy - kernel proxies create --type datacenter --country US --name "US Datacenter" - # Create a custom proxy kernel proxies create --type custom --host proxy.example.com --port 8080 --username myuser --password mypass --name "My Custom Proxy" @@ -62,7 +58,7 @@ Examples: kernel proxies create --type residential --country US --city sanfrancisco --state CA --name "SF Residential" # Create a proxy with bypass hosts - kernel proxies create --type datacenter --country US --bypass-host localhost,internal.service.local --name "Internal Services"`, + kernel proxies create --type isp --country US --bypass-host localhost,internal.service.local --name "Internal Services"`, RunE: runProxiesCreate, } @@ -110,12 +106,12 @@ func init() { // Add flags for create command proxiesCreateCmd.Flags().String("name", "", "Proxy configuration name (required)") _ = proxiesCreateCmd.MarkFlagRequired("name") - proxiesCreateCmd.Flags().String("type", "", "Proxy type (datacenter|isp|residential|mobile|custom)") + proxiesCreateCmd.Flags().String("type", "", "Proxy type (isp|residential|mobile|custom)") _ = proxiesCreateCmd.MarkFlagRequired("type") proxiesCreateCmd.Flags().String("protocol", "https", "Protocol to use for the proxy connection (http|https)") - // Location flags (datacenter, isp, residential, mobile) - proxiesCreateCmd.Flags().String("country", "", "ISO 3166 country code or EU (isp proxies support US, GB, FR, DE, SG; datacenter and isp default to US, residential and mobile use the global pool without country targeting)") + // Location flags (isp, residential, mobile) + proxiesCreateCmd.Flags().String("country", "", "ISO 3166 country code or EU (isp proxies support US, GB, FR, DE, SG; isp defaults to US, residential and mobile use the global pool without country targeting)") proxiesCreateCmd.Flags().String("city", "", "City name (no spaces, e.g. sanfrancisco)") proxiesCreateCmd.Flags().String("state", "", "Two-letter state code") proxiesCreateCmd.Flags().String("zip", "", "US ZIP code") diff --git a/cmd/proxies/update_test.go b/cmd/proxies/update_test.go index d25d6994..5f5b1d29 100644 --- a/cmd/proxies/update_test.go +++ b/cmd/proxies/update_test.go @@ -22,7 +22,7 @@ func TestProxyUpdate_RenamesProxy(t *testing.T) { return &kernel.ProxyUpdateResponse{ ID: id, Name: body.Name, - Type: kernel.ProxyUpdateResponseTypeDatacenter, + Type: "datacenter", Status: kernel.ProxyUpdateResponseStatusAvailable, }, nil }, diff --git a/go.mod b/go.mod index fd049025..3edad86a 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/joho/godotenv v1.5.1 - github.com/kernel/kernel-go-sdk v0.120.0 + github.com/kernel/kernel-go-sdk v0.121.0 github.com/klauspost/compress v1.18.5 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pterm/pterm v0.12.80 diff --git a/go.sum b/go.sum index 27c84c37..a456eea6 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kernel/kernel-go-sdk v0.120.0 h1:m4E5OPcv3jZfODi+zP5waICXL1fvcoBD0xdvDAAP4hM= github.com/kernel/kernel-go-sdk v0.120.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= +github.com/kernel/kernel-go-sdk v0.121.0 h1:fuw8MVy4XN71MtBc/bY+b2Oeuy40VVnEHzk+9Kf9fcw= +github.com/kernel/kernel-go-sdk v0.121.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= From 9a1c57edeec2a8b9111d652a080be74ce18e7bf7 Mon Sep 17 00:00:00 2001 From: rgarcia <72655+rgarcia@users.noreply.github.com> Date: Wed, 7 Oct 2026 20:08:26 +0000 Subject: [PATCH 2/3] Create and check 1Password access requests without a browser --- cmd/vaults_commands.go | 11 +++++------ cmd/vaults_credentials.go | 7 ++++--- cmd/vaults_onepassword_test.go | 17 +++++++++-------- cmd/vaults_operation_params.go | 16 ++++++++-------- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/cmd/vaults_commands.go b/cmd/vaults_commands.go index 43c99312..8e32c1d6 100644 --- a/cmd/vaults_commands.go +++ b/cmd/vaults_commands.go @@ -212,11 +212,10 @@ exit nonzero with JSON retained on stdout. unknown means the tool may have run: and never retry automatically. 400/403/404/409 rejections mean the tool was not invoked. 1Password credentials (see credentials --help) use --params or --spec-file without type: -1pw_create_access_request: browser_id (vault-bound session ID); optional goal (<=140), - reason (<=100), keywords (1-5 strings); reason and keywords only for single-entry - credentials. Present the returned onepassword:// approval link and instructions to +1pw_create_access_request: no browser needed; optional goal (<=140), reason (<=100), + keywords (1-5 strings); reason and keywords only for single-entry credentials. Present the returned onepassword:// approval link and instructions to the account owner unchanged; invoke it once per credential. -1pw_access_request_status: browser_id; optional timeout_seconds 0-120 (default 10). +1pw_access_request_status: no browser needed; optional timeout_seconds 0-120 (default 10). Check status after the account owner has the approval link. 1pw_fill: browser_id and the exact page_url of one open login page on a requested origin; entry_id when several approved entries share that origin; optional @@ -237,8 +236,8 @@ JSON kernel vaults items invoke user-vault login webmcp_invoke --spec-file - <<'JSON' {"browser_id":"","tool_ref":"","page_url":"https://example.com/login","input":{"email":null,"password":null},"bindings":[{"field":"email","input_path":"/email"},{"field":"password","input_path":"/password"}]} JSON - kernel vaults items invoke user-vault github 1pw_create_access_request --params '{"browser_id":"","reason":"Sign in to GitHub"}' - kernel vaults items invoke user-vault github 1pw_access_request_status --params '{"browser_id":"","timeout_seconds":60}' + kernel vaults items invoke user-vault github 1pw_create_access_request --params '{"reason":"Sign in to GitHub"}' + kernel vaults items invoke user-vault github 1pw_access_request_status --params '{"timeout_seconds":60}' kernel vaults items invoke user-vault github 1pw_fill --params '{"browser_id":"","page_url":"https://github.com/login"}' kernel vaults items invoke user-vault github 1pw_fill --params '{"browser_id":"","page_url":"https://github.com/login","entry_id":""}' kernel vaults items invoke checkout order-1 fill --params '{"browser_id":"browser-session-id","page_url":"https://shop.example/checkout","fields":[{"field":"number","selector":"#card-number"}]}' -o json`, diff --git a/cmd/vaults_credentials.go b/cmd/vaults_credentials.go index c4a30e51..33b3bf77 100644 --- a/cmd/vaults_credentials.go +++ b/cmd/vaults_credentials.go @@ -53,11 +53,12 @@ const vaultOnePasswordCredentialHelp = `1Password flow: with the HTTPS website of a login page. Use one entry unless the user needs several logins, such as separate accounts or sign-in origins; per-entry reason and keywords go in the spec. No field definitions, selectors, or values are accepted. -3. Invoke 1pw_create_access_request once with a vault-bound browser_id. Present the - returned onepassword:// approval link and instructions to the account owner unchanged. +3. Invoke 1pw_create_access_request once; it needs no browser. Present the returned + onepassword:// approval link and instructions to the account owner unchanged. 4. Invoke 1pw_access_request_status (timeout_seconds 0-120) until the credential is ready, declined, or failed. Ready means approved, not signed in. -5. Open the login page and invoke 1pw_fill with browser_id and the exact page_url. When +5. Create a browser with the vault attached, open the login page, and invoke 1pw_fill + with browser_id and the exact page_url. When several approved entries share that page's origin, pass entry_id from the state.access_request entries in items get -o json. fill_submitted means the form was submitted, not that sign-in succeeded. diff --git a/cmd/vaults_onepassword_test.go b/cmd/vaults_onepassword_test.go index ec7d6b72..eb97824f 100644 --- a/cmd/vaults_onepassword_test.go +++ b/cmd/vaults_onepassword_test.go @@ -134,8 +134,8 @@ func TestOnePasswordOperationRequests(t *testing.T) { for _, tc := range []struct { operation, params, body, item string }{ - {"1pw_create_access_request", `{"browser_id":"browser-1","goal":"Manage billing","reason":"Sign in","keywords":["personal"]}`, `{"type":"1pw_create_access_request","browser_id":"browser-1","goal":"Manage billing","reason":"Sign in","keywords":["personal"]}`, onePasswordCredentialFixture}, - {"1pw_access_request_status", `{"browser_id":"browser-1","timeout_seconds":60}`, `{"type":"1pw_access_request_status","browser_id":"browser-1","timeout_seconds":60}`, onePasswordCredentialFixture}, + {"1pw_create_access_request", `{"goal":"Manage billing","reason":"Sign in","keywords":["personal"]}`, `{"type":"1pw_create_access_request","goal":"Manage billing","reason":"Sign in","keywords":["personal"]}`, onePasswordCredentialFixture}, + {"1pw_access_request_status", `{"timeout_seconds":60}`, `{"type":"1pw_access_request_status","timeout_seconds":60}`, onePasswordCredentialFixture}, {"1pw_recover", "", `{"type":"1pw_recover"}`, onePasswordAccountFixture}, } { t.Run(tc.operation, func(t *testing.T) { @@ -167,10 +167,11 @@ func TestOnePasswordOperationValidation(t *testing.T) { t.Setenv("KERNEL_PROJECT", "") for _, tc := range []struct{ operation, params, err string }{ {"1pw_create_access_request", "", "requires --params"}, - {"1pw_create_access_request", `{"browser_id":""}`, "browser_id"}, - {"1pw_create_access_request", `{"browser_id":"b","password":"x"}`, "only supported"}, - {"1pw_create_access_request", `{"type":"1pw_create_access_request","browser_id":"b"}`, "must not contain type"}, - {"1pw_access_request_status", `{"browser_id":"b","timeout_seconds":121}`, "timeout_seconds"}, + {"1pw_create_access_request", `{"browser_id":"b"}`, "only supported"}, + {"1pw_create_access_request", `{"password":"x"}`, "only supported"}, + {"1pw_create_access_request", `{"type":"1pw_create_access_request"}`, "must not contain type"}, + {"1pw_access_request_status", `{"browser_id":"b"}`, "only supported"}, + {"1pw_access_request_status", `{"timeout_seconds":121}`, "timeout_seconds"}, {"1pw_reconcile_access", `{"acknowledge_unconfirmed":true}`, "unsupported 1Password operation"}, {"1pw_fill", `{"browser_id":"b"}`, "page_url"}, {"1pw_fill", `{"browser_id":"b","page_url":"https://github.com/login","timeout_ms":0}`, "timeout_ms"}, @@ -400,7 +401,7 @@ func TestOnePasswordOperationErrorGuidance(t *testing.T) { w.WriteHeader(tc.status) io.WriteString(w, tc.body) }) - _, _, err := executeVaultCommand(t, client, "vaults", "items", "invoke", "user", "github", "1pw_create_access_request", "--params", `{"browser_id":"browser-1"}`) + _, _, err := executeVaultCommand(t, client, "vaults", "items", "invoke", "user", "github", "1pw_create_access_request", "--params", `{}`) require.ErrorContains(t, err, tc.want) assert.NotContains(t, err.Error(), "secret-echo") assert.NotContains(t, err.Error(), "before retrying") @@ -412,7 +413,7 @@ func TestOnePasswordOperationErrorGuidance(t *testing.T) { w.Header().Set("Content-Type", "application/json") io.WriteString(w, onePasswordCredentialFixture) }) - _, _, err := executeVaultCommand(t, client, "vaults", "items", "invoke", "user", "github", "1pw_create_access_request", "--params", `{"browser_id":"browser-1"}`) + _, _, err := executeVaultCommand(t, client, "vaults", "items", "invoke", "user", "github", "1pw_create_access_request", "--params", `{}`) require.ErrorContains(t, err, "check that the linked credential_account is connected") assert.Contains(t, err.Error(), "do not delete or recreate the item") } diff --git a/cmd/vaults_operation_params.go b/cmd/vaults_operation_params.go index 5a0d5cd2..7150e145 100644 --- a/cmd/vaults_operation_params.go +++ b/cmd/vaults_operation_params.go @@ -195,8 +195,8 @@ func parseVaultFillParams(raw string) (*vaultFillParams, error) { func parseOnePasswordOperationParams(operation, raw string) (*kernel.VaultItemPerformOperationParams, error) { allowed := map[string]string{ - "1pw_create_access_request": "browser_id goal reason keywords", - "1pw_access_request_status": "browser_id timeout_seconds", + "1pw_create_access_request": "goal reason keywords", + "1pw_access_request_status": "timeout_seconds", "1pw_fill": "browser_id page_url entry_id timeout_ms", "1pw_update_access_token": "access_token", }[operation] @@ -214,13 +214,9 @@ func parseOnePasswordOperationParams(operation, raw string) (*kernel.VaultItemPe } return &kernel.VaultItemPerformOperationParams{Of1pwUpdateAccessToken: &request}, nil } - var browserID string - if json.Unmarshal(object["browser_id"], &browserID) != nil || strings.TrimSpace(browserID) == "" { - return nil, fmt.Errorf("browser_id must be a non-empty browser session ID, not a name") - } switch operation { case "1pw_create_access_request": - request := kernel.OnePasswordRequestAccessVaultItemOperationRequestParam{BrowserID: browserID, Type: kernel.OnePasswordRequestAccessVaultItemOperationRequestType1pwCreateAccessRequest} + request := kernel.OnePasswordRequestAccessVaultItemOperationRequestParam{Type: kernel.OnePasswordRequestAccessVaultItemOperationRequestType1pwCreateAccessRequest} for _, name := range []string{"goal", "reason"} { if value, ok := object[name]; ok { var text string @@ -239,7 +235,7 @@ func parseOnePasswordOperationParams(operation, raw string) (*kernel.VaultItemPe } return &kernel.VaultItemPerformOperationParams{Of1pwCreateAccessRequest: &request}, nil case "1pw_access_request_status": - request := kernel.VaultItemPerformOperationParamsBody1pwAccessRequestStatus{BrowserID: browserID} + request := kernel.VaultItemPerformOperationParamsBody1pwAccessRequestStatus{} if value, ok := object["timeout_seconds"]; ok { var timeout *int64 if json.Unmarshal(value, &timeout) != nil || timeout == nil || *timeout < 0 || *timeout > 120 { @@ -249,6 +245,10 @@ func parseOnePasswordOperationParams(operation, raw string) (*kernel.VaultItemPe } return &kernel.VaultItemPerformOperationParams{Of1pwAccessRequestStatus: &request}, nil default: + var browserID string + if json.Unmarshal(object["browser_id"], &browserID) != nil || strings.TrimSpace(browserID) == "" { + return nil, fmt.Errorf("browser_id must be a non-empty browser session ID, not a name") + } request := kernel.OnePasswordFillVaultItemOperationRequestParam{BrowserID: browserID, Type: kernel.OnePasswordFillVaultItemOperationRequestType1pwFill} if json.Unmarshal(object["page_url"], &request.PageURL) != nil { return nil, fmt.Errorf("page_url must be the exact absolute URL of the open login page") From ea83ddd4f559daec53b4830ad65589aa72df9671 Mon Sep 17 00:00:00 2001 From: rgarcia <72655+rgarcia@users.noreply.github.com> Date: Fri, 9 Oct 2026 04:01:38 +0000 Subject: [PATCH 3/3] Remove datacenter proxies from the CLI --- README.md | 10 +++++----- cmd/proxies/check.go | 2 +- cmd/proxies/check_test.go | 4 ++-- cmd/proxies/common_test.go | 12 ++++++------ cmd/proxies/create.go | 2 -- cmd/proxies/create_test.go | 10 ++-------- cmd/proxies/get.go | 2 +- cmd/proxies/get_test.go | 16 ++++++++-------- cmd/proxies/list.go | 2 +- cmd/proxies/list_test.go | 6 +++--- cmd/proxies/types.go | 2 +- cmd/proxies/update_test.go | 4 ++-- 12 files changed, 32 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index b0c14597..2c874dbd 100644 --- a/README.md +++ b/README.md @@ -1131,7 +1131,7 @@ anywhere a project ID does. - `--output json`, `-o json` - Output raw JSON object - `--name ` - Proxy configuration name (required) - - `--type ` - Proxy type: datacenter, isp, residential, mobile, custom (required) + - `--type ` - Proxy type: isp, residential, mobile, custom (required) - `--protocol ` - Protocol to use (default: https) - `--country ` - ISO 3166 country code or "EU" (location-based types) - `--city ` - City name (no spaces, e.g. sanfrancisco) (residential, mobile; requires `--country`) @@ -1589,11 +1589,11 @@ kernel browsers extensions upload my-browser ./extension1 ./extension2 # List proxy configurations kernel proxies list -# Create a datacenter proxy -kernel proxies create --type datacenter --country US --name "US Datacenter" +# Create an ISP proxy +kernel proxies create --type isp --country US --name "US ISP" -# Create a datacenter proxy using HTTP protocol -kernel proxies create --type datacenter --country US --protocol http --name "US DC (HTTP)" +# Create an ISP proxy using HTTP protocol +kernel proxies create --type isp --country US --protocol http --name "US ISP (HTTP)" # Create a custom proxy kernel proxies create --type custom --host proxy.example.com --port 8080 --username myuser --password mypass --name "My Custom Proxy" diff --git a/cmd/proxies/check.go b/cmd/proxies/check.go index b313b250..d4d676bc 100644 --- a/cmd/proxies/check.go +++ b/cmd/proxies/check.go @@ -94,7 +94,7 @@ func getProxyCheckConfigRows(proxy *kernel.ProxyCheckResponse) [][]string { config := &proxy.Config switch proxy.Type { - case "datacenter", kernel.ProxyCheckResponseTypeIsp: + case kernel.ProxyCheckResponseTypeIsp: if config.Country != "" { rows = append(rows, []string{"Country", config.Country}) } diff --git a/cmd/proxies/check_test.go b/cmd/proxies/check_test.go index 1a94fcd3..7b3b5c04 100644 --- a/cmd/proxies/check_test.go +++ b/cmd/proxies/check_test.go @@ -17,7 +17,7 @@ func TestProxyCheck_ShowsBypassHosts(t *testing.T) { return &kernel.ProxyCheckResponse{ ID: id, Name: "Proxy 1", - Type: "datacenter", + Type: kernel.ProxyCheckResponseTypeIsp, BypassHosts: []string{"localhost", "internal.service.local"}, Status: kernel.ProxyCheckResponseStatusAvailable, }, nil @@ -45,7 +45,7 @@ func TestProxyCheck_PassesURL(t *testing.T) { return &kernel.ProxyCheckResponse{ ID: id, Name: "Proxy 1", - Type: "datacenter", + Type: kernel.ProxyCheckResponseTypeIsp, Status: kernel.ProxyCheckResponseStatusAvailable, }, nil }, diff --git a/cmd/proxies/common_test.go b/cmd/proxies/common_test.go index 427e6b96..6d022429 100644 --- a/cmd/proxies/common_test.go +++ b/cmd/proxies/common_test.go @@ -57,21 +57,21 @@ func (f *FakeProxyService) Get(ctx context.Context, id string, opts ...option.Re if f.GetFunc != nil { return f.GetFunc(ctx, id, opts...) } - return &kernel.ProxyGetResponse{ID: id, Type: "datacenter"}, nil + return &kernel.ProxyGetResponse{ID: id, Type: kernel.ProxyGetResponseTypeIsp}, nil } func (f *FakeProxyService) New(ctx context.Context, body kernel.ProxyNewParams, opts ...option.RequestOption) (*kernel.ProxyNewResponse, error) { if f.NewFunc != nil { return f.NewFunc(ctx, body, opts...) } - return &kernel.ProxyNewResponse{ID: "new-proxy", Type: "datacenter"}, nil + return &kernel.ProxyNewResponse{ID: "new-proxy", Type: kernel.ProxyNewResponseTypeIsp}, nil } func (f *FakeProxyService) Update(ctx context.Context, id string, body kernel.ProxyUpdateParams, opts ...option.RequestOption) (*kernel.ProxyUpdateResponse, error) { if f.UpdateFunc != nil { return f.UpdateFunc(ctx, id, body, opts...) } - return &kernel.ProxyUpdateResponse{ID: id, Name: body.Name, Type: "datacenter"}, nil + return &kernel.ProxyUpdateResponse{ID: id, Name: body.Name, Type: kernel.ProxyUpdateResponseTypeIsp}, nil } func (f *FakeProxyService) Delete(ctx context.Context, id string, opts ...option.RequestOption) error { @@ -85,15 +85,15 @@ func (f *FakeProxyService) Check(ctx context.Context, id string, body kernel.Pro if f.CheckFunc != nil { return f.CheckFunc(ctx, id, body, opts...) } - return &kernel.ProxyCheckResponse{ID: id, Type: "datacenter"}, nil + return &kernel.ProxyCheckResponse{ID: id, Type: kernel.ProxyCheckResponseTypeIsp}, nil } // Helper function to create test proxy responses -func createDatacenterProxy(id, name, country string) kernel.ProxyListResponse { +func createISPProxy(id, name, country string) kernel.ProxyListResponse { return kernel.ProxyListResponse{ ID: id, Name: name, - Type: "datacenter", + Type: kernel.ProxyListResponseTypeIsp, Config: kernel.ProxyListResponseConfigUnion{ Country: country, }, diff --git a/cmd/proxies/create.go b/cmd/proxies/create.go index 2f681edb..a101b41f 100644 --- a/cmd/proxies/create.go +++ b/cmd/proxies/create.go @@ -21,8 +21,6 @@ func (p ProxyCmd) Create(ctx context.Context, in ProxyCreateInput) error { // Validate proxy type var proxyType kernel.ProxyNewParamsType switch in.Type { - case "datacenter": - return fmt.Errorf("datacenter proxies are deprecated; use --type isp") case "isp": proxyType = kernel.ProxyNewParamsTypeIsp case "residential": diff --git a/cmd/proxies/create_test.go b/cmd/proxies/create_test.go index 3fdb452f..0ec237f2 100644 --- a/cmd/proxies/create_test.go +++ b/cmd/proxies/create_test.go @@ -57,12 +57,6 @@ func TestProxyCreate_ISP_BypassHosts(t *testing.T) { assert.Contains(t, output, "internal.service.local") } -func TestProxyCreate_DatacenterDeprecated(t *testing.T) { - p := ProxyCmd{proxies: &FakeProxyService{}} - err := p.Create(context.Background(), ProxyCreateInput{Name: "Legacy", Type: "datacenter"}) - assert.EqualError(t, err, "datacenter proxies are deprecated; use --type isp") -} - func TestProxyCreate_Residential_Success(t *testing.T) { buf := captureOutput(t) @@ -328,7 +322,7 @@ func TestProxyCreate_Protocol_Valid(t *testing.T) { return &kernel.ProxyNewResponse{ ID: "test-proxy", Name: "Test Proxy", - Type: "datacenter", + Type: kernel.ProxyNewResponseTypeIsp, }, nil }, } @@ -366,7 +360,7 @@ func TestProxyCreate_BypassHosts_Normalized(t *testing.T) { assert.Equal(t, []string{"localhost", "internal.service.local"}, body.BypassHosts) return &kernel.ProxyNewResponse{ ID: "test-proxy", - Type: "datacenter", + Type: kernel.ProxyNewResponseTypeIsp, }, nil }, } diff --git a/cmd/proxies/get.go b/cmd/proxies/get.go index 130044a4..5511b85e 100644 --- a/cmd/proxies/get.go +++ b/cmd/proxies/get.go @@ -72,7 +72,7 @@ func getProxyConfigRows(proxy *kernel.ProxyGetResponse) [][]string { config := &proxy.Config switch proxy.Type { - case "datacenter", kernel.ProxyGetResponseTypeIsp: + case kernel.ProxyGetResponseTypeIsp: if config.Country != "" { rows = append(rows, []string{"Country", config.Country}) } diff --git a/cmd/proxies/get_test.go b/cmd/proxies/get_test.go index 8b81b169..4729be50 100644 --- a/cmd/proxies/get_test.go +++ b/cmd/proxies/get_test.go @@ -11,15 +11,15 @@ import ( "github.com/stretchr/testify/assert" ) -func TestProxyGet_Datacenter(t *testing.T) { +func TestProxyGet_ISP(t *testing.T) { buf := captureOutput(t) fake := &FakeProxyService{ GetFunc: func(ctx context.Context, id string, opts ...option.RequestOption) (*kernel.ProxyGetResponse, error) { return &kernel.ProxyGetResponse{ - ID: "dc-1", - Name: "US Datacenter", - Type: "datacenter", + ID: "isp-us", + Name: "US ISP", + Type: kernel.ProxyGetResponseTypeIsp, BypassHosts: []string{"localhost", "internal.service.local"}, Config: kernel.ProxyGetResponseConfigUnion{ Country: "US", @@ -29,18 +29,18 @@ func TestProxyGet_Datacenter(t *testing.T) { } p := ProxyCmd{proxies: fake} - err := p.Get(context.Background(), ProxyGetInput{ID: "dc-1"}) + err := p.Get(context.Background(), ProxyGetInput{ID: "isp-us"}) assert.NoError(t, err) output := buf.String() // Check all fields are displayed assert.Contains(t, output, "ID") - assert.Contains(t, output, "dc-1") + assert.Contains(t, output, "isp-us") assert.Contains(t, output, "Name") - assert.Contains(t, output, "US Datacenter") + assert.Contains(t, output, "US ISP") assert.Contains(t, output, "Type") - assert.Contains(t, output, "datacenter") + assert.Contains(t, output, "isp") assert.Contains(t, output, "Bypass Hosts") assert.Contains(t, output, "localhost") assert.Contains(t, output, "internal.service.local") diff --git a/cmd/proxies/list.go b/cmd/proxies/list.go index 8ecc6db1..6c1ff0b8 100644 --- a/cmd/proxies/list.go +++ b/cmd/proxies/list.go @@ -109,7 +109,7 @@ func (p ProxyCmd) List(ctx context.Context, in ProxyListInput) error { func formatProxyConfig(proxy *kernel.ProxyListResponse) string { config := &proxy.Config switch proxy.Type { - case "datacenter", kernel.ProxyListResponseTypeIsp: + case kernel.ProxyListResponseTypeIsp: if config.Country != "" { return fmt.Sprintf("Country: %s", config.Country) } diff --git a/cmd/proxies/list_test.go b/cmd/proxies/list_test.go index abd27b18..009fb8c4 100644 --- a/cmd/proxies/list_test.go +++ b/cmd/proxies/list_test.go @@ -30,7 +30,7 @@ func TestProxyList_WithProxies(t *testing.T) { buf := captureOutput(t) proxies := []kernel.ProxyListResponse{ - createDatacenterProxy("dc-1", "US Datacenter", "US"), + createISPProxy("isp-us", "US ISP", "US"), createResidentialProxy("res-1", "SF Residential", "US", "sanfrancisco", "CA"), createCustomProxy("custom-1", "My Proxy", "proxy.example.com", 8080), { @@ -73,9 +73,9 @@ func TestProxyList_WithProxies(t *testing.T) { assert.Contains(t, output, "Status") // Check proxy data - verify IDs and short columns are fully visible - assert.Contains(t, output, "dc-1") + assert.Contains(t, output, "isp-us") assert.Contains(t, output, "https") // Protocol is shown - assert.Contains(t, output, "datacenter") + assert.Contains(t, output, "isp") assert.Contains(t, output, "res-1") assert.Contains(t, output, "residential") diff --git a/cmd/proxies/types.go b/cmd/proxies/types.go index ee0b6247..1a543c42 100644 --- a/cmd/proxies/types.go +++ b/cmd/proxies/types.go @@ -45,7 +45,7 @@ type ProxyCreateInput struct { Protocol string // Hostnames that should bypass the parent proxy and connect directly. BypassHosts []string - // Datacenter/ISP config + // ISP config Country string // Residential/Mobile config City string diff --git a/cmd/proxies/update_test.go b/cmd/proxies/update_test.go index 5f5b1d29..d08c4ea1 100644 --- a/cmd/proxies/update_test.go +++ b/cmd/proxies/update_test.go @@ -22,7 +22,7 @@ func TestProxyUpdate_RenamesProxy(t *testing.T) { return &kernel.ProxyUpdateResponse{ ID: id, Name: body.Name, - Type: "datacenter", + Type: kernel.ProxyUpdateResponseTypeIsp, Status: kernel.ProxyUpdateResponseStatusAvailable, }, nil }, @@ -37,7 +37,7 @@ func TestProxyUpdate_RenamesProxy(t *testing.T) { out := buf.String() assert.Contains(t, out, "Renamed proxy proxy-1 to New Name") - assert.Contains(t, out, "datacenter") + assert.Contains(t, out, "isp") } func TestProxyUpdate_RequiresName(t *testing.T) {