mirror of
https://github.com/coder/coder.git
synced 2026-09-22 21:22:17 +08:00
Extracted from #27873 so the schema change can be reviewed for migration safety on its own. #27873 will rebase onto this. `client_type` decides whether the token endpoint validates a client secret at all, and the column accepts any text: nullable, no `CHECK`, no enum. No Go path can write a bad value today, and `IsPublic` fails closed on anything unrecognized, so the read side is safe. What the schema still permits is the problem: a future migration writing `'public'` onto a row that holds a secret turns off client authentication for that app with nothing to catch it, no constraint, no log, no audit entry, no test. `000565` adds `CHECK (client_type IN ('confidential', 'public'))` and `NOT NULL`. The `UPDATE` ahead of it should touch zero rows, since migration `000344` added the column with a default of `'confidential'` and backfilled with `COALESCE`; it is there so `SET NOT NULL` cannot fail on an unexpected row. Both `ALTER`s take `ACCESS EXCLUSIVE` and scan a table holding one row per registered OAuth2 client, so the lock is brief. ## The second migration, and why it aligns the way it does Two columns describe the same fact and can currently contradict each other. `token_endpoint_auth_method` is the client's own declaration: registered client metadata under RFC 7591 §2, where `"none"` is defined to mean the client is public and has no secret. `client_type` is Coder's derived copy, and it is what the token endpoint enforces on. RFC 7591 defines no `client_type` metadata field; the column exists only as a denormalization. Registration used to persist the declaration verbatim while hardcoding `client_type` to `'confidential'`, so rows exist declaring `"none"` on a client stored confidential that was issued, and still requires, a real secret. A client that reads its own metadata and believes it is public will drop that secret and stop being able to exchange codes. `000566` aligns the declaration to what is enforced, not the reverse. Deriving enforcement from the declaration would reclassify every such client as public and stop requiring the secret it holds, which is a silent authentication downgrade. The down migration is deliberately empty: the previous values are not recorded, and restoring them would only reinstate metadata that tells a client to authenticate in a way the server rejects. ## Application changes `SET NOT NULL` changes the generated field from `sql.NullString` to `string`, so the three write sites are updated to match. That is the entire application diff and no behavior depends on it. Refs https://linear.app/codercom/issue/ENG-3029/oauth2-support-public-client --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
73 lines
9.8 KiB
Go
Generated
73 lines
9.8 KiB
Go
Generated
// Code generated by scripts/dbgen/main.go. DO NOT EDIT.
|
|
package database
|
|
|
|
// CheckConstraint represents a named check constraint on a table.
|
|
type CheckConstraint string
|
|
|
|
// CheckConstraint enums.
|
|
const (
|
|
CheckAIGatewayKeysHashedSecretCheck CheckConstraint = "ai_gateway_keys_hashed_secret_check" // ai_gateway_keys
|
|
CheckAIGatewayKeysNameCheck CheckConstraint = "ai_gateway_keys_name_check" // ai_gateway_keys
|
|
CheckAIGatewayKeysSecretPrefixCheck CheckConstraint = "ai_gateway_keys_secret_prefix_check" // ai_gateway_keys
|
|
CheckAIModelPricesCacheReadPriceCheck CheckConstraint = "ai_model_prices_cache_read_price_check" // ai_model_prices
|
|
CheckAIModelPricesCacheWritePriceCheck CheckConstraint = "ai_model_prices_cache_write_price_check" // ai_model_prices
|
|
CheckAIModelPricesInputPriceCheck CheckConstraint = "ai_model_prices_input_price_check" // ai_model_prices
|
|
CheckAIModelPricesOutputPriceCheck CheckConstraint = "ai_model_prices_output_price_check" // ai_model_prices
|
|
CheckAIProvidersNameCheck CheckConstraint = "ai_providers_name_check" // ai_providers
|
|
CheckAIUserDailySpendSpendMicrosCheck CheckConstraint = "ai_user_daily_spend_spend_micros_check" // ai_user_daily_spend
|
|
CheckAibridgeTokenUsagesCacheReadPriceMicrosCheck CheckConstraint = "aibridge_token_usages_cache_read_price_micros_check" // aibridge_token_usages
|
|
CheckAibridgeTokenUsagesCacheWritePriceMicrosCheck CheckConstraint = "aibridge_token_usages_cache_write_price_micros_check" // aibridge_token_usages
|
|
CheckAibridgeTokenUsagesCostMicrosCheck CheckConstraint = "aibridge_token_usages_cost_micros_check" // aibridge_token_usages
|
|
CheckAibridgeTokenUsagesInputPriceMicrosCheck CheckConstraint = "aibridge_token_usages_input_price_micros_check" // aibridge_token_usages
|
|
CheckAibridgeTokenUsagesOutputPriceMicrosCheck CheckConstraint = "aibridge_token_usages_output_price_micros_check" // aibridge_token_usages
|
|
CheckAPIKeysAllowListNotEmpty CheckConstraint = "api_keys_allow_list_not_empty" // api_keys
|
|
CheckBoundaryLogsSequenceNumberCheck CheckConstraint = "boundary_logs_sequence_number_check" // boundary_logs
|
|
CheckChatModelConfigsAIProviderRequiredWhenActive CheckConstraint = "chat_model_configs_ai_provider_required_when_active" // chat_model_configs
|
|
CheckChatModelConfigsCompressionThresholdCheck CheckConstraint = "chat_model_configs_compression_threshold_check" // chat_model_configs
|
|
CheckChatModelConfigsContextLimitCheck CheckConstraint = "chat_model_configs_context_limit_check" // chat_model_configs
|
|
CheckChatUsageLimitConfigDefaultLimitMicrosCheck CheckConstraint = "chat_usage_limit_config_default_limit_micros_check" // chat_usage_limit_config
|
|
CheckChatUsageLimitConfigPeriodCheck CheckConstraint = "chat_usage_limit_config_period_check" // chat_usage_limit_config
|
|
CheckChatUsageLimitConfigSingletonCheck CheckConstraint = "chat_usage_limit_config_singleton_check" // chat_usage_limit_config
|
|
CheckChatAclOnlyOnRootChats CheckConstraint = "chat_acl_only_on_root_chats" // chats
|
|
CheckChatGroupAclNotNullJsonb CheckConstraint = "chat_group_acl_not_null_jsonb" // chats
|
|
CheckChatUserAclNotNullJsonb CheckConstraint = "chat_user_acl_not_null_jsonb" // chats
|
|
CheckChatsPinOrderArchivedCheck CheckConstraint = "chats_pin_order_archived_check" // chats
|
|
CheckChatsPinOrderParentCheck CheckConstraint = "chats_pin_order_parent_check" // chats
|
|
CheckOneTimePasscodeSet CheckConstraint = "one_time_passcode_set" // users
|
|
CheckUsersChatSpendLimitMicrosCheck CheckConstraint = "users_chat_spend_limit_micros_check" // users
|
|
CheckUsersEmailNotEmpty CheckConstraint = "users_email_not_empty" // users
|
|
CheckUsersServiceAccountLoginType CheckConstraint = "users_service_account_login_type" // users
|
|
CheckUsersUsernameMinLength CheckConstraint = "users_username_min_length" // users
|
|
CheckOrganizationIDNotZero CheckConstraint = "organization_id_not_zero" // custom_roles
|
|
CheckGroupAIBudgetsSpendLimitMicrosCheck CheckConstraint = "group_ai_budgets_spend_limit_micros_check" // group_ai_budgets
|
|
CheckGroupsChatSpendLimitMicrosCheck CheckConstraint = "groups_chat_spend_limit_micros_check" // groups
|
|
CheckMcpServerConfigsAuthTypeCheck CheckConstraint = "mcp_server_configs_auth_type_check" // mcp_server_configs
|
|
CheckMcpServerConfigsAvailabilityCheck CheckConstraint = "mcp_server_configs_availability_check" // mcp_server_configs
|
|
CheckMcpServerConfigsTransportCheck CheckConstraint = "mcp_server_configs_transport_check" // mcp_server_configs
|
|
CheckOauth2ProviderAppsClientTypeCheck CheckConstraint = "oauth2_provider_apps_client_type_check" // oauth2_provider_apps
|
|
CheckMaxProvisionerLogsLength CheckConstraint = "max_provisioner_logs_length" // provisioner_jobs
|
|
CheckNatsPortValidTcp CheckConstraint = "nats_port_valid_tcp" // replicas
|
|
CheckMaxLogsLength CheckConstraint = "max_logs_length" // workspace_agents
|
|
CheckSubsystemsNotNone CheckConstraint = "subsystems_not_none" // workspace_agents
|
|
CheckWorkspaceBuildsDeadlineBelowMaxDeadline CheckConstraint = "workspace_builds_deadline_below_max_deadline" // workspace_builds
|
|
CheckGroupAclIsObject CheckConstraint = "group_acl_is_object" // workspaces
|
|
CheckUserAclIsObject CheckConstraint = "user_acl_is_object" // workspaces
|
|
CheckTelemetryLockEventTypeConstraint CheckConstraint = "telemetry_lock_event_type_constraint" // telemetry_locks
|
|
CheckValidationMonotonicOrder CheckConstraint = "validation_monotonic_order" // template_version_parameters
|
|
CheckUsageEventTypeCheck CheckConstraint = "usage_event_type_check" // usage_events
|
|
CheckUserAIBudgetOverridesSpendLimitMicrosCheck CheckConstraint = "user_ai_budget_overrides_spend_limit_micros_check" // user_ai_budget_overrides
|
|
CheckUserAIProviderKeysAPIKeyCheck CheckConstraint = "user_ai_provider_keys_api_key_check" // user_ai_provider_keys
|
|
CheckUserSecretsEnabledRequiresTarget CheckConstraint = "user_secrets_enabled_requires_target" // user_secrets
|
|
CheckUserSkillsContentSize CheckConstraint = "user_skills_content_size" // user_skills
|
|
CheckUserSkillsDescriptionSize CheckConstraint = "user_skills_description_size" // user_skills
|
|
CheckUserSkillsNameFormat CheckConstraint = "user_skills_name_format" // user_skills
|
|
CheckUserSkillsNameSize CheckConstraint = "user_skills_name_size" // user_skills
|
|
CheckWorkspaceBuildOrchestrationsAttemptCountCheck CheckConstraint = "workspace_build_orchestrations_attempt_count_check" // workspace_build_orchestrations
|
|
CheckWorkspaceBuildOrchestrationsChildLogLevelCheck CheckConstraint = "workspace_build_orchestrations_child_log_level_check" // workspace_build_orchestrations
|
|
CheckWorkspaceBuildOrchestrationsChildParametersCheck CheckConstraint = "workspace_build_orchestrations_child_parameters_check" // workspace_build_orchestrations
|
|
CheckWorkspaceBuildOrchestrationsChildPresetVersionCheck CheckConstraint = "workspace_build_orchestrations_child_preset_version_check" // workspace_build_orchestrations
|
|
CheckWorkspaceBuildOrchestrationsCompletedChildCheck CheckConstraint = "workspace_build_orchestrations_completed_child_check" // workspace_build_orchestrations
|
|
CheckWorkspaceBuildOrchestrationsNextRetryAfterCheck CheckConstraint = "workspace_build_orchestrations_next_retry_after_check" // workspace_build_orchestrations
|
|
CheckWorkspaceBuildOrchestrationsStatusCheck CheckConstraint = "workspace_build_orchestrations_status_check" // workspace_build_orchestrations
|
|
)
|