gb/prompts/pass.md

8.8 KiB

VAULT MIGRATION PLAN - Multi-Tenant Structure

Hierarchy

tenant (cluster/deployment) ← INFRASTRUCTURE
    └── org (customer organization)
        ├── bot
        └── user

tenant ≠ org

  • tenant = deployment cluster (dev, staging, prod)
  • org = customer organization inside a tenant

VAULT PATH STRUCTURE

gbo/
├── tenants/                          # PER-TENANT (cluster/deployment)
│   └── {tenant_id}/                  # dev, staging, prod
│       ├── infrastructure/           # TENANT INFRASTRUCTURE
│       │   ├── tables/             # host, port, username, password
│       │   ├── drive/             # host, port, accesskey, secret
│       │   ├── cache/             # host, port, password
│       │   ├── email/             # smtp host, port, user, pass
│       │   ├── directory/          # Zitadel url
│       │   ├── llm/               # LLM endpoint
│       │   └── models/            # Model server url
│       │
│       └── config/                 # Tenant settings
│           ├── name
│           ├── domain
│           └── settings
│
├── orgs/                            # PER-ORGANIZATION (customer)
│   └── {org_id}/
│       ├── bots/
│       │   └── {bot_id}/
│       │       ├── email/         # Bot email credentials
│       │       ├── whatsapp/
│       │       ├── llm/           # Bot-specific LLM override
│       │       └── api-keys/
│       │
│       └── users/
│           └── {user_id}/
│               ├── email/         # User email credentials
│               └── oauth/
│
└── system/                          # GLOBAL FALLBACK
    ├── jwt/secret
    ├── tables/                      # Fallback if tenant not set
    ├── drive/
    ├── cache/
    ├── email/
    ├── llm/
    ├── directory/
    ├── security/
    ├── alm/
    ├── cloud/
    └── app/
│   │   │   │   │   ├── smtp-port
│   │   │   │   │   ├── smtp-user
│   │   │   │   │   ├── smtp-password
│   │   │   │   │   ├── imap-host
│   │   │   │   │   ├── imap-port
│   │   │   │   │   ├── imap-user
│   │   │   │   │   └── imap-password
│   │   │   │   │
│   │   │   │   ├── whatsapp/   # Bot WhatsApp
│   │   │   │   │   ├── phone-number-id
│   │   │   │   │   ├── business-account-id
│   │   │   │   │   └── api-key
│   │   │   │   │
│   │   │   │   ├── llm/         # Bot-specific LLM (override)
│   │   │   │   │   ├── provider
│   │   │   │   │   ├── model
│   │   │   │   │   └── api-key
│   │   │   │   │
│   │   │   │   └── api-keys/
│   │   │   │       ├── openai
│   │   │   │       ├── anthropic
│   │   │   │       └── custom/
│   │   │   │
│   │   │   └── {bot_id2}/
│   │   │       └── ...
│   │   │
│   │   └── users/
│   │       ├── {user_id}/
│   │       │   ├── email/       # User email credentials
│   │       │   │   ├── imap-host
│   │       │   │   ├── imap-port
│   │       │   │   ├── imap-user
│   │       │   │   ├── imap-password
│   │       │   │   ├── smtp-host
│   │       │   │   ├── smtp-port
│   │       │   │   ├── smtp-user
│   │       │   │   └── smtp-password
│   │       │   │
│   │       │   └── oauth/
│   │       │       ├── google/
│   │       │       │   ├── client-id
│   │       │       │   └── client-secret
│   │       │       ├── microsoft/
│   │       │       │   ├── client-id
│   │       │       │   └── client-secret
│   │       │       └── github/
│   │       │           ├── client-id
│   │       │           └── client-secret
│   │       │
│   │       └── {user_id2}/
│   │           └── ...
│   │
│   └── {org_id2}/
│       └── ...
│
├── system/                      # SYSTEM-WIDE (includes ALM/deployment)
│   ├── jwt/
│   │   └── secret
│   ├── tables/                # Database
│   │   ├── host
│   │   ├── port
│   │   ├── database
│   │   ├── username
│   │   └── password
│   ├── drive/                # Storage
│   │   ├── accesskey
│   │   └── secret
│   ├── cache/
│   │   └── url
│   ├── email/                # Global SMTP fallback
│   │   ├── smtp-host
│   │   ├── smtp-port
│   │   ├── smtp-user
│   │   ├── smtp-password
│   │   └── smtp-from
│   ├── llm/                 # Global LLM defaults
│   │   ├── url
│   │   ├── model
│   │   └── providers/
│   │       └── openai/
│   │           └── api-key
│   ├── models/              # Model serving
│   │   └── url
│   ├── directory/            # Zitadel
│   │   └── config
│   ├── security/
│   │   ├── require-auth
│   │   └── anonymous-paths
│   ├── alm/                  # ALM/Deployment (Forgejo)
│   │   ├── url
│   │   ├── token
│   │   └── default-org
│   ├── cloud/               # Cloud providers (AWS, etc)
│   │   ├── access-key
│   │   ├── secret-key
│   │   ├── region
│   │   └── s3-endpoint
│   └── app/                 # Application config
│       ├── url
│       ├── environment
│       └── disable-tls

ENV VARS → VAULT MAPPING

Current ENV Vault Path Scope
JWT_SECRET gbo/system/jwt/secret system
LLM_KEY gbo/system/llm/providers/openai/api-key system
OPENAI_API_KEY gbo/system/llm/providers/openai/api-key system
SMTP_HOST gbo/system/email/smtp-host system
SMTP_USER gbo/system/email/smtp-user system
SMTP_PASS gbo/system/email/smtp-password system
SMTP_FROM gbo/system/email/smtp-from system
FORGEJO_URL gbo/system/alm/url system
FORGEJO_TOKEN gbo/system/alm/token system
FORGEJO_DEFAULT_ORG gbo/system/alm/default-org system
AWS_ACCESS_KEY_ID gbo/system/cloud/access-key system
AWS_SECRET_ACCESS_KEY gbo/system/cloud/secret-key system
AWS_REGION gbo/system/cloud/region system
S3_ENDPOINT gbo/system/cloud/s3-endpoint system
ZITADEL_ISSUER_URL gbo/system/directory/zitadel-issuer system
ZITADEL_CLIENT_ID gbo/system/directory/zitadel-client-id system
REQUIRE_AUTH gbo/system/security/require-auth system
ANONYMOUS_PATHS gbo/system/security/anonymous-paths system
APP_URL gbo/system/app/url system
BOTSERVER_ENV gbo/system/app/environment system
LLM_URL gbo/system/llm/url system
LLM_MODEL gbo/system/llm/model system
BOTMODELS_URL gbo/system/models/url system

CODE PATTERNS

Get Bot Email (tenant → bot)

async fn get_bot_email(state: &AppState, org_id: Uuid, bot_id: Uuid) -> Result<BotEmail> {
    // Try per-bot Vault path first
    let path = format!("gbo/tenants/{}/bots/{}/email", org_id, bot_id);
    if let Ok(creds) = state.secrets.get_secret(&path).await {
        return Ok(BotEmail::from_vault(creds));
    }
    // Fallback: system SMTP
    let system = state.secrets.get_secret("gbo/system/email").await?;
    Ok(BotEmail::from_system(system))
}

Get User Email (tenant → user)

async fn get_user_email(state: &AppState, org_id: Uuid, user_id: Uuid) -> Result<UserEmail> {
    let path = format!("gbo/tenants/{}/users/{}/email", org_id, user_id);
    state.secrets.get_secret(&path).await
}

Get Bot LLM (tenant → bot, with system fallback)

async fn get_bot_llm(state: &AppState, org_id: Uuid, bot_id: Uuid) -> Result<LlmConfig> {
    // Bot-specific override
    let bot_path = format!("gbo/tenants/{}/bots/{}/llm", org_id, bot_id);
    if let Ok(config) = state.secrets.get_secret(&bot_path).await {
        return Ok(LlmConfig::from_vault(config));
    }
    // System default
    state.secrets.get_secret("gbo/system/llm").await
}