From f4042fec966855ccb1d8a7c042de0b5a27ce1c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Banaszewski?= Date: Fri, 29 May 2026 14:47:39 +0000 Subject: [PATCH] ai_gateway_coderd_key -> ai_gateway_keys table rename --- .../aigatewaycoderdkey_test.go | 22 ------ .../aigatewaykey.go} | 8 +- coderd/aigatewaykey/aigatewaykey_test.go | 22 ++++++ ...igatewaycoderdkeys.go => aigatewaykeys.go} | 38 +++++----- ...igatewaycoderdkeys.go => aigatewaykeys.go} | 74 +++++++++---------- ...derdkeys_test.go => aigatewaykeys_test.go} | 62 ++++++++-------- enterprise/coderd/coderd.go | 8 +- site/src/api/typesGenerated.ts | 18 ++--- 8 files changed, 126 insertions(+), 126 deletions(-) delete mode 100644 coderd/aigatewaycoderdkey/aigatewaycoderdkey_test.go rename coderd/{aigatewaycoderdkey/aigatewaycoderdkey.go => aigatewaykey/aigatewaykey.go} (74%) create mode 100644 coderd/aigatewaykey/aigatewaykey_test.go rename codersdk/{aigatewaycoderdkeys.go => aigatewaykeys.go} (51%) rename enterprise/coderd/{aigatewaycoderdkeys.go => aigatewaykeys.go} (66%) rename enterprise/coderd/{aigatewaycoderdkeys_test.go => aigatewaykeys_test.go} (76%) diff --git a/coderd/aigatewaycoderdkey/aigatewaycoderdkey_test.go b/coderd/aigatewaycoderdkey/aigatewaycoderdkey_test.go deleted file mode 100644 index a917f85a92..0000000000 --- a/coderd/aigatewaycoderdkey/aigatewaycoderdkey_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package aigatewaycoderdkey_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/coder/coder/v2/coderd/aigatewaycoderdkey" - "github.com/coder/coder/v2/coderd/apikey" -) - -func TestNew(t *testing.T) { - t.Parallel() - - params, key, err := aigatewaycoderdkey.New("test-key") - require.NoError(t, err) - require.Len(t, key, aigatewaycoderdkey.KeyLength) - require.Len(t, params.SecretPrefix, aigatewaycoderdkey.KeyPrefixLength) - require.Equal(t, key[:aigatewaycoderdkey.KeyPrefixLength], params.SecretPrefix) - require.True(t, apikey.ValidateHash(params.HashedSecret, key)) - require.False(t, apikey.ValidateHash(params.HashedSecret, key[aigatewaycoderdkey.KeyPrefixLength:])) -} diff --git a/coderd/aigatewaycoderdkey/aigatewaycoderdkey.go b/coderd/aigatewaykey/aigatewaykey.go similarity index 74% rename from coderd/aigatewaycoderdkey/aigatewaycoderdkey.go rename to coderd/aigatewaykey/aigatewaykey.go index 34f7f483e9..db2e9ad765 100644 --- a/coderd/aigatewaycoderdkey/aigatewaycoderdkey.go +++ b/coderd/aigatewaykey/aigatewaykey.go @@ -1,4 +1,4 @@ -package aigatewaycoderdkey +package aigatewaykey import ( "github.com/google/uuid" @@ -21,14 +21,14 @@ const ( // New generates an AI Gateway Coderd key. Returns InsertParams ready // for the database query. -func New(name string) (database.InsertAIGatewayCoderdKeyParams, string, error) { +func New(name string) (database.InsertAIGatewayKeyParams, string, error) { secret, hashed, err := apikey.GenerateSecret(KeyLength) if err != nil { - return database.InsertAIGatewayCoderdKeyParams{}, "", xerrors.Errorf("generate secret: %w", err) + return database.InsertAIGatewayKeyParams{}, "", xerrors.Errorf("generate secret: %w", err) } visiblePrefix := secret[:KeyPrefixLength] - return database.InsertAIGatewayCoderdKeyParams{ + return database.InsertAIGatewayKeyParams{ ID: uuid.New(), Name: name, SecretPrefix: visiblePrefix, diff --git a/coderd/aigatewaykey/aigatewaykey_test.go b/coderd/aigatewaykey/aigatewaykey_test.go new file mode 100644 index 0000000000..e17ec4e530 --- /dev/null +++ b/coderd/aigatewaykey/aigatewaykey_test.go @@ -0,0 +1,22 @@ +package aigatewaykey_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/coderd/aigatewaykey" + "github.com/coder/coder/v2/coderd/apikey" +) + +func TestNew(t *testing.T) { + t.Parallel() + + params, key, err := aigatewaykey.New("test-key") + require.NoError(t, err) + require.Len(t, key, aigatewaykey.KeyLength) + require.Len(t, params.SecretPrefix, aigatewaykey.KeyPrefixLength) + require.Equal(t, key[:aigatewaykey.KeyPrefixLength], params.SecretPrefix) + require.True(t, apikey.ValidateHash(params.HashedSecret, key)) + require.False(t, apikey.ValidateHash(params.HashedSecret, key[aigatewaykey.KeyPrefixLength:])) +} diff --git a/codersdk/aigatewaycoderdkeys.go b/codersdk/aigatewaykeys.go similarity index 51% rename from codersdk/aigatewaycoderdkeys.go rename to codersdk/aigatewaykeys.go index 9a4b78f0ed..7c4eb1c7a1 100644 --- a/codersdk/aigatewaycoderdkeys.go +++ b/codersdk/aigatewaykeys.go @@ -11,9 +11,9 @@ import ( "golang.org/x/xerrors" ) -// AIGatewayCoderdKey is a shared secret used by a standalone AI Gateway +// AIGatewayKey is a shared secret used by a standalone AI Gateway // to authenticate into coderd. -type AIGatewayCoderdKey struct { +type AIGatewayKey struct { ID uuid.UUID `json:"id" format:"uuid"` Name string `json:"name"` KeyPrefix string `json:"key_prefix"` @@ -21,14 +21,14 @@ type AIGatewayCoderdKey struct { LastUsedAt *time.Time `json:"last_used_at,omitempty" format:"date-time"` } -// CreateAIGatewayCoderdKeyRequest requests a new AI Gateway coderd key. -type CreateAIGatewayCoderdKeyRequest struct { +// CreateAIGatewayKeyRequest requests a new AI Gateway key. +type CreateAIGatewayKeyRequest struct { Name string `json:"name" validate:"required"` } -// CreateAIGatewayCoderdKeyResponse returns all key information. +// CreateAIGatewayKeyResponse returns all key information. // Key value is only returned here and cannot be recovered afterwards. -type CreateAIGatewayCoderdKeyResponse struct { +type CreateAIGatewayKeyResponse struct { ID uuid.UUID `json:"id" format:"uuid"` Name string `json:"name"` Key string `json:"key"` @@ -36,24 +36,24 @@ type CreateAIGatewayCoderdKeyResponse struct { CreatedAt time.Time `json:"created_at" format:"date-time"` } -// CreateAIGatewayCoderdKey creates a new AI Gateway coderd key. -func (c *Client) CreateAIGatewayCoderdKey(ctx context.Context, req CreateAIGatewayCoderdKeyRequest) (CreateAIGatewayCoderdKeyResponse, error) { - res, err := c.Request(ctx, http.MethodPost, "/api/v2/aibridge/coderd-keys", req) +// CreateAIGatewayKey creates a new AI Gateway key. +func (c *Client) CreateAIGatewayKey(ctx context.Context, req CreateAIGatewayKeyRequest) (CreateAIGatewayKeyResponse, error) { + res, err := c.Request(ctx, http.MethodPost, "/api/v2/aibridge/keys", req) if err != nil { - return CreateAIGatewayCoderdKeyResponse{}, xerrors.Errorf("make request: %w", err) + return CreateAIGatewayKeyResponse{}, xerrors.Errorf("make request: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusCreated { - return CreateAIGatewayCoderdKeyResponse{}, ReadBodyAsError(res) + return CreateAIGatewayKeyResponse{}, ReadBodyAsError(res) } - var resp CreateAIGatewayCoderdKeyResponse + var resp CreateAIGatewayKeyResponse return resp, json.NewDecoder(res.Body).Decode(&resp) } -// ListAIGatewayCoderdKeys lists all AI Gateway coderd keys. -func (c *Client) ListAIGatewayCoderdKeys(ctx context.Context) ([]AIGatewayCoderdKey, error) { - res, err := c.Request(ctx, http.MethodGet, "/api/v2/aibridge/coderd-keys", nil) +// ListAIGatewayKeys lists all AI Gateway keys. +func (c *Client) ListAIGatewayKeys(ctx context.Context) ([]AIGatewayKey, error) { + res, err := c.Request(ctx, http.MethodGet, "/api/v2/aibridge/keys", nil) if err != nil { return nil, xerrors.Errorf("make request: %w", err) } @@ -62,14 +62,14 @@ func (c *Client) ListAIGatewayCoderdKeys(ctx context.Context) ([]AIGatewayCoderd if res.StatusCode != http.StatusOK { return nil, ReadBodyAsError(res) } - var resp []AIGatewayCoderdKey + var resp []AIGatewayKey return resp, json.NewDecoder(res.Body).Decode(&resp) } -// DeleteAIGatewayCoderdKey deletes an AI Gateway coderd key by ID. -func (c *Client) DeleteAIGatewayCoderdKey(ctx context.Context, id uuid.UUID) error { +// DeleteAIGatewayKey deletes an AI Gateway key by ID. +func (c *Client) DeleteAIGatewayKey(ctx context.Context, id uuid.UUID) error { res, err := c.Request(ctx, http.MethodDelete, - fmt.Sprintf("/api/v2/aibridge/coderd-keys/%s", id.String()), nil) + fmt.Sprintf("/api/v2/aibridge/keys/%s", id.String()), nil) if err != nil { return xerrors.Errorf("make request: %w", err) } diff --git a/enterprise/coderd/aigatewaycoderdkeys.go b/enterprise/coderd/aigatewaykeys.go similarity index 66% rename from enterprise/coderd/aigatewaycoderdkeys.go rename to enterprise/coderd/aigatewaykeys.go index aa59f4ab43..b18625615e 100644 --- a/enterprise/coderd/aigatewaycoderdkeys.go +++ b/enterprise/coderd/aigatewaykeys.go @@ -10,7 +10,7 @@ import ( "github.com/go-chi/chi/v5" "github.com/google/uuid" - "github.com/coder/coder/v2/coderd/aigatewaycoderdkey" + "github.com/coder/coder/v2/coderd/aigatewaykey" "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/httpapi" @@ -24,20 +24,20 @@ const maxKeyInsertAttempts = 7 // nameFormatDetail is the human-readable description of valid key names. const nameFormatDetail = "Must be 64 characters or fewer, lowercase letters, numbers, and non-consecutive hyphens, cannot start or end with a hyphen." -// @Summary Create AI Gateway coderd key -// @ID create-ai-gateway-coderd-key +// @Summary Create AI Gateway key +// @ID create-ai-gateway-key // @Security CoderSessionToken // @Accept json // @Produce json // @Tags Enterprise -// @Param request body codersdk.CreateAIGatewayCoderdKeyRequest true "Create AI Gateway coderd key request" -// @Success 201 {object} codersdk.CreateAIGatewayCoderdKeyResponse -// @Router /api/v2/aibridge/coderd-keys [post] -func (api *API) postAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request) { +// @Param request body codersdk.CreateAIGatewayKeyRequest true "Create AI Gateway key request" +// @Success 201 {object} codersdk.CreateAIGatewayKeyResponse +// @Router /api/v2/aibridge/keys [post] +func (api *API) postAIGatewayKey(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() auditor = api.AGPL.Auditor.Load() - aReq, commitAudit = audit.InitRequest[database.AiGatewayCoderdKey](rw, &audit.RequestParams{ + aReq, commitAudit = audit.InitRequest[database.AIGatewayKey](rw, &audit.RequestParams{ Audit: *auditor, Log: api.Logger, Request: r, @@ -46,7 +46,7 @@ func (api *API) postAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request) ) defer commitAudit() - var req codersdk.CreateAIGatewayCoderdKeyRequest + var req codersdk.CreateAIGatewayKeyRequest if !httpapi.Read(ctx, rw, r, &req) { return } @@ -60,14 +60,14 @@ func (api *API) postAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request) return } - aReq.New = database.AiGatewayCoderdKey{ + aReq.New = database.AIGatewayKey{ ID: row.ID, Name: row.Name, SecretPrefix: row.SecretPrefix, CreatedAt: row.CreatedAt, } - httpapi.Write(ctx, rw, http.StatusCreated, codersdk.CreateAIGatewayCoderdKeyResponse{ + httpapi.Write(ctx, rw, http.StatusCreated, codersdk.CreateAIGatewayKeyResponse{ ID: row.ID, Name: row.Name, KeyPrefix: row.SecretPrefix, @@ -77,14 +77,14 @@ func (api *API) postAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request) } // generateAndInsertKey creates fresh key material and attempts an insert. -func (api *API) generateAndInsertKey(ctx context.Context, name string) (database.InsertAIGatewayCoderdKeyRow, string, error) { - params, key, err := aigatewaycoderdkey.New(name) +func (api *API) generateAndInsertKey(ctx context.Context, name string) (database.InsertAIGatewayKeyRow, string, error) { + params, key, err := aigatewaykey.New(name) if err != nil { - return database.InsertAIGatewayCoderdKeyRow{}, "", err + return database.InsertAIGatewayKeyRow{}, "", err } - row, err := api.Database.InsertAIGatewayCoderdKey(ctx, params) + row, err := api.Database.InsertAIGatewayKey(ctx, params) if err != nil { - return database.InsertAIGatewayCoderdKeyRow{}, "", err + return database.InsertAIGatewayKeyRow{}, "", err } return row, key, nil } @@ -92,8 +92,8 @@ func (api *API) generateAndInsertKey(ctx context.Context, name string) (database // isRetryableKeyInsertErr returns true for generated-secret collisions. func isRetryableKeyInsertErr(err error) bool { return database.IsUniqueViolation(err, - database.UniqueAiGatewayCoderdKeysSecretPrefixIndex, - database.UniqueAiGatewayCoderdKeysHashedSecretIndex, + database.UniqueAiGatewayKeysSecretPrefixIndex, + database.UniqueAiGatewayKeysHashedSecretIndex, ) } @@ -102,14 +102,14 @@ func writeKeyInsertError(ctx context.Context, rw http.ResponseWriter, err error) switch { case httpapi.IsUnauthorizedError(err): httpapi.Forbidden(rw) - case database.IsCheckViolation(err, database.CheckAiGatewayCoderdKeysNameCheck): + case database.IsCheckViolation(err, database.CheckAiGatewayKeysNameCheck): httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Invalid key name.", Validations: []codersdk.ValidationError{ {Field: "name", Detail: nameFormatDetail}, }, }) - case database.IsUniqueViolation(err, database.UniqueAiGatewayCoderdKeysNameIndex): + case database.IsUniqueViolation(err, database.UniqueAiGatewayKeysNameIndex): httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Key name must be unique.", Validations: []codersdk.ValidationError{ @@ -121,17 +121,17 @@ func writeKeyInsertError(ctx context.Context, rw http.ResponseWriter, err error) } } -// @Summary List AI Gateway coderd keys -// @ID list-ai-gateway-coderd-keys +// @Summary List AI Gateway keys +// @ID list-ai-gatewaykeys // @Security CoderSessionToken // @Produce json // @Tags Enterprise -// @Success 200 {array} codersdk.AIGatewayCoderdKey -// @Router /api/v2/aibridge/coderd-keys [get] -func (api *API) aiGatewayCoderdKeys(rw http.ResponseWriter, r *http.Request) { +// @Success 200 {array} codersdk.AIGatewayKey +// @Router /api/v2/aibridge/keys [get] +func (api *API) aiGatewayKeys(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() - rows, err := api.Database.ListAIGatewayCoderdKeys(ctx) + rows, err := api.Database.ListAIGatewayKeys(ctx) if httpapi.IsUnauthorizedError(err) { httpapi.Forbidden(rw) return @@ -141,26 +141,26 @@ func (api *API) aiGatewayCoderdKeys(rw http.ResponseWriter, r *http.Request) { return } - out := make([]codersdk.AIGatewayCoderdKey, 0, len(rows)) + out := make([]codersdk.AIGatewayKey, 0, len(rows)) for _, row := range rows { - out = append(out, convertAIGatewayCoderdKey(row)) + out = append(out, convertAIGatewayKey(row)) } httpapi.Write(ctx, rw, http.StatusOK, out) } -// @Summary Delete AI Gateway coderd key -// @ID delete-ai-gateway-coderd-key +// @Summary Delete AI Gateway key +// @ID delete-ai-gateway-key // @Security CoderSessionToken // @Tags Enterprise // @Param key path string true "Key ID" format(uuid) // @Success 204 -// @Router /api/v2/aibridge/coderd-keys/{key} [delete] -func (api *API) deleteAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request) { +// @Router /api/v2/aibridge/keys/{key} [delete] +func (api *API) deleteAIGatewayKey(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() auditor = api.AGPL.Auditor.Load() - aReq, commitAudit = audit.InitRequest[database.AiGatewayCoderdKey](rw, &audit.RequestParams{ + aReq, commitAudit = audit.InitRequest[database.AIGatewayKey](rw, &audit.RequestParams{ Audit: *auditor, Log: api.Logger, Request: r, @@ -178,7 +178,7 @@ func (api *API) deleteAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request return } - deleted, err := api.Database.DeleteAIGatewayCoderdKey(ctx, id) + deleted, err := api.Database.DeleteAIGatewayKey(ctx, id) if err != nil { if httpapi.IsUnauthorizedError(err) { httpapi.Forbidden(rw) @@ -192,7 +192,7 @@ func (api *API) deleteAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request return } - aReq.Old = database.AiGatewayCoderdKey{ + aReq.Old = database.AIGatewayKey{ ID: deleted.ID, Name: deleted.Name, SecretPrefix: deleted.SecretPrefix, @@ -203,13 +203,13 @@ func (api *API) deleteAIGatewayCoderdKey(rw http.ResponseWriter, r *http.Request rw.WriteHeader(http.StatusNoContent) } -func convertAIGatewayCoderdKey(row database.ListAIGatewayCoderdKeysRow) codersdk.AIGatewayCoderdKey { +func convertAIGatewayKey(row database.ListAIGatewayKeysRow) codersdk.AIGatewayKey { var lastUsed *time.Time if row.LastUsedAt.Valid { t := row.LastUsedAt.Time lastUsed = &t } - return codersdk.AIGatewayCoderdKey{ + return codersdk.AIGatewayKey{ ID: row.ID, Name: row.Name, KeyPrefix: row.SecretPrefix, diff --git a/enterprise/coderd/aigatewaycoderdkeys_test.go b/enterprise/coderd/aigatewaykeys_test.go similarity index 76% rename from enterprise/coderd/aigatewaycoderdkeys_test.go rename to enterprise/coderd/aigatewaykeys_test.go index a885f2e687..82e12c2f06 100644 --- a/enterprise/coderd/aigatewaycoderdkeys_test.go +++ b/enterprise/coderd/aigatewaykeys_test.go @@ -12,7 +12,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" - "github.com/coder/coder/v2/coderd/aigatewaycoderdkey" + "github.com/coder/coder/v2/coderd/aigatewaykey" "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" @@ -26,7 +26,7 @@ import ( "github.com/coder/coder/v2/testutil" ) -func TestAIGatewayCoderdKeys(t *testing.T) { +func TestAIGatewayKeys(t *testing.T) { t.Parallel() // Single instance shared by all subtests (except FeatureGate). @@ -36,22 +36,22 @@ func TestAIGatewayCoderdKeys(t *testing.T) { //nolint:paralleltest // Subtests share a single coderdenttest instance. t.Run("CRUD", func(t *testing.T) { - keys, err := ownerClient.ListAIGatewayCoderdKeys(ctx) + keys, err := ownerClient.ListAIGatewayKeys(ctx) require.NoError(t, err) require.Empty(t, keys) name := uniqueName(t, "happy") - created, err := ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: name}) + created, err := ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: name}) require.NoError(t, err) require.NotEqual(t, uuid.Nil, created.ID) require.Equal(t, name, created.Name) - require.Len(t, created.KeyPrefix, aigatewaycoderdkey.KeyPrefixLength) - require.Len(t, created.Key, aigatewaycoderdkey.KeyLength) + require.Len(t, created.KeyPrefix, aigatewaykey.KeyPrefixLength) + require.Len(t, created.Key, aigatewaykey.KeyLength) require.True(t, strings.HasPrefix(created.Key, created.KeyPrefix), "key must begin with key_prefix") require.WithinDuration(t, time.Now(), created.CreatedAt, time.Minute) - keys, err = ownerClient.ListAIGatewayCoderdKeys(ctx) + keys, err = ownerClient.ListAIGatewayKeys(ctx) require.NoError(t, err) require.Len(t, keys, 1) require.Equal(t, created.ID, keys[0].ID) @@ -59,25 +59,25 @@ func TestAIGatewayCoderdKeys(t *testing.T) { require.Equal(t, created.KeyPrefix, keys[0].KeyPrefix) require.Nil(t, keys[0].LastUsedAt) - require.NoError(t, ownerClient.DeleteAIGatewayCoderdKey(ctx, created.ID)) + require.NoError(t, ownerClient.DeleteAIGatewayKey(ctx, created.ID)) - keys, err = ownerClient.ListAIGatewayCoderdKeys(ctx) + keys, err = ownerClient.ListAIGatewayKeys(ctx) require.NoError(t, err) require.Empty(t, keys) }) //nolint:paralleltest // Subtests share a single coderdenttest instance. t.Run("ListResponseDoesNotLeakSecrets", func(t *testing.T) { - created, err := ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{ + created, err := ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{ Name: uniqueName(t, "leak"), }) require.NoError(t, err) t.Cleanup(func() { - _ = ownerClient.DeleteAIGatewayCoderdKey(ctx, created.ID) + _ = ownerClient.DeleteAIGatewayKey(ctx, created.ID) }) // Raw HTTP read of LIST to confirm the JSON shape. - resp, err := ownerClient.Request(ctx, http.MethodGet, "/api/v2/aibridge/coderd-keys", nil) + resp, err := ownerClient.Request(ctx, http.MethodGet, "/api/v2/aibridge/keys", nil) require.NoError(t, err) t.Cleanup(func() { _ = resp.Body.Close() }) require.Equal(t, http.StatusOK, resp.StatusCode) @@ -94,46 +94,46 @@ func TestAIGatewayCoderdKeys(t *testing.T) { //nolint:paralleltest // Subtests share a single coderdenttest instance. t.Run("CreateValidation", func(t *testing.T) { // Empty name -> 400 (validate:"required" on request struct). - _, err := ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: ""}) + _, err := ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: ""}) require.ErrorContains(t, err, "Validation failed") // >64 char name -> 400 (DB check constraint). longName := strings.Repeat("a", 65) - _, err = ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: longName}) + _, err = ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: longName}) require.ErrorContains(t, err, "Invalid key name") // Uppercase name -> 400 (DB check constraint rejects non-lowercase). - _, err = ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: "UPPER-CASE"}) + _, err = ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: "UPPER-CASE"}) require.ErrorContains(t, err, "Invalid key name") // Duplicate name -> 400. name := uniqueName(t, "dup") - created, err := ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: name}) + created, err := ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: name}) require.NoError(t, err) t.Cleanup(func() { - _ = ownerClient.DeleteAIGatewayCoderdKey(ctx, created.ID) + _ = ownerClient.DeleteAIGatewayKey(ctx, created.ID) }) - _, err = ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: name}) + _, err = ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: name}) require.ErrorContains(t, err, "must be unique") }) //nolint:paralleltest // Subtests share a single coderdenttest instance. t.Run("DeleteValidation", func(t *testing.T) { // Invalid UUID -> 400 (raw request; SDK method accepts uuid.UUID). - resp, err := ownerClient.Request(ctx, http.MethodDelete, "/api/v2/aibridge/coderd-keys/not-a-uuid", nil) + resp, err := ownerClient.Request(ctx, http.MethodDelete, "/api/v2/aibridge/keys/not-a-uuid", nil) require.NoError(t, err) t.Cleanup(func() { _ = resp.Body.Close() }) require.Equal(t, http.StatusBadRequest, resp.StatusCode) // Delete existing key -> 204 (SDK returns nil error on 204). - created, err := ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{ + created, err := ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{ Name: uniqueName(t, "del"), }) require.NoError(t, err) - require.NoError(t, ownerClient.DeleteAIGatewayCoderdKey(ctx, created.ID)) + require.NoError(t, ownerClient.DeleteAIGatewayKey(ctx, created.ID)) // Unknown UUID -> 404. - err = ownerClient.DeleteAIGatewayCoderdKey(ctx, uuid.New()) + err = ownerClient.DeleteAIGatewayKey(ctx, uuid.New()) var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusNotFound, sdkErr.StatusCode()) @@ -143,18 +143,18 @@ func TestAIGatewayCoderdKeys(t *testing.T) { t.Run("ReturnsForbiddenForNonOwners", func(t *testing.T) { member, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) - _, err := member.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{ + _, err := member.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{ Name: uniqueName(t, "denied"), }) var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusForbidden, sdkErr.StatusCode()) - _, err = member.ListAIGatewayCoderdKeys(ctx) + _, err = member.ListAIGatewayKeys(ctx) require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusForbidden, sdkErr.StatusCode()) - err = member.DeleteAIGatewayCoderdKey(ctx, uuid.New()) + err = member.DeleteAIGatewayKey(ctx, uuid.New()) require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusForbidden, sdkErr.StatusCode()) }) @@ -171,14 +171,14 @@ func TestAIGatewayCoderdKeys(t *testing.T) { }) //nolint:gocritic // Managing AI Gateway coderd keys is owner-only. - _, err := ownerClient.ListAIGatewayCoderdKeys(ctx) + _, err := ownerClient.ListAIGatewayKeys(ctx) var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusForbidden, sdkErr.StatusCode()) }) } -func TestAIGatewayCoderdKeyAudit(t *testing.T) { +func TestAIGatewayKeyAudit(t *testing.T) { t.Parallel() db, ps := dbtestutil.NewDB(t) @@ -200,15 +200,15 @@ func TestAIGatewayCoderdKeyAudit(t *testing.T) { name := uniqueName(t, "audit") //nolint:gocritic // Managing AI Gateway coderd keys is owner-only. - created, err := ownerClient.CreateAIGatewayCoderdKey(ctx, codersdk.CreateAIGatewayCoderdKeyRequest{Name: name}) + created, err := ownerClient.CreateAIGatewayKey(ctx, codersdk.CreateAIGatewayKeyRequest{Name: name}) require.NoError(t, err) //nolint:gocritic // Managing AI Gateway coderd keys is owner-only. - require.NoError(t, ownerClient.DeleteAIGatewayCoderdKey(ctx, created.ID)) + require.NoError(t, ownerClient.DeleteAIGatewayKey(ctx, created.ID)) rows, err := db.GetAuditLogsOffset( dbauthz.AsSystemRestricted(ctx), database.GetAuditLogsOffsetParams{ - ResourceType: string(database.ResourceTypeAiGatewayCoderdKey), + ResourceType: string(database.ResourceTypeAIGatewayKey), LimitOpt: 10, }, ) @@ -233,7 +233,7 @@ func TestAIGatewayCoderdKeyAudit(t *testing.T) { require.Equal(t, http.StatusNoContent, int(deleteLog.StatusCode)) for _, log := range []database.AuditLog{createLog, deleteLog} { - require.Equal(t, database.ResourceTypeAiGatewayCoderdKey, log.ResourceType) + require.Equal(t, database.ResourceTypeAIGatewayKey, log.ResourceType) require.Equal(t, created.ID, log.ResourceID) require.Equal(t, name, log.ResourceTarget) } diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index e42bca4367..092314a973 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -299,14 +299,14 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { }) api.AGPL.APIHandler.Group(func(r chi.Router) { - r.Route("/aibridge/coderd-keys", func(r chi.Router) { + r.Route("/aibridge/keys", func(r chi.Router) { r.Use( apiKeyMiddleware, api.RequireFeatureMW(codersdk.FeatureAIBridge), ) - r.Get("/", api.aiGatewayCoderdKeys) - r.Post("/", api.postAIGatewayCoderdKey) - r.Delete("/{key}", api.deleteAIGatewayCoderdKey) + r.Get("/", api.aiGatewayKeys) + r.Post("/", api.postAIGatewayKey) + r.Delete("/{key}", api.deleteAIGatewayKey) }) }) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 4b3cae467d..5c0cf7c24d 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -304,12 +304,12 @@ export interface AIConfig { readonly chat?: ChatConfig; } -// From codersdk/aigatewaycoderdkeys.go +// From codersdk/aigatewaykeys.go /** - * AIGatewayCoderdKey is a shared secret used by a standalone AI Gateway + * AIGatewayKey is a shared secret used by a standalone AI Gateway * to authenticate into coderd. */ -export interface AIGatewayCoderdKey { +export interface AIGatewayKey { readonly id: string; readonly name: string; readonly key_prefix: string; @@ -3257,20 +3257,20 @@ export interface ConvertLoginRequest { readonly password: string; } -// From codersdk/aigatewaycoderdkeys.go +// From codersdk/aigatewaykeys.go /** - * CreateAIGatewayCoderdKeyRequest requests a new AI Gateway coderd key. + * CreateAIGatewayKeyRequest requests a new AI Gateway key. */ -export interface CreateAIGatewayCoderdKeyRequest { +export interface CreateAIGatewayKeyRequest { readonly name: string; } -// From codersdk/aigatewaycoderdkeys.go +// From codersdk/aigatewaykeys.go /** - * CreateAIGatewayCoderdKeyResponse returns all key information. + * CreateAIGatewayKeyResponse returns all key information. * Key value is only returned here and cannot be recovered afterwards. */ -export interface CreateAIGatewayCoderdKeyResponse { +export interface CreateAIGatewayKeyResponse { readonly id: string; readonly name: string; readonly key: string;