feat(phase-4): WS6 — Billing & Usage Metering (Stripe, free tier enforcement)

- DB migration 023: tenant_subscriptions and usage_events tables
- UsageMeteringMiddleware: in-memory counters, 60s flush to DB via UPSERT
- FreeTierEnforcementMiddleware: 10 agents / 1,000 calls/day limits, Redis cache
- UsageService: getDailyUsage and getActiveAgentCount
- BillingService: Stripe checkout sessions, webhook verification, subscription status
- POST /billing/checkout, POST /billing/webhook, GET /billing/usage endpoints
- BILLING_ENABLED=false disables enforcement without breaking metering
- Dashboard: Usage tab with Free Tier/Pro badges and metric cards
- 19 unit tests passing across billing services and middleware

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SentryAgent.ai Developer
2026-04-02 10:51:36 +00:00
parent fefbf1e3ea
commit 26a56f84e1
18 changed files with 1647 additions and 17 deletions

View File

@@ -9,6 +9,7 @@ import AgentDetail from '@/pages/AgentDetail';
import Credentials from '@/pages/Credentials';
import AuditLog from '@/pages/AuditLog';
import Health from '@/pages/Health';
import { UsagePanel } from '@/components/UsagePanel';
/** Top-level router — defines all application routes. */
export default function App(): React.JSX.Element {
@@ -23,6 +24,7 @@ export default function App(): React.JSX.Element {
<Route path="/dashboard/agents/:agentId/credentials" element={<Credentials />} />
<Route path="/dashboard/audit" element={<AuditLog />} />
<Route path="/dashboard/health" element={<Health />} />
<Route path="/dashboard/usage" element={<UsagePanel />} />
</Route>
</Route>
<Route path="/dashboard" element={<Navigate to="/dashboard/agents" replace />} />