## WS6: AGNTCY Compliance Certification Package

### Purpose

Position SentryAgent.ai as the reference implementation for the AGNTCY standard. Deliver four artifacts: (1) an auto-generated machine-readable AGNTCY compliance report endpoint; (2) an agent card export endpoint per the AGNTCY Agent Card specification; (3) a Jest-based interoperability test suite verifying AGNTCY alignment on every CI run; (4) a human-readable certification guide documenting how SentryAgent.ai satisfies each AGNTCY requirement.

This workstream produces no user-facing UI changes. It is infrastructure for compliance, certification, and ecosystem trust.

### New Endpoints

#### `GET /agntcy/compliance-report`

**Summary:** Generate and return a real-time AGNTCY compliance report for the authenticated tenant's environment.

**Authentication:** Bearer token (tenant-scoped). The tenant's subscription tier must be `pro` or `enterprise`.

**Response 200** (`application/json`):
```json
{
  "reportId": "string (UUID)",
  "generatedAt": "string (ISO 8601)",
  "agntcySpecVersion": "1.0.0",
  "tenantId": "string (UUID)",
  "overallStatus": "compliant",
  "sections": [
    {
      "id": "agent-identity",
      "name": "Agent Identity",
      "status": "compliant",
      "requirements": [
        {
          "id": "AI-001",
          "description": "Each agent MUST have a globally unique, persistent identifier",
          "status": "compliant",
          "evidence": "All agents are assigned a UUID v4 at registration, stored immutably in agents.id",
          "verifiedAt": "string (ISO 8601)"
        },
        {
          "id": "AI-002",
          "description": "Each agent MUST have a W3C DID document",
          "status": "compliant",
          "evidence": "DID documents are auto-generated as did:web identifiers at agent registration",
          "verifiedAt": "string (ISO 8601)"
        }
      ]
    },
    {
      "id": "authentication",
      "name": "Authentication",
      "status": "compliant",
      "requirements": [
        {
          "id": "AUTH-001",
          "description": "Agent authentication MUST use OAuth 2.0 or OIDC",
          "status": "compliant",
          "evidence": "OAuth 2.0 Client Credentials flow implemented at POST /oauth2/token",
          "verifiedAt": "string (ISO 8601)"
        }
      ]
    },
    {
      "id": "authorization",
      "name": "Authorization",
      "status": "compliant",
      "requirements": []
    },
    {
      "id": "audit-and-governance",
      "name": "Audit & Governance",
      "status": "compliant",
      "requirements": []
    },
    {
      "id": "interoperability",
      "name": "Interoperability",
      "status": "compliant",
      "requirements": []
    },
    {
      "id": "delegation",
      "name": "Agent-to-Agent Delegation",
      "status": "compliant",
      "requirements": []
    }
  ],
  "summary": {
    "totalRequirements": 24,
    "compliant": 24,
    "nonCompliant": 0,
    "notApplicable": 0
  }
}
```

**`overallStatus`** values: `"compliant"` | `"partial"` | `"non-compliant"`

**Error Responses:**

| Status | Code | Description |
|---|---|---|
| 401 | `UNAUTHORIZED` | Missing or invalid Bearer token |
| 403 | `TIER_REQUIRED` | Compliance report requires Pro or Enterprise tier |
| 429 | `RATE_LIMITED` | Rate limit exceeded |

**Business Rules:**
- Report is generated on demand from live system state — no cache
- Each requirement's `status` is computed by querying current system configuration (e.g., verify DID documents exist by checking `agents` table, verify audit log is enabled by checking config)
- `agntcySpecVersion` is hardcoded to the AGNTCY spec version the system was last validated against
- An audit log entry is created with `event_type: "compliance.report_generated"`

---

#### `GET /agents/:id/agent-card`

**Summary:** Return the AGNTCY-compliant Agent Card for a specific agent. Agent Cards are publicly accessible for public agents and require authentication for private agents.

**Authentication:** Optional. Required only if the agent's `is_public` is `false`.

**Path Parameter:**

| Parameter | Type | Description |
|---|---|---|
| `id` | string (UUID) | Agent ID |

**Response 200** (`application/json`):

Per the AGNTCY Agent Card specification:
```json
{
  "agntcyVersion": "1.0",
  "type": "agent-card",
  "agent": {
    "id": "string (UUID)",
    "name": "string",
    "description": "string | null",
    "did": "did:web:sentryagent.ai:agents:abc123",
    "capabilities": ["string"],
    "version": "string",
    "publisher": {
      "tenantId": "string (UUID)",
      "name": "string"
    },
    "endpoints": {
      "tokenEndpoint": "https://api.sentryagent.ai/oauth2/token",
      "delegationEndpoint": "https://api.sentryagent.ai/oauth2/token/delegate"
    },
    "authentication": {
      "schemes": ["oauth2_client_credentials"],
      "tokenEndpoint": "https://api.sentryagent.ai/oauth2/token"
    },
    "governance": {
      "auditLogEnabled": true,
      "credentialRotationPolicy": "manual",
      "complianceStandards": ["AGNTCY-1.0", "OAuth2-RFC6749", "W3C-DID"]
    },
    "metadata": {}
  },
  "issuedAt": "string (ISO 8601)",
  "expiresAt": "string (ISO 8601)"
}
```

**Error Responses:**

| Status | Code | Description |
|---|---|---|
| 401 | `UNAUTHORIZED` | Agent is private and no Bearer token provided |
| 403 | `FORBIDDEN` | Agent is private and authenticated tenant does not own it |
| 404 | `AGENT_NOT_FOUND` | No agent with the given ID |
| 429 | `RATE_LIMITED` | Rate limit exceeded |

**Business Rules:**
- Public agents (`is_public: true`) return agent card without authentication
- Private agents require the owning tenant's Bearer token
- Agent card `expiresAt` is `issuedAt + 24 hours` (cards are short-lived — consumers should re-fetch daily)
- `complianceStandards` array is sourced from system config, not per-agent configuration

---

### AGNTCY Interoperability Test Suite

**File:** `tests/agntcy/interoperability.test.ts`

A Jest test suite that verifies AGNTCY alignment on every CI run. Tests run against a live API instance (reads `AGENTIDP_API_URL` from environment).

**Test categories and cases:**

```typescript
// AGNTCY-AI-001: Agent identity uniqueness
test('each registered agent receives a unique UUID', ...)
test('agent UUID is immutable after registration', ...)

// AGNTCY-AI-002: W3C DID documents
test('registered agent has a valid did:web DID', ...)
test('DID document resolves via GET /agents/:id', ...)

// AGNTCY-AUTH-001: OAuth 2.0 token issuance
test('POST /oauth2/token returns access_token and token_type: bearer', ...)
test('access token is a valid JWT with correct claims', ...)
test('expired token is rejected with 401', ...)

// AGNTCY-AUTH-002: OIDC compliance
test('GET /.well-known/openid-configuration returns valid OIDC discovery document', ...)
test('JWKS endpoint returns valid JWK Set', ...)

// AGNTCY-AUTHZ-001: Scope-based access control
test('token with agent:read scope cannot call agent:write operations', ...)
test('scopes are included in JWT payload', ...)

// AGNTCY-DEL-001: Agent-to-Agent delegation
test('POST /oauth2/token/delegate creates a valid delegation chain', ...)
test('delegated scopes cannot exceed delegator scopes', ...)
test('POST /oauth2/token/verify-delegation returns valid: true for active chain', ...)
test('POST /oauth2/token/verify-delegation returns valid: false for expired chain', ...)

// AGNTCY-AUDIT-001: Immutable audit logs
test('every token issuance creates an audit log entry', ...)
test('audit log entries cannot be deleted via API', ...)

// AGNTCY-GOV-001: Agent lifecycle governance
test('credential rotation is logged in audit log', ...)
test('agent deletion logs deletion event in audit log', ...)

// AGNTCY-INTER-001: Agent Card export
test('GET /agents/:id/agent-card returns valid AGNTCY Agent Card', ...)
test('Agent Card contains required agntcyVersion, did, capabilities fields', ...)

// AGNTCY-COMP-001: Compliance report
test('GET /agntcy/compliance-report returns compliant status', ...)
test('compliance report covers all 6 AGNTCY sections', ...)
test('compliance report totalRequirements >= 24', ...)
```

**Running the suite:**
```bash
# In CI (requires live API):
AGENTIDP_API_URL=http://localhost:3000 npm run test:agntcy

# Added to package.json:
"test:agntcy": "jest --testPathPattern=tests/agntcy --forceExit"
```

---

### AGNTCY Certification Guide

**File:** `docs/agntcy/certification-guide.md`

A markdown document structured as follows:
1. **Overview** — What AGNTCY certification means and how SentryAgent.ai achieves it
2. **Requirement Mapping** — Table mapping each AGNTCY requirement ID to the SentryAgent.ai implementation (endpoint, service, or config)
3. **Running the Compliance Report** — Step-by-step guide to generating and interpreting the compliance report
4. **Agent Card Usage** — How to retrieve, cache, and use Agent Cards in multi-agent workflows
5. **Self-Certification Checklist** — Checklist for operators deploying self-hosted SentryAgent.ai to verify their instance's compliance
6. **Submitting for Official AGNTCY Certification** — Links and instructions for the Linux Foundation AGNTCY certification program

---

### New Source Files

| File | Description |
|---|---|
| `src/services/ComplianceService.ts` | Business logic: query system state, evaluate each AGNTCY requirement, build report |
| `src/controllers/ComplianceController.ts` | HTTP handlers for compliance report and agent card endpoints |
| `src/routes/agntcy.ts` | Express router: `GET /agntcy/compliance-report`, `GET /agents/:id/agent-card` |
| `src/types/compliance.ts` | TypeScript interfaces: `ComplianceReport`, `ComplianceSection`, `ComplianceRequirement`, `AgentCard` |
| `src/config/agntcyRequirements.ts` | Static array of AGNTCY requirement definitions (id, description, evaluator function reference) |
| `tests/agntcy/interoperability.test.ts` | Jest interoperability test suite |
| `docs/agntcy/certification-guide.md` | Human-readable certification guide |

### Modified Source Files

| File | Change |
|---|---|
| `src/routes/index.ts` | Register `agntcy` router |
| `src/routes/agents.ts` | Add `GET /agents/:id/agent-card` route (or register via agntcy router — agent-card is agent-scoped) |
| `package.json` (API) | Add `"test:agntcy"` script |
| `docs/openapi.yaml` | Add `GET /agntcy/compliance-report` and `GET /agents/:id/agent-card` endpoints |

### `ComplianceService` Interface

```typescript
interface IComplianceService {
    /**
     * Generate a live AGNTCY compliance report for the given tenant.
     * Evaluates all registered AGNTCY requirements against current system state.
     */
    generateComplianceReport(tenantId: string): Promise<ComplianceReport>;

    /**
     * Generate an AGNTCY Agent Card for a specific agent.
     */
    generateAgentCard(agentId: string): Promise<AgentCard>;
}
```

### Prometheus Metrics

| Metric | Type | Labels | Description |
|---|---|---|---|
| `agentidp_compliance_reports_generated_total` | Counter | `tenant_id` | Total compliance reports generated |
| `agentidp_compliance_report_duration_ms` | Histogram | — | Time to generate compliance report |
| `agentidp_agent_cards_served_total` | Counter | `visibility` (public/private) | Agent cards served by visibility |

### Feature Flag

`AGNTCY_ENABLED` (default: `true`). When `false`, all `/agntcy/` routes and `GET /agents/:id/agent-card` return HTTP 404.

### Acceptance Criteria

- `GET /agntcy/compliance-report` returns a report with `overallStatus: "compliant"` on a correctly configured instance
- Report contains all 6 sections: agent-identity, authentication, authorization, audit-and-governance, interoperability, delegation
- Report `totalRequirements >= 24`
- `GET /agents/:id/agent-card` returns a valid AGNTCY Agent Card with all required fields
- Agent Card is accessible without auth for public agents
- Agent Card requires owning tenant's auth for private agents
- All 25+ interoperability test cases pass against a live API instance
- `npm run test:agntcy` exits 0 on a correctly configured instance
- `docs/agntcy/certification-guide.md` is complete — no TODOs, no placeholders
- Unit tests cover: compliance report generation (compliant system, partially compliant), agent card generation (public agent, private agent)
