관리자 AI 제공자 연결 기능 추가 (claude·codex·agy·openrouter 토큰 붙여넣기 연결)
Some checks failed
API contract / OpenAPI type drift (push) Failing after 12m57s
Some checks failed
API contract / OpenAPI type drift (push) Failing after 12m57s
관리자 /admin/ai 화면에서 provider 토큰(OAuth 액세스 토큰 또는 API 키)을 발급받아 붙여넣으면 DB에 암호화 저장되고, shared-secret으로 보호되는 게이트웨이 내부 엔드포인트로 push되어 실행 중인 엔진 컨테이너에 즉시 적용된다. NAS처럼 게이트웨이가 컨테이너로 도는 환경에서 CLI·로컬 PC 의존 없이 claude_api·openai·openrouter를 연결할 수 있다. - 게이트웨이: openrouter 어댑터 신설(chat/completions), OAuth 토큰이면 Anthropic Bearer 헤더, /internal/provider-credentials GET/POST와 boot_id 기반 재동기화 - API: app.admin_provider_credential 테이블(idempotent DDL), stdlib HMAC-CTR+MAC 암호화 서비스(PROVIDER_CREDENTIAL_SECRET, 폴백 SESSION_SECRET), /admin/providers CRUD·검증 라우트 - 웹: 제공자 연결 패널(저장·검증·해제, 토큰 힌트만 표시), 엔진 선택에 OpenRouter 추가, api.gen.ts 재생성 - compose: api 서비스에 PROVIDER_CREDENTIAL_SECRET 전달(로컬·NAS)
This commit is contained in:
parent
6831a79ffb
commit
4b45d33142
22 changed files with 2088 additions and 13 deletions
|
|
@ -180,6 +180,70 @@ export interface paths {
|
|||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/providers": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/**
|
||||
* List Providers
|
||||
* @description 연결 가능한 AI provider 목록과 자격증명 상태를 반환한다.
|
||||
*/
|
||||
get: operations["list_providers_admin_providers_get"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/providers/{provider}/credential": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
/**
|
||||
* Put Provider Credential
|
||||
* @description 사용자가 발급받아 붙여넣은 provider 토큰을 암호화 저장하고 게이트웨이에 주입한다.
|
||||
*/
|
||||
put: operations["put_provider_credential_admin_providers__provider__credential_put"];
|
||||
post?: never;
|
||||
/**
|
||||
* Delete Provider Credential
|
||||
* @description 저장된 provider 자격증명을 삭제하고 게이트웨이 주입 상태를 재동기화한다.
|
||||
*/
|
||||
delete: operations["delete_provider_credential_admin_providers__provider__credential_delete"];
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/providers/{provider}/verify": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/**
|
||||
* Verify Provider Credential
|
||||
* @description 저장된 토큰으로 provider에 실제 요청을 보내 연결을 확인한다.
|
||||
*/
|
||||
post: operations["verify_provider_credential_admin_providers__provider__verify_post"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/tickets": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
|
@ -2694,7 +2758,7 @@ export interface components {
|
|||
* Engine Mode
|
||||
* @enum {string}
|
||||
*/
|
||||
engine_mode: "claude_cli" | "claude_api" | "codex_cli" | "agy_cli" | "openai" | "solar";
|
||||
engine_mode: "claude_cli" | "claude_api" | "codex_cli" | "agy_cli" | "openai" | "openrouter" | "solar";
|
||||
/** Engine Url */
|
||||
engine_url: string;
|
||||
/** Model */
|
||||
|
|
@ -2915,6 +2979,98 @@ export interface components {
|
|||
/** Version */
|
||||
version: number;
|
||||
};
|
||||
/** AdminProviderCredentialRequest */
|
||||
AdminProviderCredentialRequest: {
|
||||
/**
|
||||
* Auth Kind
|
||||
* @default api_key
|
||||
* @enum {string}
|
||||
*/
|
||||
auth_kind: "api_key" | "oauth_token";
|
||||
/** Token */
|
||||
token: string;
|
||||
};
|
||||
/** AdminProviderCredentialResponse */
|
||||
AdminProviderCredentialResponse: {
|
||||
/** Auth Kind */
|
||||
auth_kind: string;
|
||||
gateway_sync: components["schemas"]["AdminProviderGatewaySync"];
|
||||
/** Provider */
|
||||
provider: string;
|
||||
/** Token Hint */
|
||||
token_hint: string;
|
||||
/** Updated At */
|
||||
updated_at?: number | null;
|
||||
/** Updated By */
|
||||
updated_by?: string | null;
|
||||
};
|
||||
/** AdminProviderCredentialStatus */
|
||||
AdminProviderCredentialStatus: {
|
||||
/** Allowed Auth Kinds */
|
||||
allowed_auth_kinds: string[];
|
||||
/** Auth Kind */
|
||||
auth_kind?: string | null;
|
||||
/** Connected */
|
||||
connected: boolean;
|
||||
/** Description */
|
||||
description: string;
|
||||
/** Guide */
|
||||
guide: string;
|
||||
/** Label */
|
||||
label: string;
|
||||
/** Last Verified At */
|
||||
last_verified_at?: number | null;
|
||||
/** Last Verify Error */
|
||||
last_verify_error?: string | null;
|
||||
/** Last Verify Ok */
|
||||
last_verify_ok?: boolean | null;
|
||||
/** Provider */
|
||||
provider: string;
|
||||
/** Token Hint */
|
||||
token_hint?: string | null;
|
||||
/** Token Page Label */
|
||||
token_page_label: string;
|
||||
/** Token Page Url */
|
||||
token_page_url: string;
|
||||
/** Updated At */
|
||||
updated_at?: number | null;
|
||||
/** Updated By */
|
||||
updated_by?: string | null;
|
||||
};
|
||||
/** AdminProviderDeleteResponse */
|
||||
AdminProviderDeleteResponse: {
|
||||
gateway_sync: components["schemas"]["AdminProviderGatewaySync"];
|
||||
/** Ok */
|
||||
ok: boolean;
|
||||
/** Provider */
|
||||
provider: string;
|
||||
};
|
||||
/** AdminProviderGatewaySync */
|
||||
AdminProviderGatewaySync: {
|
||||
/** Boot Id */
|
||||
boot_id?: string | null;
|
||||
/** Detail */
|
||||
detail?: string | null;
|
||||
/** Synced */
|
||||
synced: boolean;
|
||||
};
|
||||
/** AdminProviderVerifyResponse */
|
||||
AdminProviderVerifyResponse: {
|
||||
/** Detail */
|
||||
detail: string;
|
||||
/** Ok */
|
||||
ok: boolean;
|
||||
/** Provider */
|
||||
provider: string;
|
||||
/** Verified At */
|
||||
verified_at?: number | null;
|
||||
};
|
||||
/** AdminProvidersResponse */
|
||||
AdminProvidersResponse: {
|
||||
gateway_sync: components["schemas"]["AdminProviderGatewaySync"];
|
||||
/** Providers */
|
||||
providers: components["schemas"]["AdminProviderCredentialStatus"][];
|
||||
};
|
||||
/** AdminServiceHealth */
|
||||
AdminServiceHealth: {
|
||||
/** Detail */
|
||||
|
|
@ -5093,7 +5249,7 @@ export interface components {
|
|||
* Provider
|
||||
* @enum {string}
|
||||
*/
|
||||
provider: "claude_cli" | "claude_api" | "codex_cli" | "agy_cli" | "openai" | "solar";
|
||||
provider: "claude_cli" | "claude_api" | "codex_cli" | "agy_cli" | "openai" | "openrouter" | "solar";
|
||||
/**
|
||||
* Source
|
||||
* @enum {string}
|
||||
|
|
@ -11843,6 +11999,144 @@ export interface operations {
|
|||
};
|
||||
};
|
||||
};
|
||||
list_providers_admin_providers_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: {
|
||||
"__Host-vignette_sid"?: string | null;
|
||||
vignette_sid?: string | null;
|
||||
};
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["AdminProvidersResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
put_provider_credential_admin_providers__provider__credential_put: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
provider: string;
|
||||
};
|
||||
cookie?: {
|
||||
"__Host-vignette_sid"?: string | null;
|
||||
vignette_sid?: string | null;
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["AdminProviderCredentialRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["AdminProviderCredentialResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete_provider_credential_admin_providers__provider__credential_delete: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
provider: string;
|
||||
};
|
||||
cookie?: {
|
||||
"__Host-vignette_sid"?: string | null;
|
||||
vignette_sid?: string | null;
|
||||
};
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["AdminProviderDeleteResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
verify_provider_credential_admin_providers__provider__verify_post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
provider: string;
|
||||
};
|
||||
cookie?: {
|
||||
"__Host-vignette_sid"?: string | null;
|
||||
vignette_sid?: string | null;
|
||||
};
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["AdminProviderVerifyResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
list_tickets_admin_tickets_get: {
|
||||
parameters: {
|
||||
query?: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue