chore(openspec): archive phase-6-market-expansion — 53/53 tasks complete
Analytics Dashboard, API Gateway Tiers, AGNTCY Compliance all delivered. Development freeze now in effect per CEO directive — no Phase 7. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-04-03
|
||||
@@ -0,0 +1,81 @@
|
||||
## Context
|
||||
|
||||
SentryAgent.ai AgentIdP has completed four major phases: core OAuth2/agent identity (Phase 1), enterprise features — multi-tenancy, DIDs, OIDC, federation, webhooks, SOC2 (Phase 3), production hardening and developer tooling (Phase 4), and SDK ecosystem + A2A authorization (Phase 5). The platform is feature-complete for identity; Phase 6 makes it commercially competitive by adding visibility (analytics), monetization (tiers), and ecosystem certification (AGNTCY compliance).
|
||||
|
||||
**Current state constraints:**
|
||||
- Stack: Node.js 18+, TypeScript strict, Express, PostgreSQL 14+, Redis 7+, React/Next.js 14 (portal)
|
||||
- Existing Redis rate limiter: per-agent token bucket keys (`rate:agent:<id>`)
|
||||
- Existing tenant model: `tenants` table with `plan` column (currently unused for enforcement)
|
||||
- Existing audit log: `audit_events` table (used for SOC2, not analytics)
|
||||
- Portal: Next.js 14 at `portal/`, API explorer via Stoplight Elements added in Phase 5
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Deliver tenant-facing analytics (token trends, agent activity heatmaps) via new API + portal views
|
||||
- Enforce tier-based rate limits (free/pro/enterprise) transparently via existing middleware layer
|
||||
- Expose self-service tier upgrade endpoint (integration with existing Stripe billing from Phase 4)
|
||||
- Generate AGNTCY-standard compliance reports and agent cards on demand
|
||||
- Provide an interoperability test suite for AGNTCY ecosystem partners
|
||||
|
||||
**Non-Goals:**
|
||||
- Real-time streaming analytics (WebSocket push) — batch/polling sufficient for Phase 6
|
||||
- Billing tier downgrades (upgrade only; downgrade requires support intervention)
|
||||
- Multi-region analytics aggregation — single-region PostgreSQL sufficient
|
||||
- Full AGNTCY federation partner onboarding UI — report + card export is the deliverable
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: Analytics Storage — Dedicated Table vs. Querying `audit_events`
|
||||
|
||||
**Decision**: New `analytics_events` table with pre-aggregated daily rollups.
|
||||
|
||||
**Rationale**: `audit_events` is an append-only SOC2 ledger with a Merkle chain — querying it for analytics requires full scans and breaks its integrity guarantees. A separate `analytics_events` table with `(tenant_id, date, metric_type, count)` schema enables indexed range queries without touching the audit chain.
|
||||
|
||||
**Alternative considered**: Materialized views over `audit_events` — rejected because the Merkle chain structure makes column selection fragile and any schema change risks audit integrity.
|
||||
|
||||
### D2: Tier Enforcement — Middleware vs. Per-Endpoint Guards
|
||||
|
||||
**Decision**: New `tierEnforcement` Express middleware inserted before route handlers, reading tier config from a `TIER_CONFIG` constant (not DB) for zero-latency enforcement.
|
||||
|
||||
**Rationale**: Per-endpoint guards duplicate logic and are easy to miss on new routes. A single middleware checking `req.tenant.tier` against `TIER_CONFIG[tier].limits` is DRY and auditable. Redis keys prefixed `rate:tier:<tier>:<tenant_id>` track daily call counts.
|
||||
|
||||
**Alternative considered**: DB-driven tier limits per tenant row — rejected because it adds a DB read to every request; tier configs change rarely and belong in config, not data.
|
||||
|
||||
### D3: AGNTCY Compliance Report — Generated On-Demand vs. Scheduled
|
||||
|
||||
**Decision**: Generated on-demand (`GET /api/compliance/report`) with 5-minute Redis cache.
|
||||
|
||||
**Rationale**: Compliance reports are requested infrequently (audit cycles, partner onboarding) and must reflect current state. A 5-minute cache prevents redundant computation without staleness risk. No background job needed.
|
||||
|
||||
**Alternative considered**: Nightly scheduled generation — rejected because it could be stale at the moment of an audit request.
|
||||
|
||||
### D4: recharts Integration — Dashboard vs. Portal
|
||||
|
||||
**Decision**: Analytics views live in `portal/src/pages/analytics/` as new Next.js pages using `recharts` components. No changes to the existing `dashboard/` directory (Phase 3 admin dashboard).
|
||||
|
||||
**Rationale**: The developer portal (`portal/`) is the tenant-facing surface. The `dashboard/` is the internal admin view. Tenant analytics belong in the portal alongside existing usage stats.
|
||||
|
||||
### D5: Delivery Sequence
|
||||
|
||||
**Decision**: WS3 (Analytics) → WS4 (API Tiers) → WS6 (AGNTCY Compliance), sequential.
|
||||
|
||||
**Rationale**: Analytics requires the `analytics_events` table; tiers build on top of existing Redis + tenant model and can reuse analytics data for usage display; compliance requires all prior capabilities to be stable for report generation. Each workstream is independently deployable.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Analytics table growth** → Mitigation: daily rollup rows (not per-event rows); add `created_at` index with a 90-day retention policy via PostgreSQL `pg_partman` or a simple cron DELETE.
|
||||
- **Tier enforcement bypass during Redis failure** → Mitigation: fail-open on Redis errors (log + allow) to avoid availability impact; flag in health endpoint.
|
||||
- **recharts bundle size in portal** → Mitigation: dynamic import (`next/dynamic`) for chart components — only loaded on analytics pages.
|
||||
- **AGNTCY spec version drift** → Mitigation: pin to AGNTCY agent-card schema v1.0; add schema version field to report output; test suite validates against pinned version.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. **WS3**: Run migration `023_add_analytics_events.sql` → deploy API changes → deploy portal analytics pages
|
||||
2. **WS4**: Run migration `024_add_tenant_tiers.sql` → deploy tier middleware (with `TIER_ENFORCEMENT=false` feature flag initially) → smoke test → enable flag
|
||||
3. **WS6**: No migration required — compliance report queries existing tables; deploy endpoint + test suite
|
||||
4. **Rollback**: Each WS has a feature flag (`ANALYTICS_ENABLED`, `TIER_ENFORCEMENT`, `COMPLIANCE_ENABLED`). Set to `false` to disable without rollback.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None — scope is fully defined from Phase 5 deferred workstreams. AGNTCY agent-card schema version confirmed as v1.0 per Phase 3 W3C DIDs implementation.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
Phase 5 delivered the Rust SDK, A2A authorization, and developer experience improvements — completing the core platform. Phase 6 activates market expansion: analytics to demonstrate value to tenants, tiered API access to monetize at scale, and AGNTCY compliance certification to unlock enterprise and ecosystem partnerships. These three workstreams were scoped and approved in Phase 5 but deferred to keep Phase 5 focused; the work is already designed and ready to execute.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Advanced Analytics Dashboard (WS3)**: New `/api/analytics/` endpoints exposing token issuance trends, agent activity heatmaps, and per-tenant usage breakdowns. New React dashboard views using `recharts` for visualization. Tenant admins can see real-time and historical usage.
|
||||
- **API Gateway Tiers (WS4)**: Multi-tier rate limiting — free (10 agents, 1,000 calls/day), pro (100 agents, 50,000 calls/day), enterprise (unlimited). Self-service tier upgrade endpoint. Rate limit headers on all API responses. Enforcement layer integrated with existing Redis rate limiter.
|
||||
- **AGNTCY Compliance Certification (WS6)**: Auto-generated compliance report endpoint (`GET /api/compliance/report`) covering agent identity, audit trail, credential rotation, and federation status. Agent card export in AGNTCY-standard JSON format. Interoperability test suite validating AGNTCY protocol conformance.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `analytics-dashboard`: Per-tenant usage analytics — token issuance trends, agent activity heatmaps, daily/weekly/monthly breakdowns via new API endpoints and React dashboard views
|
||||
- `api-gateway-tiers`: Tiered rate limiting (free/pro/enterprise), self-service upgrade endpoint, rate limit headers, Redis-backed enforcement per tenant and tier
|
||||
- `agntcy-compliance`: AGNTCY compliance report generation, agent card export (AGNTCY JSON format), interoperability conformance test suite
|
||||
|
||||
### Modified Capabilities
|
||||
- `web-dashboard`: New analytics and tier-management views added to existing React portal (no breaking changes to existing dashboard routes)
|
||||
|
||||
## Impact
|
||||
|
||||
- **New dependencies**: `recharts`, `date-fns` (analytics charts); no new backend deps (compliance and tier enforcement use existing stack)
|
||||
- **API surface**: 8–12 new endpoints across analytics, tiers, and compliance namespaces
|
||||
- **Database**: New `analytics_events` table (time-series), `tenant_tiers` table; migration files required
|
||||
- **Redis**: Tier-aware rate limit keys (`rate:tier:<tier>:<tenant_id>`) alongside existing per-agent keys
|
||||
- **Portal**: 2–3 new page routes in `portal/src/pages/` using `recharts` components
|
||||
- **No breaking changes** to existing endpoints or agent identity model
|
||||
@@ -0,0 +1,82 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: System generates an on-demand AGNTCY compliance report
|
||||
The system SHALL expose `GET /api/compliance/report` returning a structured JSON compliance report covering: agent identity verification, audit trail integrity, credential rotation status, and federation readiness. The report SHALL be generated on-demand and cached in Redis for 5 minutes (`compliance:report:<tenant_id>`).
|
||||
|
||||
The report SHALL include:
|
||||
- `generated_at`: ISO 8601 timestamp
|
||||
- `tenant_id`: tenant identifier
|
||||
- `agntcy_schema_version`: pinned version string (e.g., `"1.0"`)
|
||||
- `sections`: array of compliance sections, each with `name`, `status` (`pass`/`fail`/`warn`), and `details`
|
||||
- `overall_status`: `pass` if all sections pass, `fail` if any section fails, `warn` if any section warns
|
||||
|
||||
#### Scenario: Successful compliance report generation
|
||||
- **WHEN** an authenticated tenant admin calls `GET /api/compliance/report`
|
||||
- **THEN** the response SHALL be HTTP 200 with a JSON compliance report containing all required sections
|
||||
|
||||
#### Scenario: Compliance report is served from cache within TTL
|
||||
- **WHEN** `GET /api/compliance/report` is called twice within 5 minutes
|
||||
- **THEN** the second response SHALL be served from Redis cache (not recomputed) and include a `X-Cache: HIT` header
|
||||
|
||||
#### Scenario: Compliance report requires authentication
|
||||
- **WHEN** `GET /api/compliance/report` is called without a valid JWT
|
||||
- **THEN** the response SHALL be HTTP 401
|
||||
|
||||
### Requirement: Compliance report covers agent identity verification
|
||||
The compliance report SHALL include an `agent-identity` section validating that all active agents have: a valid DID:WEB identifier, a current credential (not expired), and an AGNTCY agent card on record. The section SHALL report `pass` only if all agents satisfy all three checks.
|
||||
|
||||
#### Scenario: All agents compliant — agent identity section passes
|
||||
- **WHEN** all active agents have valid DIDs, non-expired credentials, and agent cards
|
||||
- **THEN** the `agent-identity` section SHALL have `status: "pass"`
|
||||
|
||||
#### Scenario: Agent with expired credential — section warns
|
||||
- **WHEN** one or more active agents have credentials expiring within 7 days
|
||||
- **THEN** the `agent-identity` section SHALL have `status: "warn"` with details listing affected agents
|
||||
|
||||
#### Scenario: Agent missing DID — section fails
|
||||
- **WHEN** one or more active agents have no DID:WEB identifier
|
||||
- **THEN** the `agent-identity` section SHALL have `status: "fail"` with details listing affected agents
|
||||
|
||||
### Requirement: Compliance report covers audit trail integrity
|
||||
The compliance report SHALL include an `audit-trail` section verifying the Merkle chain integrity of the `audit_events` table for the tenant. The section SHALL report `pass` if the chain is unbroken, `fail` if any hash mismatch is detected.
|
||||
|
||||
#### Scenario: Intact audit chain passes
|
||||
- **WHEN** the Merkle chain for all audit events is valid
|
||||
- **THEN** the `audit-trail` section SHALL have `status: "pass"` with the total event count
|
||||
|
||||
#### Scenario: Broken audit chain fails
|
||||
- **WHEN** a hash mismatch is detected in the audit event chain
|
||||
- **THEN** the `audit-trail` section SHALL have `status: "fail"` with the sequence number of the first invalid event
|
||||
|
||||
### Requirement: System exports AGNTCY-standard agent cards
|
||||
The system SHALL expose `GET /api/compliance/agent-cards` returning an array of all active agents as AGNTCY agent card objects in the standard JSON format. Each agent card SHALL include: `id` (DID:WEB), `name`, `capabilities` (from agent metadata), `endpoint`, `created_at`, and `agntcy_schema_version`.
|
||||
|
||||
#### Scenario: Successful agent card export
|
||||
- **WHEN** an authenticated tenant admin calls `GET /api/compliance/agent-cards`
|
||||
- **THEN** the response SHALL be HTTP 200 with a JSON array of agent card objects for all active agents
|
||||
|
||||
#### Scenario: Agent card export respects tenant isolation
|
||||
- **WHEN** tenant A exports agent cards
|
||||
- **THEN** the response SHALL contain ONLY agents belonging to tenant A
|
||||
|
||||
#### Scenario: Empty tenant returns empty array
|
||||
- **WHEN** the tenant has no active agents
|
||||
- **THEN** the response SHALL be HTTP 200 with an empty array
|
||||
|
||||
### Requirement: AGNTCY interoperability test suite validates protocol conformance
|
||||
The system SHALL include an interoperability test suite at `tests/agntcy-conformance/` that validates the platform's conformance to the AGNTCY agent identity protocol. The suite SHALL test: agent registration (DID:WEB creation), token issuance for agent clients, A2A delegation chain creation and verification, and compliance report generation. All tests SHALL pass in CI.
|
||||
|
||||
#### Scenario: Conformance suite passes in CI environment
|
||||
- **WHEN** `npm run test:agntcy-conformance` is executed in a CI environment with a live test database
|
||||
- **THEN** all conformance tests SHALL pass with exit code 0
|
||||
|
||||
#### Scenario: Conformance suite fails on missing DID endpoint
|
||||
- **WHEN** the DID resolution endpoint is unreachable
|
||||
- **THEN** the conformance test for DID:WEB SHALL fail with a descriptive error message
|
||||
|
||||
### Requirement: Compliance features can be toggled via feature flag
|
||||
The system SHALL respect a `COMPLIANCE_ENABLED` environment variable (default: `true`). When `COMPLIANCE_ENABLED=false`, all `/api/compliance/*` endpoints SHALL return HTTP 404.
|
||||
|
||||
#### Scenario: Compliance disabled returns 404
|
||||
- **WHEN** `COMPLIANCE_ENABLED=false` and `GET /api/compliance/report` is called
|
||||
- **THEN** the response SHALL be HTTP 404
|
||||
@@ -0,0 +1,67 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Analytics events are recorded for token issuances and agent activity
|
||||
The system SHALL record an analytics event row in `analytics_events` for every OAuth2 token issuance and every agent registration, update, and deactivation, scoped to the tenant. Each row SHALL contain: `tenant_id`, `date` (UTC date), `metric_type` (e.g., `token_issued`, `agent_registered`), and `count` (aggregated daily).
|
||||
|
||||
#### Scenario: Token issuance recorded in analytics
|
||||
- **WHEN** `POST /oauth2/token` succeeds for a tenant
|
||||
- **THEN** the `analytics_events` table SHALL have a row incremented for `metric_type=token_issued` for that tenant on today's UTC date
|
||||
|
||||
#### Scenario: Agent registration recorded in analytics
|
||||
- **WHEN** `POST /api/agents` succeeds
|
||||
- **THEN** the `analytics_events` table SHALL have a row incremented for `metric_type=agent_registered` for the owning tenant on today's UTC date
|
||||
|
||||
#### Scenario: Analytics recording does not block the primary response
|
||||
- **WHEN** the analytics write fails (e.g., DB timeout)
|
||||
- **THEN** the primary API response SHALL still succeed and the error SHALL be logged
|
||||
|
||||
### Requirement: Tenant can retrieve token issuance trend data
|
||||
The system SHALL expose `GET /api/analytics/tokens` returning daily token issuance counts for the authenticated tenant over a configurable date range (default: last 30 days, max: 90 days). Response SHALL include an array of `{ date, count }` objects sorted ascending by date.
|
||||
|
||||
#### Scenario: Successful token trend retrieval
|
||||
- **WHEN** an authenticated tenant admin calls `GET /api/analytics/tokens?days=30`
|
||||
- **THEN** the response SHALL be HTTP 200 with a JSON array of up to 30 `{ date, count }` objects
|
||||
|
||||
#### Scenario: Date range exceeding maximum is rejected
|
||||
- **WHEN** the request specifies `days` greater than 90
|
||||
- **THEN** the response SHALL be HTTP 400 with an error indicating the maximum is 90 days
|
||||
|
||||
#### Scenario: Tenant sees only their own data
|
||||
- **WHEN** tenant A retrieves analytics
|
||||
- **THEN** the response SHALL contain only rows where `tenant_id` matches tenant A — no cross-tenant data leakage
|
||||
|
||||
### Requirement: Tenant can retrieve agent activity heatmap data
|
||||
The system SHALL expose `GET /api/analytics/agents/activity` returning per-agent event counts grouped by day-of-week and hour-of-day for the authenticated tenant (last 30 days). Response SHALL include an array of `{ agent_id, dow, hour, count }` objects suitable for rendering a heatmap.
|
||||
|
||||
#### Scenario: Successful activity heatmap retrieval
|
||||
- **WHEN** an authenticated tenant admin calls `GET /api/analytics/agents/activity`
|
||||
- **THEN** the response SHALL be HTTP 200 with a JSON array of activity buckets
|
||||
|
||||
#### Scenario: Tenant with no agents returns empty array
|
||||
- **WHEN** the tenant has no registered agents
|
||||
- **THEN** the response SHALL be HTTP 200 with an empty array
|
||||
|
||||
### Requirement: Tenant can retrieve a per-agent usage summary
|
||||
The system SHALL expose `GET /api/analytics/agents` returning a list of agents with their total token issuances for the current billing period (current calendar month). Response SHALL include `{ agent_id, name, token_count }` sorted descending by `token_count`.
|
||||
|
||||
#### Scenario: Successful per-agent summary
|
||||
- **WHEN** an authenticated tenant admin calls `GET /api/analytics/agents`
|
||||
- **THEN** the response SHALL be HTTP 200 with a sorted list of agent usage summaries
|
||||
|
||||
#### Scenario: Analytics endpoint requires authentication
|
||||
- **WHEN** a request to any `/api/analytics/*` endpoint is made without a valid JWT
|
||||
- **THEN** the response SHALL be HTTP 401
|
||||
|
||||
### Requirement: Analytics data is accessible via the developer portal
|
||||
The portal SHALL include an Analytics page at `/analytics` with:
|
||||
- A line chart showing token issuance trend (last 30 days) rendered with `recharts`
|
||||
- A heatmap chart showing agent activity by day/hour rendered with `recharts`
|
||||
- A table listing per-agent usage for the current month
|
||||
|
||||
#### Scenario: Analytics page loads token trend chart
|
||||
- **WHEN** a tenant admin navigates to `/analytics` in the portal
|
||||
- **THEN** the page SHALL render a line chart with token issuance data from `GET /api/analytics/tokens`
|
||||
|
||||
#### Scenario: Analytics page is code-split (lazy loaded)
|
||||
- **WHEN** the portal bundle is built
|
||||
- **THEN** `recharts` and analytics page components SHALL be in a separate chunk (via `next/dynamic`) and NOT included in the main bundle
|
||||
@@ -0,0 +1,72 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Tenants are assigned to a tier with defined rate limits
|
||||
The system SHALL maintain a `tenant_tiers` table linking each tenant to a tier (`free`, `pro`, `enterprise`) with associated limits: max agents, max API calls per day, and max token issuances per day. Tier configuration SHALL be defined in a `TIER_CONFIG` constant (not in the database) to enable zero-latency enforcement.
|
||||
|
||||
Tier defaults:
|
||||
- `free`: 10 agents, 1,000 API calls/day, 1,000 token issuances/day
|
||||
- `pro`: 100 agents, 50,000 API calls/day, 50,000 token issuances/day
|
||||
- `enterprise`: unlimited (no enforcement)
|
||||
|
||||
#### Scenario: New tenant defaults to free tier
|
||||
- **WHEN** a new tenant is created via `POST /api/tenants`
|
||||
- **THEN** a `tenant_tiers` row SHALL be created with `tier=free`
|
||||
|
||||
#### Scenario: Enterprise tier bypasses all rate limits
|
||||
- **WHEN** a tenant on the `enterprise` tier makes any API call
|
||||
- **THEN** no rate limit check SHALL be applied for that tenant
|
||||
|
||||
### Requirement: API calls are rate-limited per tenant tier
|
||||
The system SHALL enforce daily API call limits per tenant using Redis keys `rate:tier:calls:<tenant_id>` with a TTL aligned to UTC midnight. When a tenant exceeds their daily call limit, subsequent requests SHALL be rejected.
|
||||
|
||||
#### Scenario: Tenant within call limit proceeds normally
|
||||
- **WHEN** a tenant on the `free` tier has made fewer than 1,000 API calls today
|
||||
- **THEN** the request SHALL proceed and the counter SHALL be incremented
|
||||
|
||||
#### Scenario: Tenant exceeding daily call limit is rejected
|
||||
- **WHEN** a tenant on the `free` tier has made 1,000 or more API calls today
|
||||
- **THEN** any further API request SHALL return HTTP 429 with `Retry-After` header set to seconds until UTC midnight
|
||||
|
||||
#### Scenario: Rate limit headers are present on all responses
|
||||
- **WHEN** any authenticated API request is made
|
||||
- **THEN** the response SHALL include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers reflecting the tenant's daily call allowance
|
||||
|
||||
### Requirement: Agent count is enforced per tenant tier
|
||||
The system SHALL prevent tenants from creating more agents than their tier allows. The check SHALL occur at agent creation time.
|
||||
|
||||
#### Scenario: Tenant at agent limit cannot create new agent
|
||||
- **WHEN** a `free` tier tenant already has 10 agents and calls `POST /api/agents`
|
||||
- **THEN** the response SHALL be HTTP 429 with an error message indicating the agent limit and a link to upgrade
|
||||
|
||||
#### Scenario: Tenant below agent limit can create agents
|
||||
- **WHEN** a `free` tier tenant has fewer than 10 agents and calls `POST /api/agents`
|
||||
- **THEN** the request SHALL proceed normally
|
||||
|
||||
### Requirement: Tier enforcement can be toggled via feature flag
|
||||
The system SHALL respect a `TIER_ENFORCEMENT` environment variable (default: `true`). When `TIER_ENFORCEMENT=false`, all tier limit checks SHALL be bypassed and requests SHALL proceed as if on the `enterprise` tier. Rate limit headers SHALL still be present but reflect unlimited limits.
|
||||
|
||||
#### Scenario: Tier enforcement disabled allows all requests
|
||||
- **WHEN** `TIER_ENFORCEMENT=false` and a `free` tier tenant has exceeded their daily limit
|
||||
- **THEN** the request SHALL succeed with HTTP 200 (no 429 returned)
|
||||
|
||||
### Requirement: Tenant can self-service upgrade their tier
|
||||
The system SHALL expose `POST /api/tiers/upgrade` allowing an authenticated tenant admin to request an upgrade to a higher tier. The endpoint SHALL validate the target tier is higher than the current tier and initiate a Stripe checkout session for the new tier's price. On successful payment webhook, the `tenant_tiers` row SHALL be updated.
|
||||
|
||||
#### Scenario: Successful tier upgrade initiation
|
||||
- **WHEN** a `free` tier tenant calls `POST /api/tiers/upgrade` with `{ "target_tier": "pro" }`
|
||||
- **THEN** the response SHALL be HTTP 200 with a Stripe checkout URL
|
||||
|
||||
#### Scenario: Downgrade attempt is rejected
|
||||
- **WHEN** a `pro` tier tenant calls `POST /api/tiers/upgrade` with `{ "target_tier": "free" }`
|
||||
- **THEN** the response SHALL be HTTP 400 with an error indicating downgrades require support
|
||||
|
||||
#### Scenario: Stripe webhook updates tier on payment success
|
||||
- **WHEN** Stripe sends a `checkout.session.completed` event for a tier upgrade
|
||||
- **THEN** the tenant's `tier` SHALL be updated to the purchased tier within 5 seconds
|
||||
|
||||
### Requirement: Tenant can view their current tier and usage
|
||||
The system SHALL expose `GET /api/tiers/status` returning the tenant's current tier, daily limits, current usage counts (calls today, tokens today, agent count), and time until daily limit reset.
|
||||
|
||||
#### Scenario: Tier status returns current usage
|
||||
- **WHEN** an authenticated tenant admin calls `GET /api/tiers/status`
|
||||
- **THEN** the response SHALL be HTTP 200 with tier name, limits, and live usage counters
|
||||
@@ -0,0 +1,27 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Portal includes an Analytics page
|
||||
The portal SHALL include a new page at `/analytics` accessible to authenticated tenant admins. The page SHALL render: a line chart (token issuance trend, last 30 days), an activity heatmap (agent activity by day/hour), and a per-agent usage table for the current month. All chart components SHALL be lazy-loaded via `next/dynamic`.
|
||||
|
||||
#### Scenario: Analytics page is accessible to tenant admins
|
||||
- **WHEN** an authenticated tenant admin navigates to `/analytics`
|
||||
- **THEN** the page SHALL render without error and display the token trend chart
|
||||
|
||||
#### Scenario: Analytics page redirects unauthenticated users
|
||||
- **WHEN** an unauthenticated user navigates to `/analytics`
|
||||
- **THEN** the portal SHALL redirect to the login page
|
||||
|
||||
### Requirement: Portal includes a Tier & Billing page
|
||||
The portal SHALL include a new page at `/settings/tier` accessible to authenticated tenant admins showing: current tier name, daily limits (agents, API calls, token issuances), current usage vs. limit, and an "Upgrade" button that initiates a Stripe checkout session for tenants not on the `enterprise` tier.
|
||||
|
||||
#### Scenario: Free tier tenant sees upgrade prompt
|
||||
- **WHEN** a `free` tier tenant admin navigates to `/settings/tier`
|
||||
- **THEN** the page SHALL display current limits, current usage, and an enabled "Upgrade to Pro" button
|
||||
|
||||
#### Scenario: Enterprise tier tenant sees no upgrade prompt
|
||||
- **WHEN** an `enterprise` tier tenant admin navigates to `/settings/tier`
|
||||
- **THEN** the page SHALL display "Enterprise — Unlimited" and SHALL NOT display an upgrade button
|
||||
|
||||
#### Scenario: Upgrade button initiates Stripe checkout
|
||||
- **WHEN** a tenant admin clicks "Upgrade to Pro" on the tier page
|
||||
- **THEN** the portal SHALL call `POST /api/tiers/upgrade` and redirect to the returned Stripe checkout URL
|
||||
@@ -0,0 +1,76 @@
|
||||
## 1. Foundation & Database Migrations
|
||||
|
||||
- [x] 1.1 Create migration `023_add_analytics_events.sql` — `analytics_events(id, tenant_id, date, metric_type, count, PRIMARY KEY(tenant_id, date, metric_type))`
|
||||
- [x] 1.2 Create migration `024_add_tenant_tiers.sql` — `tenant_tiers(tenant_id FK, tier ENUM('free','pro','enterprise'), created_at, updated_at)`
|
||||
- [x] 1.3 Add `TIER_CONFIG` constant to `src/config/tiers.ts` with free/pro/enterprise limits
|
||||
- [x] 1.4 Add `ANALYTICS_ENABLED`, `TIER_ENFORCEMENT`, `COMPLIANCE_ENABLED` env vars to `.env.example` and `src/config/env.ts`
|
||||
- [x] 1.5 Run migrations in test environment and verify table creation
|
||||
|
||||
## 2. WS3 — Analytics Backend
|
||||
|
||||
- [x] 2.1 Create `src/services/AnalyticsService.ts` — `recordEvent(tenantId, metricType)`, `getTokenTrend(tenantId, days)`, `getAgentActivity(tenantId)`, `getAgentUsageSummary(tenantId)` with JSDoc
|
||||
- [x] 2.2 Add analytics event recording to `OAuth2Service.issueToken()` — fire-and-forget (non-blocking)
|
||||
- [x] 2.3 Add analytics event recording to `AgentService.create()` and `AgentService.deactivate()`
|
||||
- [x] 2.4 Create `src/controllers/AnalyticsController.ts` — GET /api/analytics/tokens, GET /api/analytics/agents/activity, GET /api/analytics/agents
|
||||
- [x] 2.5 Create `src/routes/analytics.ts` and register under `/api/analytics` in `src/app.ts` (guarded by `ANALYTICS_ENABLED` flag)
|
||||
- [x] 2.6 Add input validation: `days` param capped at 90, tenant scoping enforced on all queries
|
||||
|
||||
## 3. WS3 — Analytics Portal Pages
|
||||
|
||||
- [x] 3.1 Add `recharts` and `date-fns` to `portal/package.json`
|
||||
- [x] 3.2 Create `portal/src/components/charts/TokenTrendChart.tsx` — recharts LineChart, lazy-loadable
|
||||
- [x] 3.3 Create `portal/src/components/charts/AgentHeatmap.tsx` — recharts custom heatmap, lazy-loadable
|
||||
- [x] 3.4 Create `portal/src/pages/analytics/index.tsx` — uses `next/dynamic` for chart components, fetches from `/api/analytics/*`
|
||||
- [x] 3.5 Add `/analytics` route to portal navigation (`portal/src/components/Sidebar.tsx` or equivalent)
|
||||
- [x] 3.6 Verify `next build` succeeds and analytics chunk is separate from main bundle
|
||||
|
||||
## 4. WS4 — API Gateway Tiers Backend
|
||||
|
||||
- [x] 4.1 Create `src/middleware/tierEnforcement.ts` — reads `req.tenant.tier`, checks Redis `rate:tier:calls:<tenant_id>` against `TIER_CONFIG`, sets rate limit headers on all responses
|
||||
- [x] 4.2 Register `tierEnforcement` middleware in `src/app.ts` after auth middleware, before routes (skip when `TIER_ENFORCEMENT=false`)
|
||||
- [x] 4.3 Add agent count enforcement in `AgentService.create()` — query active agent count vs. tier limit, throw typed `TierLimitError` if exceeded
|
||||
- [x] 4.4 Create `src/services/TierService.ts` — `getStatus(tenantId)`, `initiateUpgrade(tenantId, targetTier)`, `applyUpgrade(tenantId, tier)` (called from Stripe webhook)
|
||||
- [x] 4.5 Create `src/controllers/TierController.ts` — GET /api/tiers/status, POST /api/tiers/upgrade
|
||||
- [x] 4.6 Create `src/routes/tiers.ts` and register under `/api/tiers` in `src/app.ts`
|
||||
- [x] 4.7 Update Stripe webhook handler (`src/services/BillingService.ts`) to call `TierService.applyUpgrade()` on `checkout.session.completed` for tier upgrade events
|
||||
- [x] 4.8 Add `TierLimitError` to error hierarchy in `src/errors/index.ts` — HTTP 429, `tier_limit_exceeded` code
|
||||
|
||||
## 5. WS4 — Tier Portal Page
|
||||
|
||||
- [x] 5.1 Create `portal/src/pages/settings/tier.tsx` — displays current tier, limits, usage, upgrade button
|
||||
- [x] 5.2 Upgrade button calls `POST /api/tiers/upgrade` and redirects to Stripe checkout URL
|
||||
- [x] 5.3 Enterprise tier view shows "Unlimited" with no upgrade button
|
||||
- [x] 5.4 Add `/settings/tier` to portal navigation
|
||||
|
||||
## 6. WS6 — AGNTCY Compliance Backend
|
||||
|
||||
- [x] 6.1 Create `src/services/ComplianceService.ts` — `generateReport(tenantId)` building all compliance sections, `exportAgentCards(tenantId)`, Redis cache with 5-minute TTL
|
||||
- [x] 6.2 Implement `agent-identity` section: check all active agents for valid DID, non-expired credential, agent card presence
|
||||
- [x] 6.3 Implement `audit-trail` section: verify Merkle chain integrity for tenant's audit events
|
||||
- [x] 6.4 Implement agent card export: map agent records to AGNTCY agent card JSON schema v1.0
|
||||
- [x] 6.5 Create `src/controllers/ComplianceController.ts` — GET /api/compliance/report, GET /api/compliance/agent-cards
|
||||
- [x] 6.6 Create `src/routes/compliance.ts` and register under `/api/compliance` in `src/app.ts` (guarded by `COMPLIANCE_ENABLED` flag)
|
||||
|
||||
## 7. WS6 — AGNTCY Conformance Test Suite
|
||||
|
||||
- [x] 7.1 Create `tests/agntcy-conformance/` directory with Jest config
|
||||
- [x] 7.2 Write conformance test: agent registration creates DID:WEB identifier
|
||||
- [x] 7.3 Write conformance test: token issuance for agent client
|
||||
- [x] 7.4 Write conformance test: A2A delegation chain create + verify
|
||||
- [x] 7.5 Write conformance test: compliance report generation returns valid structure
|
||||
- [x] 7.6 Add `test:agntcy-conformance` npm script to `package.json`
|
||||
|
||||
## 8. QA & Release
|
||||
|
||||
- [x] 8.1 Write unit tests for `AnalyticsService` — event recording, trend query, heatmap query, usage summary (>80% coverage)
|
||||
- [x] 8.2 Write unit tests for `TierService` — tier status, upgrade initiation, tier limit enforcement
|
||||
- [x] 8.3 Write unit tests for `ComplianceService` — report generation, agent card export, cache hit/miss
|
||||
- [x] 8.4 Write integration tests for all analytics endpoints (`/api/analytics/*`)
|
||||
- [x] 8.5 Write integration tests for all tier endpoints (`/api/tiers/*`) including Stripe webhook
|
||||
- [x] 8.6 Write integration tests for compliance endpoints (`/api/compliance/*`) including feature flag behavior
|
||||
- [x] 8.7 Run full test suite — verify >80% coverage on all new services
|
||||
- [x] 8.8 Run `tsc --noEmit` across API, portal, and CLI — zero errors
|
||||
- [x] 8.9 Run `next build` for portal — verify clean build and code-split chunks
|
||||
- [x] 8.10 Verify feature flags: `ANALYTICS_ENABLED=false` → 404 on analytics routes; `TIER_ENFORCEMENT=false` → no 429s; `COMPLIANCE_ENABLED=false` → 404 on compliance routes
|
||||
- [x] 8.11 Run AGNTCY conformance suite — all tests pass
|
||||
- [x] 8.12 Commit Phase 6 with message `feat(phase-6): WS3+WS4+WS6 — Analytics, Tiers, AGNTCY Compliance`
|
||||
Reference in New Issue
Block a user