feat: add API key authentication system and update documentation
API Key System: - Add TpmjsApiKey, ApiUsageRecord, ApiUsageSummary models to schema - Create API key utilities (generate, hash, mask with tpmjs_sk_ prefix) - Implement dual auth middleware (session + API key) - Add rate limiting with Vercel KV - Create CRUD endpoints for API key management - Add usage tracking and analytics endpoint - Build API key management UI in dashboard - Build usage dashboard with charts Route Protection: - Require auth for MCP endpoints (mcp:execute scope) - Require auth for agent chat (agent:chat scope) - Require auth for bridge connections (bridge:connect scope) Documentation Updates: - Update all curl/fetch examples with Authorization header - Document API key format, scopes, and rate limits - Update PRD-MCP-BRIDGE.md, MCP-AGGREGATOR-DESIGN.md - Update API docs page with auth requirements - Update HOW_TO_PUBLISH_A_TOOL.md
This commit is contained in:
parent
b663ca3e05
commit
a3f1f3935e
20 changed files with 2813 additions and 90 deletions
|
|
@ -334,6 +334,9 @@ model User {
|
|||
image String?
|
||||
username String? @unique @db.VarChar(30) // URL-friendly username (nullable for migration)
|
||||
|
||||
// Tier for rate limiting and feature access
|
||||
tier UserTier @default(FREE)
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
|
|
@ -347,6 +350,8 @@ model User {
|
|||
agentLikes AgentLike[]
|
||||
activities UserActivity[]
|
||||
bridgeConnection BridgeConnection?
|
||||
tpmjsApiKeys TpmjsApiKey[] @relation("UserTpmjsApiKeys")
|
||||
usageSummaries ApiUsageSummary[] @relation("UserUsageSummaries")
|
||||
|
||||
@@index([username])
|
||||
@@map("users")
|
||||
|
|
@ -886,3 +891,137 @@ model CollectionBridgeTool {
|
|||
@@index([collectionId])
|
||||
@@map("collection_bridge_tools")
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// API Key & Usage Tracking Models
|
||||
// ============================================================================
|
||||
|
||||
/// User tier enum - determines rate limits and feature access
|
||||
enum UserTier {
|
||||
FREE
|
||||
PRO
|
||||
ENTERPRISE
|
||||
}
|
||||
|
||||
/// TpmjsApiKey - user-owned API keys for programmatic access
|
||||
model TpmjsApiKey {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Owner relationship
|
||||
userId String @map("user_id")
|
||||
user User @relation("UserTpmjsApiKeys", fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Key identification
|
||||
name String @db.VarChar(100) // User-provided name (e.g., "Production Server")
|
||||
keyHash String @unique @map("key_hash") @db.VarChar(64) // SHA-256 hash (never store raw keys)
|
||||
keyPrefix String @map("key_prefix") @db.VarChar(20) // First 16 chars for identification (tpmjs_sk_abc123...)
|
||||
|
||||
// Permissions
|
||||
scopes String[] @default([]) // ["mcp:execute", "agent:chat", "bridge:connect", "usage:read"]
|
||||
|
||||
// Rate limiting (overrides tier default if set)
|
||||
rateLimit Int? @map("rate_limit") // Requests per hour (null = use tier default)
|
||||
|
||||
// Status
|
||||
isActive Boolean @default(true) @map("is_active")
|
||||
lastUsedAt DateTime? @map("last_used_at")
|
||||
expiresAt DateTime? @map("expires_at")
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// Relations
|
||||
usageRecords ApiUsageRecord[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([keyHash])
|
||||
@@index([keyPrefix])
|
||||
@@index([isActive])
|
||||
@@map("tpmjs_api_keys")
|
||||
}
|
||||
|
||||
/// ApiUsageRecord - individual API request logs (kept for 30 days)
|
||||
model ApiUsageRecord {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// API key relationship
|
||||
apiKeyId String @map("api_key_id")
|
||||
apiKey TpmjsApiKey @relation(fields: [apiKeyId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Request details
|
||||
endpoint String @db.VarChar(500)
|
||||
method String @db.VarChar(10) // GET, POST, etc.
|
||||
statusCode Int @map("status_code")
|
||||
latencyMs Int @map("latency_ms")
|
||||
|
||||
// Resource tracking
|
||||
resourceType String? @map("resource_type") @db.VarChar(50) // "mcp" | "agent" | "bridge" | "collection"
|
||||
resourceId String? @map("resource_id") @db.VarChar(100) // Collection ID, Agent ID, etc.
|
||||
|
||||
// LLM usage (if applicable)
|
||||
tokensIn Int? @map("tokens_in")
|
||||
tokensOut Int? @map("tokens_out")
|
||||
model String? @db.VarChar(50) // e.g., "gpt-4o-mini"
|
||||
|
||||
// Error tracking
|
||||
errorCode String? @map("error_code") @db.VarChar(50)
|
||||
errorMessage String? @map("error_message") @db.Text
|
||||
|
||||
// Client metadata
|
||||
userAgent String? @map("user_agent") @db.VarChar(500)
|
||||
ipAddress String? @map("ip_address") @db.VarChar(45) // IPv4 or IPv6
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@index([apiKeyId])
|
||||
@@index([createdAt])
|
||||
@@index([endpoint])
|
||||
@@index([resourceType, resourceId])
|
||||
@@map("api_usage_records")
|
||||
}
|
||||
|
||||
/// ApiUsageSummary - aggregated usage summaries (hourly/daily rollups)
|
||||
model ApiUsageSummary {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// User relationship
|
||||
userId String @map("user_id")
|
||||
user User @relation("UserUsageSummaries", fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Optional API key (null for user-level summaries)
|
||||
apiKeyId String? @map("api_key_id")
|
||||
|
||||
// Time period
|
||||
periodType String @map("period_type") @db.VarChar(20) // "hourly" | "daily" | "monthly"
|
||||
periodStart DateTime @map("period_start")
|
||||
|
||||
// Request counts
|
||||
totalRequests Int @default(0) @map("total_requests")
|
||||
successRequests Int @default(0) @map("success_requests")
|
||||
errorRequests Int @default(0) @map("error_requests")
|
||||
|
||||
// Endpoint breakdown (JSON: { "/api/mcp/...": 100, ... })
|
||||
endpointCounts Json @default("{}") @map("endpoint_counts") @db.JsonB
|
||||
|
||||
// LLM usage totals
|
||||
totalTokensIn Int @default(0) @map("total_tokens_in")
|
||||
totalTokensOut Int @default(0) @map("total_tokens_out")
|
||||
|
||||
// Performance
|
||||
avgLatencyMs Float @default(0) @map("avg_latency_ms")
|
||||
p95LatencyMs Float @default(0) @map("p95_latency_ms")
|
||||
|
||||
// Cost estimation (in cents)
|
||||
estimatedCostCents Int @default(0) @map("estimated_cost_cents")
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([userId, apiKeyId, periodType, periodStart])
|
||||
@@index([userId])
|
||||
@@index([periodType, periodStart])
|
||||
@@map("api_usage_summaries")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue