openapi: 3.0.3 info: title: SentryAgent.ai — Compliance & SOC 2 Type II Service version: 1.0.0 description: | The Compliance Service exposes endpoints supporting SentryAgent.ai's **SOC 2 Type II** audit readiness programme. Two categories of control are surfaced: **Audit chain verification** (`GET /audit/verify`) — Confirms cryptographic integrity of the immutable audit log chain across an optional date range. This endpoint provides auditors and compliance tooling with a single call to assert that no audit events have been tampered with, deleted, or reordered after initial capture. **SOC 2 control status** (`GET /compliance/controls`) — Returns a live status snapshot for each of the five in-scope SOC 2 Trust Services Criteria controls monitored by the platform. Designed as a lightweight, public health-style endpoint so that monitoring infrastructure can poll without bearer credentials. **In-scope SOC 2 controls:** | Control ID | Name | Description | |------------|------|-------------| | `CC6.1` | Encryption at Rest | Verifies database and secrets store encryption is active | | `CC6.7` | TLS Enforcement | Confirms TLS 1.2+ is enforced on all inbound connections | | `CC7.2` | Audit Log Integrity | Validates audit chain hash continuity | | `CC9.2` | Secrets Rotation | Checks that all managed secrets are within rotation policy | | `CC7.1` | Webhook Dead-Letter Monitoring | Asserts dead-letter queue depth is within threshold | **Required scope (audit chain verify only):** `audit:read` servers: - url: http://localhost:3000/api/v1 description: Local development server - url: https://api.sentryagent.ai/v1 description: Production server tags: - name: Audit Chain description: Cryptographic integrity verification of the immutable audit event chain - name: Compliance Controls description: SOC 2 Type II control status — public health-style monitoring endpoint components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: | JWT access token with `audit:read` scope, obtained via `POST /token`. Include as: `Authorization: Bearer ` schemas: ChainVerificationResult: type: object description: | Result of an audit event chain integrity verification run. The audit log is structured as a hash-linked chain. Each event stores a reference to the hash of the preceding event. `verified: true` means every event in the requested window was checked and no breaks in the chain were detected. When `verified` is `false`, `brokenAtEventId` identifies the first event where the chain integrity check failed, enabling targeted forensic investigation. required: - verified - checkedCount - brokenAtEventId properties: verified: type: boolean description: > `true` if every audit event in the checked range maintains an unbroken cryptographic hash chain; `false` if at least one chain break was detected. example: true checkedCount: type: integer description: Total number of audit events examined during this verification run. minimum: 0 example: 2847 brokenAtEventId: type: string format: uuid nullable: true description: > UUID of the first audit event where chain continuity failed, or `null` when `verified` is `true`. Only the first detected break is reported; subsequent events are not checked after a break is found. example: null fromDate: type: string format: date-time description: > The ISO 8601 lower bound of the date range that was verified. Present only when a `fromDate` query parameter was supplied. example: "2026-03-01T00:00:00.000Z" toDate: type: string format: date-time description: > The ISO 8601 upper bound of the date range that was verified. Present only when a `toDate` query parameter was supplied. example: "2026-03-31T23:59:59.999Z" ControlStatus: type: string description: Operational status of a SOC 2 control at the time of the last check. enum: - passing - failing - unknown example: passing ComplianceControl: type: object description: Status record for a single SOC 2 Trust Services Criteria control. required: - id - name - status - lastChecked properties: id: type: string description: SOC 2 Trust Services Criteria control identifier. enum: - CC6.1 - CC6.7 - CC7.2 - CC9.2 - CC7.1 example: "CC6.1" name: type: string description: Human-readable name of the control. example: "Encryption at Rest" status: $ref: '#/components/schemas/ControlStatus' lastChecked: type: string format: date-time description: ISO 8601 timestamp of the most recent automated check for this control. example: "2026-03-31T06:00:00.000Z" ComplianceControlsResponse: type: object description: SOC 2 compliance control status summary for all in-scope controls. required: - controls properties: controls: type: array description: Status record for each of the five in-scope SOC 2 controls. minItems: 5 maxItems: 5 items: $ref: '#/components/schemas/ComplianceControl' example: - id: "CC6.1" name: "Encryption at Rest" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC6.7" name: "TLS Enforcement" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.2" name: "Audit Log Integrity" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC9.2" name: "Secrets Rotation" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.1" name: "Webhook Dead-Letter Monitoring" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" ErrorResponse: type: object description: Standard error response envelope used across all SentryAgent.ai APIs. required: - code - message properties: code: type: string description: Machine-readable error code. example: "UNAUTHORIZED" message: type: string description: Human-readable description of the error. example: "A valid Bearer token is required." details: type: object description: Optional structured details providing additional context. additionalProperties: true example: {} 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. Requires `audit:read` scope. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "INSUFFICIENT_SCOPE" message: "The 'audit:read' scope is required to verify the audit chain." TooManyRequests: description: | Rate limit exceeded. Retry after the reset time indicated in `X-RateLimit-Reset`. headers: X-RateLimit-Limit: schema: type: integer description: Maximum requests allowed per minute. example: 30 X-RateLimit-Remaining: schema: type: integer description: Requests remaining in the current window. example: 0 X-RateLimit-Reset: schema: type: integer description: Unix timestamp when the rate limit window resets. example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "RATE_LIMIT_EXCEEDED" message: "Too many requests. Please retry after the rate limit window resets." 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." paths: /audit/verify: get: operationId: verifyAuditChain tags: - Audit Chain summary: Verify audit log chain integrity description: | Triggers a full integrity verification pass over the immutable audit event chain. Each event in the log contains a cryptographic hash of the previous event; this endpoint traverses the chain and confirms no breaks exist. **Use cases:** - Auditor evidence collection for SOC 2 Type II assessment - Continuous compliance monitoring (cron-driven) - Incident response — confirm audit log has not been tampered with **Requires:** Bearer token with `audit:read` scope. **Rate limit:** 30 requests/minute per `client_id`. Audit chain verification is a computationally intensive operation and is rate-limited more aggressively than standard read endpoints. For continuous monitoring, poll no more than once per minute. **Date range filtering:** Supply `fromDate` and/or `toDate` to restrict verification to a specific window. When omitted, the entire retained audit log is verified. `fromDate` must be before or equal to `toDate` when both are provided. **Result interpretation:** - `verified: true` — chain is intact across all checked events - `verified: false` — at least one chain break detected; `brokenAtEventId` identifies the first affected event security: - BearerAuth: [] parameters: - name: fromDate in: query description: | ISO 8601 date-time lower bound for the verification window (inclusive). When omitted, verification starts from the earliest available audit event. Must be before or equal to `toDate` when both are supplied. required: false schema: type: string format: date-time example: "2026-03-01T00:00:00.000Z" - name: toDate in: query description: | ISO 8601 date-time upper bound for the verification window (inclusive). When omitted, verification runs up to and including the most recent audit event. Must be after or equal to `fromDate` when both are supplied. required: false schema: type: string format: date-time example: "2026-03-31T23:59:59.999Z" responses: '200': description: | Audit chain verification completed. Inspect `verified` to determine whether chain integrity is intact. A `200` is returned regardless of whether verification passed or failed — check the response body. headers: X-RateLimit-Limit: schema: type: integer description: Maximum requests allowed per minute for this endpoint. example: 30 X-RateLimit-Remaining: schema: type: integer description: Requests remaining in the current rate limit window. example: 29 X-RateLimit-Reset: schema: type: integer description: Unix timestamp when the rate limit window resets. example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/ChainVerificationResult' examples: chainIntact: summary: Verification passed — chain is intact value: verified: true checkedCount: 2847 brokenAtEventId: null fromDate: "2026-03-01T00:00:00.000Z" toDate: "2026-03-31T23:59:59.999Z" chainBroken: summary: Verification failed — chain break detected value: verified: false checkedCount: 1203 brokenAtEventId: "c4d5e6f7-a8b9-0123-cdef-456789012345" fromDate: "2026-03-01T00:00:00.000Z" toDate: "2026-03-31T23:59:59.999Z" noDateRange: summary: Full log verified (no date range supplied) value: verified: true checkedCount: 18504 brokenAtEventId: null '400': description: Invalid query parameter value or date range. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: invalidFromDate: summary: fromDate is not a valid ISO 8601 date-time value: code: "VALIDATION_ERROR" message: "Invalid query parameter value." details: field: "fromDate" reason: "Must be a valid ISO 8601 date-time string (e.g. 2026-03-01T00:00:00.000Z)." invalidToDate: summary: toDate is not a valid ISO 8601 date-time value: code: "VALIDATION_ERROR" message: "Invalid query parameter value." details: field: "toDate" reason: "Must be a valid ISO 8601 date-time string (e.g. 2026-03-31T23:59:59.999Z)." invalidDateRange: summary: fromDate is after toDate value: code: "VALIDATION_ERROR" message: "Invalid date range." details: reason: "fromDate must be before or equal to toDate." '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' /compliance/controls: get: operationId: getComplianceControls tags: - Compliance Controls summary: Get SOC 2 control status summary description: | Returns a live status snapshot for each of the five in-scope SOC 2 Type II Trust Services Criteria controls monitored by the SentryAgent.ai platform. **No authentication required.** This endpoint is intentionally public (analogous to a health check) so that external monitoring infrastructure, status pages, and audit tooling can poll it without bearer credentials. **Controls monitored:** | Control ID | Name | What is checked | |------------|------|-----------------| | `CC6.1` | Encryption at Rest | Database and secrets store encryption is active and configured | | `CC6.7` | TLS Enforcement | TLS 1.2+ is enforced on all platform inbound connections | | `CC7.2` | Audit Log Integrity | Audit chain hash continuity — shorthand of `/audit/verify` | | `CC9.2` | Secrets Rotation | All managed secrets are within the rotation policy window | | `CC7.1` | Webhook Dead-Letter Monitoring | Dead-letter queue depth is within the acceptable threshold | **Status values:** - `passing` — control is operating within policy - `failing` — control has breached policy; immediate attention required - `unknown` — automated check could not complete (e.g. dependency unavailable) **Caching note:** Responses may be cached for up to 60 seconds by intermediate proxies. The `lastChecked` field on each control indicates the timestamp of the most recent automated evaluation. **Rate limit:** 120 requests/minute per IP address. security: [] responses: '200': description: SOC 2 control status summary returned successfully. headers: Cache-Control: schema: type: string description: > Downstream caches may serve this response for up to 60 seconds. example: "public, max-age=60" X-RateLimit-Limit: schema: type: integer description: Maximum requests allowed per minute for this endpoint. example: 120 X-RateLimit-Remaining: schema: type: integer description: Requests remaining in the current rate limit window. example: 119 X-RateLimit-Reset: schema: type: integer description: Unix timestamp when the rate limit window resets. example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/ComplianceControlsResponse' examples: allPassing: summary: All controls passing value: controls: - id: "CC6.1" name: "Encryption at Rest" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC6.7" name: "TLS Enforcement" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.2" name: "Audit Log Integrity" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC9.2" name: "Secrets Rotation" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.1" name: "Webhook Dead-Letter Monitoring" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" oneControlFailing: summary: One control failing (secrets rotation overdue) value: controls: - id: "CC6.1" name: "Encryption at Rest" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC6.7" name: "TLS Enforcement" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.2" name: "Audit Log Integrity" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC9.2" name: "Secrets Rotation" status: "failing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.1" name: "Webhook Dead-Letter Monitoring" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" unknownControl: summary: One control in unknown state (dependency unavailable) value: controls: - id: "CC6.1" name: "Encryption at Rest" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC6.7" name: "TLS Enforcement" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.2" name: "Audit Log Integrity" status: "unknown" lastChecked: "2026-03-31T05:00:00.000Z" - id: "CC9.2" name: "Secrets Rotation" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" - id: "CC7.1" name: "Webhook Dead-Letter Monitoring" status: "passing" lastChecked: "2026-03-31T06:00:00.000Z" '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError'