feat(web): Selectel service-user account form (IAM credentials)

Replace the single API-key field with 4 IAM service-user fields
(username, password, account_id, project_name) matching the new
backend contract; map 400 "invalid provider credentials" to a
user-facing message.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
This commit is contained in:
2026-07-04 20:23:34 +07:00
parent 568452846a
commit be408a216c
4 changed files with 170 additions and 37 deletions
+5 -1
View File
@@ -79,7 +79,11 @@ describe("api client", () => {
it("sends secret on account creation but path has no secret leakage in response typing", async () => {
const spy = mockFetch({ id: "a2", provider: "selectel", comment: "prod" })
await api.createAccount(PROJECT_ID, { provider: "selectel", secret: "TOKEN", comment: "prod" })
await api.createAccount(PROJECT_ID, {
provider: "selectel",
secret: { username: "svc-user", password: "TOKEN", account_id: "123456", project_name: "default" },
comment: "prod",
})
const [, opts] = spy.mock.calls[0]
expect((opts as RequestInit).method).toBe("POST")
expect(String((opts as RequestInit).body)).toContain("TOKEN")
+7 -1
View File
@@ -3,7 +3,13 @@ export interface Project { id: string; name: string }
export interface AuthState { user: User; project: Project }
export interface Account { id: string; provider: string; comment: string }
export interface CreateAccountInput { provider: string; secret: string; comment: string }
export interface SelectelSecret {
username: string
password: string
account_id: string
project_name: string
}
export interface CreateAccountInput { provider: string; secret: SelectelSecret; comment: string }
export interface RecordDTO { type: string; name: string; ttl: number; values: string[] }
export interface Template { id: string; name: string; records: RecordDTO[]; version: number }