hailin
7d5840c245
feat(openclaw): Phase 1 — server pool + agent instance deployment infrastructure
...
## inventory-service
- New: pool_servers table (public schema, platform-admin managed)
- New: PoolServer entity, PoolServerRepository, PoolServerController
- CRUD endpoints at /api/v1/inventory/pool-servers
- Internal /deploy-creds endpoint (x-internal-api-key protected) for SSH key retrieval
- increment/decrement endpoints for capacity tracking
## agent-service
- New: agent_instances table (tenant schema)
- New: AgentInstance entity, AgentInstanceRepository, AgentInstanceController
- New: AgentInstanceDeployService — SSH-based docker deployment
- Queries pool server availability from inventory-service
- AES-256 encrypts OpenClaw gateway token at rest
- Allocates host ports in range 20000-29999
- Fires docker run for it0hub/openclaw-bridge:latest
- Async deploy with error capture
- Added ssh2 dependency for SSH execution
- Added INVENTORY_SERVICE_URL, INTERNAL_API_KEY, VAULT_MASTER_KEY to docker-compose
## openclaw-bridge (new package)
- packages/openclaw-bridge/ — custom Docker image
- Two processes via supervisord: OpenClaw gateway + IT0 Bridge (Node.js)
- IT0 Bridge exposes REST API on port 3000:
GET /health, GET /status, POST /task, GET /sessions, GET /metrics
- Connects to OpenClaw gateway at ws://127.0.0.1:18789 via WebSocket RPC
- Sends heartbeat to IT0 agent-service every 60s
- Dockerfile: multi-stage build (openclaw source + bridge TS compilation)
## Web Admin
- New: /server-pool page — list/add/edit/delete pool servers with capacity bars
- New: /openclaw-instances page — cross-tenant instance monitoring with status filter
- Sidebar: added 服务器池 (Database icon) + OpenClaw 实例 (Boxes icon) to platform_admin nav
## Flutter App
- my_agents_page: rewritten to show real AgentInstance data from /api/v1/agent/instances
- Added AgentInstance model with status-driven UI (running/deploying/stopped/error)
- Status badges with color coding + spinner for deploying state
- Summary chips showing running vs stopped counts
- api_endpoints.dart: added agentInstances endpoint
## Design docs
- OPENCLAW_INTEGRATION_PLAN.md: complete architecture document with all confirmed decisions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 11:11:21 -08:00
hailin
9ed80cd0bc
feat: implement complete commercial monetization loop (Phases 1-4)
...
## Phase 1 - Token Metering + Quota Enforcement
### Usage Tracking
- agent-service: add UsageRecord entity (per-tenant schema) tracking
inputTokens/outputTokens/costUsd per AI task
- Modify all 3 AI engines (claude-api, claude-code-cli, claude-agent-sdk)
to emit separate input/output token counts in the `completed` event
- claude-api-engine: costUsd = (input*3 + output*15) / 1,000,000
(claude-sonnet-4-5 pricing: $3/MTok in, $15/MTok out)
- agent.controller: persist UsageRecord and publish `usage.recorded`
event to Redis Streams on every task completion (non-blocking)
- shared/events: new events UsageRecordedEvent, SubscriptionChangedEvent,
QuotaExceededEvent, PaymentReceivedEvent
### Quota Enforcement
- TenantInfo: add maxServers, maxUsers, maxStandingOrders,
maxAgentTokensPerMonth fields
- TenantContextMiddleware: rewritten to query public.tenants table for
real quota values; 5-min in-memory cache; plan-based fallback on error
- TenantContextService: getTenant() returns null instead of throwing;
added getTenantOrThrow() for strict callers
- inventory-service/server.controller: 429 when maxServers exceeded
- ops-service/standing-order.controller: 429 when maxStandingOrders exceeded
- auth-service/auth.service: 429 when maxUsers exceeded
- 002-create-tenant-schema-template.sql: add usage_records table
## Phase 2 - billing-service (New Microservice, port 3010)
### Domain Layer (public schema, all UUIDs)
Entities: Plan, Subscription, Invoice, InvoiceItem, Payment, PaymentMethod,
UsageAggregate
Domain services:
- SubscriptionLifecycleService: full state machine (trialing -> active ->
past_due -> cancelled/expired); upgrades immediate, downgrades at period end
- InvoiceGeneratorService: monthly invoice = base fee + overage charges;
proration item for mid-cycle upgrades
- OverageCalculatorService: (totalTokens - includedTokens) * overageRate
### Infrastructure (all repos use DataSource directly, NOT TenantAwareRepository)
- PlanRepository, SubscriptionRepository, InvoiceRepository (atomic
transaction for invoice+items), PaymentRepository (payments + methods),
UsageAggregateRepository (UPSERT via ON CONFLICT for atomic accumulation)
### Application Use Cases
- CreateSubscriptionUseCase: called on tenant registration
- ChangePlanUseCase: upgrade (immediate + proration) or downgrade (scheduled)
- CancelSubscriptionUseCase: immediate or at-period-end
- GenerateMonthlyInvoiceUseCase: cron target (1st of month 00:05 UTC);
generates invoices, renews periods, applies scheduled downgrades
- AggregateUsageUseCase: Redis Streams consumer group billing-service,
upserts monthly usage aggregates from usage.recorded events
- CheckTokenQuotaUseCase: hard limit enforcement per plan
- CreatePaymentSessionUseCase + HandlePaymentWebhookUseCase
### REST API
- GET /api/v1/billing/plans
- GET/POST /api/v1/billing/subscription (+ /upgrade, /cancel)
- GET /api/v1/billing/invoices (paginated)
- GET /api/v1/billing/invoices/:id
- POST /api/v1/billing/invoices/:id/pay
- GET /api/v1/billing/usage/current + /history
- CRUD /api/v1/billing/payment-methods
- POST /api/v1/billing/webhooks/{stripe,alipay,wechat,crypto}
### Plan Seed (auto on startup via PlanSeedService)
- free: $0/mo, 100K tokens, no overage, hard limit 100%
- pro: $49.99/mo, 1M tokens, $8/MTok, hard limit 150%
- enterprise: $199.99/mo, 10M tokens, $5/MTok, no hard limit
## Phase 3 - Payment Provider Integration
### PaymentProviderRegistry (Strategy Pattern, mirrors EngineRegistry)
All providers use @Optional() injection; unconfigured providers omitted
- StripeProvider: PaymentIntent API; webhook via stripe.webhooks.constructEvent
- AlipayProvider: alipay-sdk; Native QR (precreate); RSA2 signature verify
- WeChatPayProvider: v3 REST; Native Pay code_url; AES-256-GCM decrypt;
HMAC-SHA256 request signing and webhook verification
- CryptoProvider: Coinbase Commerce; hosted checkout; HMAC-SHA256 verify
### WebhookController
All 4 webhook endpoints are public (no JWT) for payment provider callbacks.
rawBody: true enabled in main.ts for signature verification.
## Infrastructure Changes
- docker-compose.yml: billing-service container (port 13010);
added as dependency of api-gateway
- kong.yml: /api/v1/billing routes (JWT); /api/v1/billing/webhooks (public)
- 005-create-billing-tables.sql: 7 billing tables + invoice sequence +
ALTER tenants to add quota columns
- run-migrations.ts: 005 runs as part of shared schema step
## Phase 4 - Frontend
### Web Admin (Next.js)
New pages:
- /billing: subscription card + token usage bar + warning banner + invoices
- /billing/plans: comparison grid with USD/CNY toggle + upgrade/downgrade flow
- /billing/invoices: paginated table with Pay Now button
Sidebar: Billing group (CreditCard icon, 3 sub-items)
i18n: billing keys added to en + zh sidebar translations
### Flutter App
New feature module it0_app/lib/features/billing/:
- BillingOverviewPage: plan card + token LinearProgressIndicator +
latest invoice + upgrade button
- BillingProvider (FutureProvider): parallel fetch subscription/quota/invoice
Settings page: "订阅与用量" entry card
Router: /settings/billing sub-route
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 21:09:17 -08:00