Architecture Options Report
Analysis of deployment models, admin areas, API key management, team permissions, and multi-tenancy strategy for Quox's enterprise features.
Deployment Models, Key Management, and Multi-Tenancy Strategy
Date: 2026-01-21 Author: Claude (AI Architecture Analysis) Status: Decision Required
Executive Summary
This report analyzes deployment and architecture options for Quox, addressing:
- Deployment Model - Self-hosted vs hosted vs hybrid
- Admin/Superuser Area - System-level configuration and monitoring
- API Key Management - Who controls which keys and how
- Team Permissions - User autonomy vs admin control
- Future Hosted Service - Architecture decisions to preserve optionality
Recommendation: Adopt a "Self-Hosted First with Hosted Option" model using hierarchical key management with configurable delegation policies.
1. Deployment Model Analysis
Option A: Pure Self-Hosted (Open Source)
Model: Users download and run Quox on their own infrastructure.
Examples: n8n self-hosted, Mattermost self-hosted, GitLab self-managed
Pros:
- Full data sovereignty and privacy
- No vendor lock-in
- Compliance-friendly (HIPAA, GDPR, SOC 2)
- Community contributions
- No recurring SaaS costs
Cons:
- Admin must manage infrastructure
- Updates/patches are manual
- Support burden on community/docs
- No recurring revenue (unless enterprise features)
Revenue Model:
- Enterprise features (SSO, audit logs, priority support)
- Paid support contracts
- Professional services
Option B: Pure Hosted (SaaS)
Model: Quox runs as a hosted service, users sign up online.
Examples: n8n Cloud, GitLab.com
Pros:
- Recurring revenue (subscriptions)
- Faster onboarding
- Automatic updates
- Centralized monitoring
Cons:
- Infrastructure costs
- Data privacy concerns for some users
- Multi-tenant complexity
- Support obligations
Option C: Hybrid Model (Recommended)
Model: Primary focus on self-hosted, with optional hosted service for users who want convenience.
Examples:
Implementation:
┌─────────────────────────────────────────────────────────────────┐
│ QUOX DISTRIBUTION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ SELF-HOSTED │ │ HOSTED │ │
│ │ (Primary) │ │ (Optional) │ │
│ ├──────────────────┤ ├──────────────────┤ │
│ │ • Open source │ │ • Multi-tenant │ │
│ │ • Full control │ │ • Managed by us │ │
│ │ • BYOK │ │ • Quick start │ │
│ │ • No data leaves │ │ • Subscription │ │
│ │ • Free forever │ │ • Free tier │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ SAME CODEBASE │ │
│ │ (with feature │ │
│ │ flags) │ │
│ └───────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Key Principle: One codebase that works for both models, with configuration/feature flags differentiating them.
2. Admin/Superuser Area Design
The Problem
Self-hosted admins need a privileged area to:
- Start/stop services
- View system logs
- Configure system-wide API keys
- Manage secrets
- Monitor health
- Configure integrations
This is fundamentally different from "organization admin" — it's instance admin.
Proposed: Instance Admin vs Org Admin Separation
┌─────────────────────────────────────────────────────────────────┐
│ ADMIN HIERARCHY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ INSTANCE ADMIN (Superuser) │
│ ├── System Settings │
│ │ ├── Service Management (start/stop/restart) │
│ │ ├── System API Keys (Claude, OpenAI, etc.) │
│ │ ├── Email/SMTP Configuration │
│ │ ├── SSO/OIDC Configuration │
│ │ ├── License Management │
│ │ └── Backup/Restore │
│ ├── Monitoring │
│ │ ├── Service Health Dashboard │
│ │ ├── System Logs Viewer │
│ │ ├── Resource Usage (CPU, Memory, Disk) │
│ │ └── Active Sessions │
│ ├── Security │
│ │ ├── Audit Log (instance-wide) │
│ │ ├── Rate Limit Configuration │
│ │ ├── IP Allowlisting │
│ │ └── Security Policies │
│ └── Organizations │
│ ├── Create/Delete Organizations │
│ ├── Impersonate Users (for support) │
│ └── Organization Quotas │
│ │
│ ORG ADMIN (Per-Organization) │
│ ├── Members & Roles │
│ ├── Teams │
│ ├── Org-Level Secrets │
│ ├── Org Audit Log │
│ └── Billing (if hosted) │
│ │
└─────────────────────────────────────────────────────────────────┘
Database Schema Addition
-- Instance-level configuration (single row, key-value store)
CREATE TABLE instance_config (
key TEXT PRIMARY KEY,
value TEXT,
encrypted INTEGER DEFAULT 0,
updated_at TEXT DEFAULT (datetime('now')),
updated_by TEXT
);
-- Instance admin users (separate from org roles)
CREATE TABLE instance_admins (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id),
role TEXT NOT NULL DEFAULT 'admin', -- admin, readonly
created_at TEXT DEFAULT (datetime('now')),
created_by TEXT
);
-- System-level API keys
CREATE TABLE system_api_keys (
id TEXT PRIMARY KEY,
provider TEXT NOT NULL, -- 'anthropic', 'openai', 'elevenlabs', etc.
name TEXT NOT NULL,
key_ciphertext TEXT NOT NULL, -- Encrypted
is_default INTEGER DEFAULT 0,
usage_policy TEXT DEFAULT 'all', -- 'all', 'org_admin_only', 'disabled'
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT
);
-- System logs (recent, rotated)
CREATE TABLE system_logs (
id TEXT PRIMARY KEY,
service TEXT NOT NULL,
level TEXT NOT NULL, -- error, warn, info, debug
message TEXT NOT NULL,
metadata_json TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
UI Access Pattern
URL Structure:
/admin/* → Instance Admin (requires instance_admin role)
/settings/* → Org Settings (requires org admin role)
/dashboard/* → Regular user dashboard
First User Flow:
1. First user to sign up becomes instance admin
2. Can create organizations
3. Can designate other instance admins
3. API Key Management Strategy
The Core Question
Who controls which API keys? Can teams/users bring their own?
Option 1: System Keys Only (Restrictive)
Model: Instance admin configures all API keys. Users cannot add their own.
Instance Admin
└── System API Keys (Anthropic, OpenAI, etc.)
└── All orgs/users use these keys
Pros: Simple, centralized control, predictable costs Cons: No user flexibility, admin bottleneck
Use Case: Corporate deployments where IT controls all resources
Option 2: User Keys Only (BYOK-Only)
Model: No system keys. Every user must provide their own.
User
└── Personal API Keys
└── Used for their workflows
Pros: Zero cost for operator, full user autonomy Cons: Onboarding friction, no fallback, complex for teams
Use Case: Developer tools like JetBrains AI BYOK, VS Code BYOK
Option 3: Hierarchical with Delegation (Recommended)
Model: Keys cascade from instance → org → team → user with configurable policies.
┌─────────────────────────────────────────────────────────────────┐
│ KEY HIERARCHY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ INSTANCE LEVEL (Admin) │
│ ├── System Default Keys (Anthropic, OpenAI, etc.) │
│ ├── Policy: Allow org override? [yes/no] │
│ └── Policy: Allow user BYOK? [yes/no] │
│ │ │
│ ▼ │
│ ORG LEVEL (Org Admin) │
│ ├── Org Keys (override system, if allowed) │
│ ├── Policy: Allow team override? [yes/no] │
│ └── Policy: Allow user BYOK? [yes/no] │
│ │ │
│ ▼ │
│ TEAM LEVEL (Team Admin) │
│ ├── Team Keys (override org, if allowed) │
│ └── Policy: Allow user BYOK? [yes/no] │
│ │ │
│ ▼ │
│ USER LEVEL │
│ └── Personal Keys (BYOK, if allowed) │
│ │
└─────────────────────────────────────────────────────────────────┘
Resolution Order:
User Key → Team Key → Org Key → System Key → Error
Policy Configuration Examples
Corporate Lockdown:
{
"instance_policy": {
"allow_org_keys": false,
"allow_user_byok": false,
"require_approval_for_new_providers": true
}
}
All users use system keys. No overrides allowed.
Startup Flexible:
{
"instance_policy": {
"allow_org_keys": true,
"allow_user_byok": true,
"default_to_system_keys": true
}
}
System keys available by default, users can override with their own.
BYOK-Only (No Central Keys):
{
"instance_policy": {
"system_keys_enabled": false,
"require_user_byok": true
}
}
No system keys, users must provide their own.
Database Schema for Key Hierarchy
-- Key policies at each level
CREATE TABLE key_policies (
id TEXT PRIMARY KEY,
scope_type TEXT NOT NULL, -- 'instance', 'org', 'team', 'user'
scope_id TEXT, -- null for instance, org_id, team_id, user_id
allow_override INTEGER DEFAULT 1,
allow_byok INTEGER DEFAULT 1,
allowed_providers TEXT, -- JSON array: ['anthropic', 'openai']
created_at TEXT,
updated_at TEXT
);
-- API keys at any scope level
CREATE TABLE api_keys (
id TEXT PRIMARY KEY,
scope_type TEXT NOT NULL, -- 'instance', 'org', 'team', 'user'
scope_id TEXT,
provider TEXT NOT NULL, -- 'anthropic', 'openai', 'elevenlabs'
name TEXT NOT NULL,
key_ciphertext TEXT NOT NULL,
key_preview TEXT, -- Last 4 chars for identification
is_active INTEGER DEFAULT 1,
usage_count INTEGER DEFAULT 0,
last_used_at TEXT,
created_by TEXT REFERENCES users(id),
created_at TEXT DEFAULT (datetime('now')),
UNIQUE(scope_type, scope_id, provider, name)
);
Key Resolution Function
async function resolveApiKey(provider, context) {
const { userId, teamId, orgId } = context;
// 1. Check user key (if BYOK allowed)
if (userId) {
const userKey = await getKey('user', userId, provider);
if (userKey && await isBYOKAllowed('user', userId)) {
return userKey;
}
}
// 2. Check team key (if override allowed)
if (teamId) {
const teamKey = await getKey('team', teamId, provider);
if (teamKey && await isOverrideAllowed('team', teamId)) {
return teamKey;
}
}
// 3. Check org key (if override allowed)
if (orgId) {
const orgKey = await getKey('org', orgId, provider);
if (orgKey && await isOverrideAllowed('org', orgId)) {
return orgKey;
}
}
// 4. Fall back to system key
const systemKey = await getKey('instance', null, provider);
if (systemKey) {
return systemKey;
}
throw new Error(`No API key available for provider: ${provider}`);
}
4. Team Permission Models
Question: How much autonomy do teams have?
Model A: Centralized (Admin Controls Everything)
Instance Admin
└── Creates all orgs, teams, users
└── Assigns all roles
└── Configures all keys
Pros: Full control, predictable Cons: Admin bottleneck, doesn't scale
Model B: Delegated (Admins Create Orgs, Org Admins Manage)
Instance Admin
└── Creates orgs, assigns org owners
└── Org Owner
└── Creates teams, invites users
└── Team Admin
└── Manages team members
Pros: Scales well, clear hierarchy Cons: Need clear policies on what each level can do
Model C: Self-Service (Recommended for Hosted)
Any User
└── Can create own org (rate limited)
└── Becomes org owner
└── Invites team members
Pros: Low friction, viral growth Cons: Abuse potential, resource management
Recommended: Configurable Model
The instance admin chooses which model to use:
{
"user_permissions": {
"can_create_org": true, // Self-hosted: false, Hosted: true
"max_orgs_per_user": 3, // Limit for hosted
"require_email_domain": null, // Corporate: "company.com"
"require_invite": false // Closed beta: true
}
}
5. Future Hosted Service Considerations
Architecture Decisions to Preserve Optionality
| Decision | Self-Hosted | Hosted | Solution |
|---|---|---|---|
| Database | SQLite (single file) | PostgreSQL (managed) | Abstract database layer |
| File Storage | Local filesystem | S3/R2 | Storage interface |
| Auth | Local passwords | OAuth + local | Both supported |
| Secrets | Local encryption | KMS | Pluggable crypto |
| Multi-tenancy | Single org | Many orgs | Always org-scoped |
| Billing | None | Stripe | Feature flag |
Key Abstractions Needed
// Database abstraction
const db = process.env.DATABASE_URL?.startsWith('postgres')
? new PostgresAdapter(process.env.DATABASE_URL)
: new SqliteAdapter(process.env.AUTH_DB_PATH);
// Storage abstraction
const storage = process.env.S3_BUCKET
? new S3Storage(config)
: new LocalStorage(process.env.STORAGE_PATH);
// Secrets abstraction
const secrets = process.env.KMS_KEY_ID
? new KMSSecrets(config)
: new LocalSecrets(process.env.MASTER_KEY);
Hosted-Specific Features (Behind Feature Flags)
const HOSTED_FEATURES = {
billing: process.env.STRIPE_KEY !== undefined,
usageMetering: process.env.HOSTED === 'true',
automaticBackups: process.env.HOSTED === 'true',
multiRegion: process.env.HOSTED === 'true',
freeTrials: process.env.HOSTED === 'true'
};
6. Recommendations Summary
Deployment Model
✅ Hybrid: Self-hosted first, hosted option later
- Open source core with all essential features
- Hosted version uses same codebase
- Enterprise features for monetization
Admin Area
✅ Separate Instance Admin from Org Admin
- Instance Admin: System settings, logs, system keys
- Org Admin: Members, teams, org settings
- First user becomes instance admin
Key Management
✅ Hierarchical with configurable delegation
- Instance → Org → Team → User cascade
- Policies at each level control what's allowed
- BYOK optional and configurable
Team Permissions
✅ Configurable self-service model
- Default: Admins create orgs
- Optional: Users can create orgs (hosted)
- Rate limits and quotas for abuse prevention
Future Hosting
✅ Build abstractions now
- Database layer (SQLite ↔ PostgreSQL)
- Storage layer (Local ↔ S3)
- Secrets layer (Local ↔ KMS)
- Feature flags for hosted-specific features
7. Implementation Priority
Phase A (Complete)
- User authentication
- Organization management
- Basic RBAC
Phase A.5 (New - Recommended)
- Instance Admin separation
- System API key management
- Key policy configuration
- Admin dashboard (logs, health)
Phase B (As Planned)
- Organization hierarchy (divisions, departments, teams)
- Key hierarchy implementation
- Team-level key management
Phase C (As Planned)
- Human-in-the-loop
- Inbox and approvals
Phase D (As Planned)
- Workflow builder
8. Decision Points Requiring Your Input
-
Default Key Policy: Should new instances default to:
- (a) System keys only (admin must configure)
- (b) BYOK required (no system keys)
- (c) Both available (configurable)
-
Org Creation: Should users be able to create their own orgs, or admin-only?
-
Instance Admin UI: Should this be:
- (a) Integrated into main dashboard (with role check)
- (b) Separate application/port
- (c) CLI-only initially
-
Hosted Service Timeline:
- (a) Build abstractions now, launch hosted later
- (b) Focus on self-hosted only for now
- (c) Launch hosted MVP alongside self-hosted
Sources
- n8n Self-Hosted vs Cloud
- GitLab Self-Managed vs SaaS
- JetBrains BYOK
- VS Code BYOK
- Mattermost Self-Hosted Administration
- Multi-Tenant vs Single-Tenant SaaS
- AWS SaaS Architecture Fundamentals
- CodeGPT BYOK
- OpenRouter BYOK
Report generated: 2026-01-21