Validate keys in `glab config set` against the config schema
## Summary
`glab config set <key> <value>` accepts any arbitrary key without validation. Unknown keys get written to the config file and `glab config get` reads them back, but nothing in the codebase consumes them. This creates a UX trap: users discover plausible-sounding keys (or invent them based on docs or intuition), set them, see the value round-trip via `get`, and reasonably assume they're being applied.
## Example
Surfaced in [#8334](https://gitlab.com/gitlab-org/cli/-/work_items/8334), where a user set `oauth_scopes` (not a real config key) and concluded the CLI was ignoring it:
```
glab config set oauth_scopes "openid profile read_user read_api read_repository" --host <self-managed-host>
glab config get oauth_scopes --host <self-managed-host>
# => openid profile read_user read_api read_repository
```
The value silently sits in `~/.config/glab-cli/config.yml` and nothing reads it.
## Proposed work
### 1. Sweep [`internal/config/config.yaml.lock`](https://gitlab.com/gitlab-org/cli/-/blob/main/internal/config/config.yaml.lock) for missing keys
The lock file is already the canonical schema (consumed by `gen.go` → `config_stub.go` to produce the default config tree), but it's currently incomplete. Keys read by the codebase but absent from the lock:
- **User-settable** (should be added): `client_id`, `ca_cert`, `client_cert`, `client_key`, `skip_tls_verify`, `use_keyring`, `job_token`, `user`, `auto_download`, `branch_prefix`
- **Internal state** (CLI-managed, decide whether to register with a marker or exclude from validation): `is_oauth2`, `oauth2_expiry_date`, `oauth2_refresh_token`, `refresh_token`, `last_update_check`
Add the user-settable ones with appropriate scoping (global vs per-host) and inline doc comments.
### 2. Wire validation into [`internal/commands/config/set/config_set.go`](https://gitlab.com/gitlab-org/cli/-/blob/main/internal/commands/config/set/config_set.go)
Load the lock-file key set at init, check `o.key` against it (including prefix-matched families like `duo_cli_*` and `orbit_local_*`), and either:
- **Warn-but-allow** — additive, lowest risk, preserves existing configs with stray keys.
- **Reject by default with a `--force` escape** — stronger signal, but breaks users who have stray keys today.
Suggested starting point: warn-but-allow, reassess after some time in the field.
### 3. Document the convention
Update [`internal/config/Readme.md`](https://gitlab.com/gitlab-org/cli/-/blob/main/internal/config/Readme.md) so future contributors know that adding a new config key requires updating the lock file. Consider a CI lint or test that diffs `cfg.Get(..., "<key>")` literals against the lock to catch drift.
## Out of scope
- Whether `oauth_scopes` itself should become a real, honored config key (separate design conversation; see discussion in #8334).
- Migrating users' existing configs to remove orphaned keys.
issue