fix(vv): resolve all 6 V&V issues — field trial unblocked

All findings from the inaugural LeadValidator audit resolved and
confirmed. Release gate: PASS.

VV_ISSUE_002 (BLOCKER): 15 OpenAPI specs verified present covering
all 20 route groups (46 endpoints documented in docs/openapi/)

VV_ISSUE_003 (MAJOR): Remove any types from src/db/pool.ts —
replaced pool.query shim with unknown[] + Object.defineProperty,
zero any types, eslint-disable suppressions removed

VV_ISSUE_004 (MAJOR): Remove raw Pool from ScaffoldController and
HealthDetailedController — injected AgentRepository/CredentialRepository
and DbProbe interface respectively; added CredentialRepository.findActiveClientId()

VV_ISSUE_005 (MAJOR): Add unit tests for 5 untested services —
ComplianceStatusStore, EventPublisher, MarketplaceService,
OIDCTrustPolicyService, UsageService

VV_ISSUE_006 (MAJOR): Add integration tests for 7 missing route
groups — analytics, billing, tiers, webhooks, marketplace,
oidc-trust-policies, oidc-token-exchange

VV_ISSUE_001 (MINOR): Create missing design.md and tasks.md in 4
OpenSpec archives — all archives now complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SentryAgent.ai Developer
2026-04-07 04:52:47 +00:00
parent d216096dfb
commit 7441c9f298
49 changed files with 8954 additions and 70 deletions

341
docs/openapi/tiers.yaml Normal file
View File

@@ -0,0 +1,341 @@
openapi: "3.0.3"
info:
title: SentryAgent.ai — Tier Management
version: 1.0.0
description: |
Tier status and upgrade endpoints for the SentryAgent.ai AgentIdP platform.
The tier system defines per-organization limits on agents, tokens, and API calls.
**All endpoints require a valid Bearer JWT.**
**Available tiers:**
| Tier | Max Agents | Max Tokens/Month | Rate Limit |
|------|-----------|-----------------|------------|
| `free` | 100 | 10,000 | 100 req/min |
| `pro` | 1,000 | 100,000 | 1,000 req/min |
| `enterprise` | unlimited | unlimited | custom |
servers:
- url: http://localhost:3000/api/v1
description: Local development server
- url: https://api.sentryagent.ai/v1
description: Production server
tags:
- name: Tiers
description: Tier status and upgrade management
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT access token obtained via `POST /token`.
Include as `Authorization: Bearer <token>`.
schemas:
PlanTier:
type: string
enum:
- free
- pro
- enterprise
description: Current subscription plan tier.
example: free
TierLimits:
type: object
description: Hard limits defined by the current tier.
required:
- maxAgents
- maxTokensPerMonth
- rateLimitPerMinute
properties:
maxAgents:
type: integer
description: Maximum number of agents allowed for this organization.
example: 100
maxTokensPerMonth:
type: integer
description: Maximum OAuth 2.0 token requests per calendar month.
example: 10000
rateLimitPerMinute:
type: integer
description: Maximum API requests per minute.
example: 100
TierUsage:
type: object
description: Live usage counters for the current billing period.
required:
- agentsRegistered
- tokensThisMonth
- requestsThisMinute
properties:
agentsRegistered:
type: integer
description: Current number of active (non-decommissioned) agents.
minimum: 0
example: 47
tokensThisMonth:
type: integer
description: Total OAuth 2.0 tokens issued in the current calendar month.
minimum: 0
example: 3214
requestsThisMinute:
type: integer
description: API requests in the current rate-limit window.
minimum: 0
example: 12
TierStatus:
type: object
description: Full tier status response — current tier, plan limits, and live usage.
required:
- organizationId
- tier
- limits
- usage
properties:
organizationId:
type: string
format: uuid
description: Organization the tier status applies to.
example: "org-1234-5678-abcd-ef01"
tier:
$ref: '#/components/schemas/PlanTier'
limits:
$ref: '#/components/schemas/TierLimits'
usage:
$ref: '#/components/schemas/TierUsage'
billingPeriodStart:
type: string
format: date
description: First day of the current billing period (UTC).
example: "2026-04-01"
billingPeriodEnd:
type: string
format: date
description: Last day of the current billing period (UTC).
example: "2026-04-30"
TierUpgradeRequest:
type: object
description: Request body for initiating a tier upgrade.
required:
- targetTier
properties:
targetTier:
type: string
enum:
- pro
- enterprise
description: |
The target plan tier to upgrade to.
Downgrading is not permitted via this endpoint.
example: "pro"
successUrl:
type: string
format: uri
description: |
URL to redirect to after successful payment.
Defaults to the platform dashboard when omitted.
example: "https://my-app.example.com/dashboard?upgrade=success"
cancelUrl:
type: string
format: uri
description: |
URL to redirect to if the user cancels checkout.
Defaults to the platform dashboard when omitted.
example: "https://my-app.example.com/dashboard?upgrade=cancel"
TierUpgradeResponse:
type: object
description: Stripe Checkout URL to initiate the tier upgrade payment flow.
required:
- checkoutUrl
- targetTier
properties:
checkoutUrl:
type: string
format: uri
description: |
Stripe-hosted Checkout page URL.
Redirect the authenticated user to this URL to complete payment.
example: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
targetTier:
$ref: '#/components/schemas/PlanTier'
ErrorResponse:
type: object
description: Standard error response envelope.
required:
- code
- message
properties:
code:
type: string
example: "UNAUTHORIZED"
message:
type: string
example: "A valid Bearer token is required to access this resource."
details:
type: object
additionalProperties: true
responses:
Unauthorized:
description: Missing or invalid Bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "UNAUTHORIZED"
message: "A valid Bearer token is required to access this resource."
Forbidden:
description: Valid token but insufficient permissions.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "FORBIDDEN"
message: "You do not have permission to perform this action."
InternalServerError:
description: Unexpected server error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "INTERNAL_SERVER_ERROR"
message: "An unexpected error occurred. Please try again later."
security:
- BearerAuth: []
paths:
/tiers/status:
get:
operationId: getTierStatus
tags:
- Tiers
summary: Get current tier status
description: |
Returns the current tier, plan limits, and live usage counters for the
authenticated organization.
The organization ID is derived from the `organization_id` claim in the
Bearer JWT — no explicit organization ID is required in the request.
Use this endpoint to:
- Display the current plan in your dashboard
- Check remaining quota before performing bulk operations
- Determine whether an upgrade is needed
responses:
'200':
description: Tier status returned successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/TierStatus'
example:
organizationId: "org-1234-5678-abcd-ef01"
tier: "free"
limits:
maxAgents: 100
maxTokensPerMonth: 10000
rateLimitPerMinute: 100
usage:
agentsRegistered: 47
tokensThisMonth: 3214
requestsThisMinute: 12
billingPeriodStart: "2026-04-01"
billingPeriodEnd: "2026-04-30"
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/tiers/upgrade:
post:
operationId: initiateTierUpgrade
tags:
- Tiers
summary: Initiate a tier upgrade via Stripe
description: |
Initiates a Stripe Checkout Session for upgrading the organization's plan tier.
The returned `checkoutUrl` is a Stripe-hosted payment page.
Redirect the authenticated user to this URL to complete the upgrade payment.
After successful payment, Stripe notifies the platform via the
`POST /billing/webhook` endpoint, which activates the new tier automatically.
**Constraints:**
- Only upgrades are supported (free → pro, free → enterprise, pro → enterprise).
- Attempting to "upgrade" to the current or lower tier returns `400`.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TierUpgradeRequest'
example:
targetTier: "pro"
successUrl: "https://my-app.example.com/dashboard?upgrade=success"
cancelUrl: "https://my-app.example.com/dashboard?upgrade=cancel"
responses:
'201':
description: Stripe Checkout Session created successfully. Redirect user to checkoutUrl.
content:
application/json:
schema:
$ref: '#/components/schemas/TierUpgradeResponse'
example:
checkoutUrl: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
targetTier: "pro"
'400':
description: Invalid upgrade request — already on target tier or attempting a downgrade.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
alreadyOnTier:
summary: Already on target tier
value:
code: "ALREADY_ON_TIER"
message: "Your organization is already on the 'pro' tier."
invalidDowngrade:
summary: Downgrade not permitted
value:
code: "DOWNGRADE_NOT_PERMITTED"
message: "Downgrading tiers is not supported via this endpoint."
missingOrgId:
summary: Missing organization_id in token
value:
code: "VALIDATION_ERROR"
message: "organization_id is required in token."
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
description: Unexpected error or Stripe API failure.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "STRIPE_ERROR"
message: "Failed to create Stripe Checkout Session. Please try again."