Skip to content

データモデル設計

GitHub Issue: #2 データモデル設計#53 設計書更新

モデル関連図

mermaid
erDiagram
    APIKey ||--o| ServiceType : "preset"
    APIKey ||--o| CustomKey : "custom"
    ServiceType ||--|| KeyCategory : "belongs to"
    CustomKey ||--|| CustomCategory : "belongs to"
    CustomKeyStore ||--|{ CustomKey : "manages"
    CustomKeyStore ||--|{ CustomCategory : "manages"
    ProxyRoute ||--|| ServiceType : "routes"

    APIKey {
        UUID id
        ServiceType service "optional"
        CustomKey customKey "optional"
        String envVarName
        Bool isConfigured
    }

    ServiceType {
        String displayName
        String envVarName
        KeyCategory category
        String tokenPrefix "optional"
        URL setupURL "optional"
        String systemImage
        Bool isWebAuth
        URL loginURL "optional"
    }

    KeyCategory {
        String rawValue "display name"
        Color color
        String systemImage
    }

    CustomKey {
        UUID id
        String envVarName
        String displayName
        UUID categoryId
    }

    CustomCategory {
        UUID id
        String name
        String systemImage
        String colorHex
    }

    ProxyRoute {
        String host
        String targetScheme
        String keychainAccount
        String headerName
        String headerValuePrefix
    }

ServiceType

20 サービスを 6 カテゴリに分類。

プロパティ

プロパティ説明
displayNameStringUI 表示名
envVarNameString環境変数名
categoryKeyCategory所属カテゴリ
tokenPrefixString?期待されるトークンプレフィックス
setupURLURL?トークン発行ページ
systemImageStringSF Symbols 名
isWebAuthBoolWeb 認証タイプかどうか
loginURLURL?Web ログインページ

サービス定義一覧

AI API

ServicedisplayNameenvVarNametokenPrefixcategory
anthropicAnthropic (Claude)ANTHROPIC_API_KEYsk-ant-ai
openAIOpenAI (GPT)OPENAI_API_KEYsk-ai
xAIxAI (Grok)XAI_API_KEYxai-ai
higgsfieldHiggsfieldHIGGSFIELD_API_KEY-ai

AI Web (Web 認証)

ServicedisplayNameenvVarNameloginURL
anthropicWebAnthropic WebANTHROPIC_WEB_AUTHclaude.ai
openAIWebOpenAI PlatformOPENAI_WEB_AUTHplatform.openai.com
googleAIStudioGoogle AI StudioGOOGLE_AI_STUDIO_AUTHaistudio.google.com
huggingFaceHugging FaceHUGGINGFACE_AUTHhuggingface.co
replicateWebReplicateREPLICATE_AUTHreplicate.com

Code & Git

ServicedisplayNameenvVarNametokenPrefix
githubGitHubGITHUB_TOKENghp_
gitlabGitLabGITLAB_TOKENglpat-

Cloud & Infra

ServicedisplayNameenvVarNametokenPrefix
cloudflareAPICloudflare APICLOUDFLARE_API_TOKEN-
cloudflareAccountCloudflare AccountCLOUDFLARE_ACCOUNT_ID-
tailscaleTailscaleTAILSCALE_AUTH_KEYtskey-

Communication

ServicedisplayNameenvVarNametokenPrefix
discordDiscordDISCORD_TOKEN-
slackSlackSLACK_APP_TOKENxapp-

Developer Tools

ServicedisplayNameenvVarNametokenPrefix
qiitaQiitaQIITA_TOKEN-

KeyCategory

6 つのビルトインカテゴリ。

swift
enum KeyCategory: String, CaseIterable, Identifiable {
    case ai = "AI API"
    case webAuth = "AI Web"
    case codeAndGit = "Code & Git"
    case cloud = "Cloud & Infra"
    case communication = "Communication"
    case devTools = "Developer Tools"
}
CategorycolorsystemImageHex
aiPurplebrain.head.profile#7C3AED
webAuthPinkglobe#DB2777
codeAndGitOrangechevron.left.forwardslash.chevron.right#EA580C
cloudBluecloud.fill#0284C7
communicationGreenbubble.left.and.bubble.right.fill#059669
devToolsGraywrench.and.screwdriver.fill#6B7280

APIKey

プリセットサービスとカスタムキーの両方を統一的に扱うモデル。

swift
struct APIKey: Identifiable {
    let id: UUID
    let service: ServiceType?      // プリセットの場合
    let customKey: CustomKey?       // カスタムの場合
    var envVarName: String
    var isConfigured: Bool          // Keychain に値が存在するか
}

算出プロパティ

プロパティ説明
displayNameStringservice?.displayName ?? customKey?.displayName
systemImageStringサービスまたはカテゴリのアイコン
categoryColorColor所属カテゴリの色
setupURLURL?トークン発行ページ (プリセットのみ)
tokenPrefixString?プレフィックス (プリセットのみ)
isCustomBoolcustomKey != nil

初期化パターン

swift
// プリセットキー
APIKey(service: .anthropic)
// → envVarName = "ANTHROPIC_API_KEY", displayName = "Anthropic (Claude)"

// カスタムキー
APIKey(customKey: CustomKey(envVarName: "MY_KEY", displayName: "My Key", categoryId: ...))

設計ポイント

  • シークレット値はモデルに持たない: 表示時に都度 Keychain から取得
  • isConfigured は stored property: Keychain アクセスのパフォーマンスを考慮し、loadKeys() 時に一括チェック
  • デュアル初期化: service / customKey の排他的なオプショナルで柔軟性を確保

CustomKeyStore

ユーザー定義のカテゴリとキーを管理するシングルトン。

swift
final class CustomKeyStore {
    static let shared = CustomKeyStore()

    var categories: [CustomCategory]     // ユーザー定義カテゴリ
    var keys: [CustomKey]                // ユーザー定義キー
    var categoryOverrides: [String: ...]  // プリセットキーのカテゴリ変更
}
データ永続化キー
categoriesUserDefaults (JSON)"custom_categories"
keysUserDefaults (JSON)"custom_keys"
categoryOverridesUserDefaults (JSON)"category_overrides"

ProxyRoute

プロキシサーバーのルーティングテーブル。静的定義。

swift
struct ProxyRoute {
    let host: String              // "api.anthropic.com"
    let targetScheme: String      // "https"
    let keychainAccount: String   // "ANTHROPIC_API_KEY"
    let headerName: String        // "x-api-key"
    let headerValuePrefix: String // "" or "Bearer "

    static func route(for host: String) -> ProxyRoute?
}
HostkeychainAccountheaderNameheaderValuePrefix
api.anthropic.comANTHROPIC_API_KEYx-api-key(なし)
api.openai.comOPENAI_API_KEYAuthorizationBearer
api.x.aiXAI_API_KEYAuthorizationBearer

OnboardingStep

5 段階のオンボーディングウィザード。

swift
enum OnboardingStep: Int, CaseIterable {
    case welcome = 0
    case modeSelect       // Standard / Proxy 選択
    case registerKeys     // キー登録案内 (スキップ可)
    case setupShell       // シェル設定 (スキップ可)
    case completion
}
SteptitlecanSkip
welcome"AI KeyChain へようこそ"false
modeSelect"モード選択"false
registerKeys"キー登録"true
setupShell"シェル設定"true
completion"セットアップ完了"false

AI開発チームのための鍵管理ツール