chore(openspec): trim phase-5 scope to WS1+WS2+WS5 per CEO approval
Approved: Rust SDK, A2A Authorization, Developer Experience. Deferred to Phase 6: Analytics Dashboard, API Gateway Tiers, AGNTCY Compliance. Tasks: 119 → 76. Specs: 6 → 3. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -56,120 +56,45 @@
|
||||
- [ ] 7.7 Write unit tests for `DelegationService` — mock DB and audit service; test: create delegation (valid), create delegation (scope escalation rejected), create delegation (self-delegation rejected), create delegation (delegatee in different tenant rejected), verify delegation (valid), verify delegation (expired — returns valid: false not throw), verify delegation (revoked — returns valid: false), revoke delegation (by delegator — succeeds), revoke delegation (by non-delegator — throws ForbiddenError), revoke delegation (already revoked — throws ConflictError)
|
||||
- [ ] 7.8 Write integration tests for delegation endpoints — test all happy paths and all error cases defined in spec; verify audit log entries are created for each delegation operation
|
||||
|
||||
## 8. WS3: Analytics — Database, Aggregation Job
|
||||
## 8. WS5: Developer Experience — Scaffold Service
|
||||
|
||||
- [ ] 8.1 Create `src/infrastructure/migrations/009_add_analytics_aggregates.sql` — create `analytics_daily_aggregates` table with columns: `id` (UUID PK), `tenant_id` (UUID FK), `agent_id` (UUID nullable FK), `date` (DATE), `metric_type` (VARCHAR 64), `count` (BIGINT), `created_at`, `updated_at`; add unique constraint on `(tenant_id, agent_id, date, metric_type)`; create indexes on `(tenant_id, date)` and `(agent_id, date) WHERE agent_id IS NOT NULL`
|
||||
- [ ] 8.2 Install `node-cron` npm package — add to `package.json`
|
||||
- [ ] 8.3 Create `src/jobs/analyticsAggregation.ts` — implement `runAnalyticsAggregation(targetDate: Date): Promise<void>`: execute upsert query aggregating previous day's `usage_events` rows into `analytics_daily_aggregates`; query is idempotent (upsert on unique constraint); update `agentidp_analytics_aggregation_job_duration_ms` gauge and `agentidp_analytics_aggregation_job_last_run` gauge on completion
|
||||
- [ ] 8.4 Register cron job in `src/app.ts` — schedule `runAnalyticsAggregation` at `00:05 UTC` daily using `node-cron`; log job start, completion, and any errors; do not crash the process on job failure — log error and continue
|
||||
- [ ] 8.1 Install `archiver` and `@types/archiver` in API `package.json`
|
||||
- [ ] 8.2 Create `src/types/scaffold.ts` — define `ScaffoldLanguage` union (`'typescript' | 'python' | 'go' | 'java' | 'rust'`), `ScaffoldOptions` interface, `ScaffoldTemplate` interface
|
||||
- [ ] 8.3 Create scaffold template files for TypeScript in `src/templates/scaffold/typescript/`: `package.json.tmpl`, `tsconfig.json.tmpl`, `src/index.ts.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl` — each file uses `{{AGENT_ID}}`, `{{AGENT_NAME}}`, `{{CLIENT_ID}}`, `{{API_URL}}` as template variables; `.env.example.tmpl` MUST include `AGENTIDP_CLIENT_SECRET=<your-client-secret>` placeholder (never inject real secret)
|
||||
- [ ] 8.4 Create scaffold template files for Python in `src/templates/scaffold/python/`: `requirements.txt.tmpl`, `main.py.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl` — same template variable convention
|
||||
- [ ] 8.5 Create scaffold template files for Go in `src/templates/scaffold/go/`: `go.mod.tmpl`, `main.go.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl`
|
||||
- [ ] 8.6 Create scaffold template files for Java in `src/templates/scaffold/java/`: `pom.xml.tmpl`, `src/main/java/Main.java.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl`
|
||||
- [ ] 8.7 Create scaffold template files for Rust in `src/templates/scaffold/rust/`: `Cargo.toml.tmpl`, `src/main.rs.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl`
|
||||
- [ ] 8.8 Create `src/services/ScaffoldService.ts` — implement `IScaffoldService`; `generateScaffold(agentId, language, apiUrl)`: load template files for language, inject template variables (replace `{{AGENT_ID}}`, `{{AGENT_NAME}}`, `{{CLIENT_ID}}`, `{{API_URL}}`), build in-memory ZIP using `archiver`; return `{ stream: NodeJS.ReadableStream, filename: string }`; emit `agentidp_scaffold_generated_total` counter and `agentidp_scaffold_generation_duration_ms` histogram
|
||||
|
||||
## 9. WS3: Analytics — Service, Controller, Routes
|
||||
## 9. WS5: Developer Experience — Scaffold Controller & Route
|
||||
|
||||
- [ ] 9.1 Create `src/types/analytics.ts` — define interfaces: `UsageSummary`, `AgentActivityResponse`, `TokenTrendsResponse`, `DailyAggregate`, `AnalyticsDateRange`
|
||||
- [ ] 9.2 Create `src/services/AnalyticsService.ts` — implement `IAnalyticsService`; `getUsageSummary`: validate date range (from <= to, max 365 days), check Redis cache (`analytics:{tenantId}:summary:{hash}`, TTL 60s), on miss query `analytics_daily_aggregates`, compute totals, write to cache, return `UsageSummary`
|
||||
- [ ] 9.3 Implement `AnalyticsService.getAgentActivity(tenantId, from, to, agentId?)` — validate date range (max 90 days), check Redis cache (TTL 5 min), on miss query `analytics_daily_aggregates` grouped by `agent_id` and `date`, join agent names from `agents` table, write to cache, return `AgentActivityResponse`
|
||||
- [ ] 9.4 Implement `AnalyticsService.getTokenTrends(tenantId, from, to, granularity)` — support `day` and `week` granularity (weekly: `date_trunc('week', date)`), check Redis cache (TTL 5 min), return `TokenTrendsResponse` with `successfulIssuances`, `failedIssuances`, `uniqueAgents` per period
|
||||
- [ ] 9.5 Create `src/controllers/AnalyticsController.ts` — handlers for `getUsageSummary`, `getAgentActivity`, `getTokenTrends`; parse and validate query parameters; return HTTP 403 for free-tier tenants (check `ANALYTICS_FREE_TIER` env and tenant subscription); emit `agentidp_analytics_query_duration_ms` histogram and cache hit/miss counters
|
||||
- [ ] 9.6 Create `src/routes/analytics.ts` — Express router for `/analytics/usage-summary`, `/analytics/agent-activity`, `/analytics/token-trends`; all routes require authentication middleware
|
||||
- [ ] 9.7 Register analytics router in `src/routes/index.ts` behind `ANALYTICS_ENABLED` feature flag
|
||||
- [ ] 9.8 Add analytics endpoints to `docs/openapi.yaml` — all query parameters, response schemas, and error codes as defined in spec
|
||||
- [ ] 9.9 Write unit tests for `AnalyticsService` — test: usage-summary (cache hit), usage-summary (cache miss → DB query), agent-activity (with agentId filter), agent-activity (no filter — all agents), token-trends (daily), token-trends (weekly), date range validation (from > to rejected), date range validation (> max days rejected), free-tier rejection
|
||||
- [ ] 9.10 Write integration tests for analytics endpoints — test all three endpoints with valid date ranges, verify free-tier rejection, verify invalid date range errors
|
||||
- [ ] 9.1 Create `src/controllers/ScaffoldController.ts` — implement `getScaffold` handler for `GET /sdk/scaffold/:agentId`: validate `language` query param against `ScaffoldLanguage` union (HTTP 400 on invalid); fetch agent, verify agent belongs to authenticated tenant (HTTP 403 if not); call `ScaffoldService.generateScaffold`; set `Content-Type: application/zip`, `Content-Disposition: attachment; filename="..."`, pipe stream to response; write audit log entry (`scaffold.generated`, metadata: `{ language }`)
|
||||
- [ ] 9.2 Create `src/routes/scaffold.ts` — Express router for `GET /sdk/scaffold/:agentId` with authentication middleware; apply scaffold-specific rate limiter (10 req/min per tenant, separate from global rate limiter)
|
||||
- [ ] 9.3 Register `scaffold` router in `src/routes/index.ts`
|
||||
- [ ] 9.4 Add `GET /sdk/scaffold/:agentId` to `docs/openapi.yaml` — document binary response type, query parameters, all error responses
|
||||
- [ ] 9.5 Write unit tests for `ScaffoldService` — test: generate TypeScript scaffold (verify ZIP contains all 6 files), generate Python scaffold (verify all 5 files), verify `{{CLIENT_ID}}` is replaced in `.env.example`, verify `{{AGENTIDP_CLIENT_SECRET}}` is placeholder not real secret, verify invalid language throws `ValidationError`
|
||||
- [ ] 9.6 Write integration tests for scaffold endpoint — test: TypeScript scaffold returns ZIP with correct `Content-Type` and `Content-Disposition`; Python scaffold returns ZIP; HTTP 400 on invalid language; HTTP 403 when agent belongs to different tenant; HTTP 404 when agent does not exist
|
||||
|
||||
## 10. WS3: Analytics — Dashboard UI
|
||||
## 10. WS5: Developer Experience — Portal & CLI
|
||||
|
||||
- [ ] 10.1 Install `recharts` and `date-fns` in `dashboard/package.json`
|
||||
- [ ] 10.2 Create `dashboard/src/api/analyticsApi.ts` — typed fetch functions for all three analytics endpoints: `fetchUsageSummary(token, from, to)`, `fetchAgentActivity(token, from, to, agentId?)`, `fetchTokenTrends(token, from, to, granularity)`; all functions return typed response objects; handle 403 response with a typed `AnalyticsNotAvailableError`
|
||||
- [ ] 10.3 Create `dashboard/src/components/charts/AgentHeatmap.tsx` — renders a grid heatmap (agents × dates) using `recharts` or a custom CSS grid; color intensity represents `apiCalls` count; hover tooltip shows agent name, date, apiCalls, tokenIssuances, credentialRotations; accepts `agents` prop from `AgentActivityResponse`
|
||||
- [ ] 10.4 Create `dashboard/src/components/charts/TokenTrendsChart.tsx` — renders a `recharts` `ComposedChart` with a `Line` for `successfulIssuances` and a `Bar` for `failedIssuances`; X-axis is dates; tooltip shows all three metrics per period; accepts `dataPoints` prop from `TokenTrendsResponse`
|
||||
- [ ] 10.5 Create `dashboard/src/components/charts/RotationFrequencyTable.tsx` — renders a sortable table of credential rotation counts per agent; columns: Agent Name, Rotations (period), Last Rotation Date; sortable by any column; accepts `agents` prop derived from `AgentActivityResponse` filtering `credentialRotations`
|
||||
- [ ] 10.6 Create `dashboard/src/pages/Analytics.tsx` — analytics tab page; renders date range picker (from/to), calls all three analytics APIs, renders `AgentHeatmap`, `TokenTrendsChart`, `RotationFrequencyTable`; shows a `UpgradeRequired` component when API returns 403
|
||||
- [ ] 10.7 Add Analytics route to `dashboard/src/App.tsx` — add `/analytics` route; add "Analytics" link to dashboard navigation
|
||||
- [ ] 10.8 Run `npm run build` in `dashboard/` — zero TypeScript errors, zero ESLint errors
|
||||
- [ ] 10.1 Install `@stoplight/elements` in `portal/package.json` — remove `swagger-ui-react`
|
||||
- [ ] 10.2 Rewrite `portal/app/api-explorer/page.tsx` — replace `SwaggerUI` component with `@stoplight/elements` `<API>` component; set `apiDescriptionUrl`, `router="hash"`, `layout="sidebar"`, `hideSchemas={false}`, `tryItCredentialsPolicy="same-origin"`; import Elements CSS; remove all Swagger UI imports and CSS
|
||||
- [ ] 10.3 Run `npm run build` in `portal/` — verify zero TypeScript errors and zero ESLint errors after Elements integration
|
||||
- [ ] 10.4 Install `unzipper` and `@types/unzipper` in `cli/package.json`
|
||||
- [ ] 10.5 Create `cli/src/commands/scaffold.ts` — implement `sentryagent scaffold` command with Commander options: `--agent-id <id>` (required), `--language <lang>` (default: typescript), `--out <directory>` (default: `.`); load config, issue Bearer token, call `GET /sdk/scaffold/{agentId}?language={language}`, pipe response through `unzipper.Extract({ path: outDir })`, print success message and next steps; handle errors (404, 403, 400) with human-readable messages
|
||||
- [ ] 10.6 Register `scaffold` command in `cli/src/index.ts` — add `.addCommand(scaffoldCommand)` to Commander program
|
||||
- [ ] 10.7 Run `npm run build` in `cli/` — zero TypeScript errors; run `node dist/index.js scaffold --help` — outputs correct usage
|
||||
|
||||
## 11. WS4: API Gateway Tiers — Configuration & Middleware
|
||||
## 11. QA & Release
|
||||
|
||||
- [ ] 11.1 Create `src/types/tiers.ts` — define interfaces: `TierName` (union: `'free' | 'pro' | 'enterprise'`), `TierLimits`, `TierFeatures`, `TierDefinition` (includes `id`, `limits`, `features`, `stripeProductId`)
|
||||
- [ ] 11.2 Create `src/config/tiers.ts` — define `TIER_CONFIG: Record<TierName, TierDefinition>` with complete limit and feature definitions for `free`, `pro`, and `enterprise` tiers as specified in spec; export `getTierConfig(tier: TierName): TierDefinition` helper
|
||||
- [ ] 11.3 Create `src/middleware/tierRateLimiter.ts` — implement `TierRateLimiter` middleware: extract `tenantId` from authenticated request context; check Redis key `tier:{tenantId}` (TTL 60s) for cached tier; on miss query `tenant_subscriptions` for tenant's current tier, cache for 60s; look up rate limit config from `TIER_CONFIG`; apply `RateLimiterRedis` with key `rl:{tier}:{tenantId}`; on rejection return HTTP 429 with `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `Retry-After` headers; increment `agentidp_rate_limit_hits_total` counter with `tier` and `tenant_id` labels
|
||||
- [ ] 11.4 Replace `RateLimiterRedis` middleware on all authenticated routes in `src/routes/index.ts` with `TierRateLimiter`; keep the flat IP-based `RateLimiterRedis` on unauthenticated routes unchanged; wrap replacement in `TIER_RATE_LIMITING_ENABLED` feature flag (fall back to old middleware when `false`)
|
||||
|
||||
## 12. WS4: API Gateway Tiers — Endpoints
|
||||
|
||||
- [ ] 12.1 Create `src/routes/tiers.ts` — Express router for `GET /tiers`; handler reads `TIER_CONFIG`, formats response as specified in spec, sets `Cache-Control: public, max-age=3600` header; no database query; no authentication required
|
||||
- [ ] 12.2 Register `tiers` router in `src/routes/index.ts`
|
||||
- [ ] 12.3 Implement `BillingService.upgradeTier(tenantId: string, targetTier: 'pro' | 'enterprise'): Promise<{ checkoutUrl: string; sessionId: string; expiresAt: string }>` — fetch current tier from `tenant_subscriptions`, validate no self-upgrade or downgrade, create Stripe Checkout session with `STRIPE_PRICE_ID_PRO` or `STRIPE_PRICE_ID_ENTERPRISE`, return checkout URL
|
||||
- [ ] 12.4 Add `upgradeTier` handler to `src/controllers/BillingController.ts` — validate `targetTier` enum, call `BillingService.upgradeTier`, return HTTP 200 with `checkoutUrl`, `sessionId`, `targetTier`, `expiresAt`
|
||||
- [ ] 12.5 Register `POST /billing/upgrade` route in `src/routes/billing.ts` with authentication middleware
|
||||
- [ ] 12.6 Add `STRIPE_PRICE_ID_PRO`, `STRIPE_PRICE_ID_ENTERPRISE`, `TIER_RATE_LIMITING_ENABLED` to `.env.example` with documentation comments
|
||||
- [ ] 12.7 Add `GET /tiers` and `POST /billing/upgrade` to `docs/openapi.yaml`
|
||||
- [ ] 12.8 Write unit tests for `TierRateLimiter` — test: free tier limit enforced (60 req/min), pro tier limit enforced (600 req/min), tier looked up from Redis cache (DB not called), tier fetched from DB on cache miss, rollback path (`TIER_RATE_LIMITING_ENABLED=false` uses old flat limiter)
|
||||
- [ ] 12.9 Write unit tests for `BillingService.upgradeTier` — test: upgrade free → pro (creates Stripe session), upgrade free → enterprise (creates Stripe session), already on pro (returns ALREADY_ON_TIER error), downgrade attempt (returns DOWNGRADE_NOT_SUPPORTED error)
|
||||
- [ ] 12.10 Write integration tests for `GET /tiers` — verify response structure, verify `Cache-Control` header, verify no auth required; write integration tests for `POST /billing/upgrade` — mock Stripe, verify checkout URL returned
|
||||
|
||||
## 13. WS5: Developer Experience — Scaffold Service
|
||||
|
||||
- [ ] 13.1 Install `archiver` and `@types/archiver` in API `package.json`
|
||||
- [ ] 13.2 Create `src/types/scaffold.ts` — define `ScaffoldLanguage` union (`'typescript' | 'python' | 'go' | 'java' | 'rust'`), `ScaffoldOptions` interface, `ScaffoldTemplate` interface
|
||||
- [ ] 13.3 Create scaffold template files for TypeScript in `src/templates/scaffold/typescript/`: `package.json.tmpl`, `tsconfig.json.tmpl`, `src/index.ts.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl` — each file uses `{{AGENT_ID}}`, `{{AGENT_NAME}}`, `{{CLIENT_ID}}`, `{{API_URL}}` as template variables; `.env.example.tmpl` MUST include `AGENTIDP_CLIENT_SECRET=<your-client-secret>` placeholder (never inject real secret)
|
||||
- [ ] 13.4 Create scaffold template files for Python in `src/templates/scaffold/python/`: `requirements.txt.tmpl`, `main.py.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl` — same template variable convention
|
||||
- [ ] 13.5 Create scaffold template files for Go in `src/templates/scaffold/go/`: `go.mod.tmpl`, `main.go.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl`
|
||||
- [ ] 13.6 Create scaffold template files for Java in `src/templates/scaffold/java/`: `pom.xml.tmpl`, `src/main/java/Main.java.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl`
|
||||
- [ ] 13.7 Create scaffold template files for Rust in `src/templates/scaffold/rust/`: `Cargo.toml.tmpl`, `src/main.rs.tmpl`, `.env.example.tmpl`, `.gitignore.tmpl`, `README.md.tmpl`
|
||||
- [ ] 13.8 Create `src/services/ScaffoldService.ts` — implement `IScaffoldService`; `generateScaffold(agentId, language, apiUrl)`: load template files for language, inject template variables (replace `{{AGENT_ID}}`, `{{AGENT_NAME}}`, `{{CLIENT_ID}}`, `{{API_URL}}`), build in-memory ZIP using `archiver`; return `{ stream: NodeJS.ReadableStream, filename: string }`; emit `agentidp_scaffold_generated_total` counter and `agentidp_scaffold_generation_duration_ms` histogram
|
||||
|
||||
## 14. WS5: Developer Experience — Scaffold Controller & Route
|
||||
|
||||
- [ ] 14.1 Create `src/controllers/ScaffoldController.ts` — implement `getScaffold` handler for `GET /sdk/scaffold/:agentId`: validate `language` query param against `ScaffoldLanguage` union (HTTP 400 on invalid); fetch agent, verify agent belongs to authenticated tenant (HTTP 403 if not); call `ScaffoldService.generateScaffold`; set `Content-Type: application/zip`, `Content-Disposition: attachment; filename="..."`, pipe stream to response; write audit log entry (`scaffold.generated`, metadata: `{ language }`)
|
||||
- [ ] 14.2 Create `src/routes/scaffold.ts` — Express router for `GET /sdk/scaffold/:agentId` with authentication middleware; apply scaffold-specific rate limiter (10 req/min per tenant, separate from `TierRateLimiter`)
|
||||
- [ ] 14.3 Register `scaffold` router in `src/routes/index.ts`
|
||||
- [ ] 14.4 Add `GET /sdk/scaffold/:agentId` to `docs/openapi.yaml` — document binary response type, query parameters, all error responses
|
||||
- [ ] 14.5 Write unit tests for `ScaffoldService` — test: generate TypeScript scaffold (verify ZIP contains all 6 files), generate Python scaffold (verify all 5 files), verify `{{CLIENT_ID}}` is replaced in `.env.example`, verify `{{AGENTIDP_CLIENT_SECRET}}` is placeholder not real secret, verify invalid language throws `ValidationError`
|
||||
- [ ] 14.6 Write integration tests for scaffold endpoint — test: TypeScript scaffold returns ZIP with correct `Content-Type` and `Content-Disposition`; Python scaffold returns ZIP; HTTP 400 on invalid language; HTTP 403 when agent belongs to different tenant; HTTP 404 when agent does not exist
|
||||
|
||||
## 15. WS5: Developer Experience — Portal & CLI
|
||||
|
||||
- [ ] 15.1 Install `@stoplight/elements` in `portal/package.json` — remove `swagger-ui-react`
|
||||
- [ ] 15.2 Rewrite `portal/app/api-explorer/page.tsx` — replace `SwaggerUI` component with `@stoplight/elements` `<API>` component; set `apiDescriptionUrl`, `router="hash"`, `layout="sidebar"`, `hideSchemas={false}`, `tryItCredentialsPolicy="same-origin"`; import Elements CSS; remove all Swagger UI imports and CSS
|
||||
- [ ] 15.3 Run `npm run build` in `portal/` — verify zero TypeScript errors and zero ESLint errors after Elements integration
|
||||
- [ ] 15.4 Install `unzipper` and `@types/unzipper` in `cli/package.json`
|
||||
- [ ] 15.5 Create `cli/src/commands/scaffold.ts` — implement `sentryagent scaffold` command with Commander options: `--agent-id <id>` (required), `--language <lang>` (default: typescript), `--out <directory>` (default: `.`); load config, issue Bearer token, call `GET /sdk/scaffold/{agentId}?language={language}`, pipe response through `unzipper.Extract({ path: outDir })`, print success message and next steps; handle errors (404, 403, 400) with human-readable messages
|
||||
- [ ] 15.6 Register `scaffold` command in `cli/src/index.ts` — add `.addCommand(scaffoldCommand)` to Commander program
|
||||
- [ ] 15.7 Run `npm run build` in `cli/` — zero TypeScript errors; run `node dist/index.js scaffold --help` — outputs correct usage
|
||||
|
||||
## 16. WS6: AGNTCY Compliance — Compliance Service
|
||||
|
||||
- [ ] 16.1 Create `src/types/compliance.ts` — define interfaces: `ComplianceRequirement` (id, description, status, evidence, verifiedAt), `ComplianceSection` (id, name, status, requirements), `ComplianceReport` (reportId, generatedAt, agntcySpecVersion, tenantId, overallStatus, sections, summary), `AgentCard` (agntcyVersion, type, agent, issuedAt, expiresAt)
|
||||
- [ ] 16.2 Create `src/config/agntcyRequirements.ts` — define the complete array of AGNTCY requirement objects (minimum 24 requirements), each with: `id` (e.g., `AI-001`), `description` (from AGNTCY spec), `section` (e.g., `agent-identity`), and `evaluate(tenantId: string, db: Pool): Promise<RequirementEvaluation>` function — each evaluator queries the live system and returns `{ status, evidence }`
|
||||
- [ ] 16.3 Create `src/services/ComplianceService.ts` — implement `IComplianceService`; `generateComplianceReport(tenantId)`: run all requirement evaluators from `agntcyRequirements.ts` in parallel, group results by section, compute overall status (`compliant` if all pass, `partial` if any non-compliant, `non-compliant` if >20% fail), build `ComplianceReport`, write audit log entry (`compliance.report_generated`), emit `agentidp_compliance_reports_generated_total` counter and `agentidp_compliance_report_duration_ms` histogram
|
||||
- [ ] 16.4 Implement `ComplianceService.generateAgentCard(agentId)` — fetch agent from DB, build `AgentCard` per AGNTCY spec format, set `expiresAt = issuedAt + 24 hours`, set `complianceStandards` from system config, emit `agentidp_agent_cards_served_total` counter with `visibility` label
|
||||
|
||||
## 17. WS6: AGNTCY Compliance — Controller, Routes
|
||||
|
||||
- [ ] 17.1 Create `src/controllers/ComplianceController.ts` — implement `getComplianceReport` handler: check tenant tier is pro or enterprise (HTTP 403 `TIER_REQUIRED` for free tier), call `ComplianceService.generateComplianceReport`, return HTTP 200; implement `getAgentCard` handler: check agent visibility (HTTP 401 if private and unauthenticated, HTTP 403 if private and wrong tenant), call `ComplianceService.generateAgentCard`, return HTTP 200
|
||||
- [ ] 17.2 Create `src/routes/agntcy.ts` — Express router for `GET /agntcy/compliance-report` (requires auth) and `GET /agents/:id/agent-card` (auth optional); register behind `AGNTCY_ENABLED` feature flag
|
||||
- [ ] 17.3 Register `agntcy` router in `src/routes/index.ts`
|
||||
- [ ] 17.4 Add `GET /agntcy/compliance-report` and `GET /agents/:id/agent-card` to `docs/openapi.yaml`
|
||||
- [ ] 17.5 Write unit tests for `ComplianceService` — test: `generateComplianceReport` (all 24 requirements pass → `compliant`), `generateComplianceReport` (one evaluator fails → `partial`), `generateAgentCard` (public agent), `generateAgentCard` (private agent — verify agent data is included), `generateAgentCard` (non-existent agent → throws NotFoundError)
|
||||
- [ ] 17.6 Write integration tests for compliance endpoints — test: compliance report for pro tenant (HTTP 200, overallStatus), compliance report for free tenant (HTTP 403), agent card for public agent (no auth required), agent card for private agent (auth required, correct tenant succeeds, wrong tenant HTTP 403)
|
||||
|
||||
## 18. WS6: AGNTCY Compliance — Interoperability Tests & Docs
|
||||
|
||||
- [ ] 18.1 Create `tests/agntcy/interoperability.test.ts` — implement all 25+ AGNTCY interoperability test cases as defined in spec: AI-001 (agent UUID uniqueness), AI-002 (W3C DID document), AUTH-001 (OAuth 2.0 token issuance), AUTH-002 (OIDC discovery), AUTHZ-001 (scope enforcement), DEL-001 through DEL-004 (delegation chain), AUDIT-001 through AUDIT-002 (immutable audit log), GOV-001 through GOV-002 (lifecycle governance), INTER-001 (agent card), COMP-001 (compliance report)
|
||||
- [ ] 18.2 Add `"test:agntcy": "jest --testPathPattern=tests/agntcy --forceExit"` script to `package.json`
|
||||
- [ ] 18.3 Write `docs/agntcy/certification-guide.md` — complete document with all 6 sections: Overview, Requirement Mapping table, Running the Compliance Report (step-by-step), Agent Card Usage, Self-Certification Checklist, Submitting for Official AGNTCY Certification; no placeholders, no TODOs
|
||||
|
||||
## 19. QA & Release
|
||||
|
||||
- [ ] 19.1 Run `cargo build` and `cargo clippy -- -D warnings` in `sdk-rust/` — zero warnings; run `cargo test` — all unit tests pass
|
||||
- [ ] 19.2 Run `tsc --noEmit` across API, dashboard, portal, and CLI — zero TypeScript errors
|
||||
- [ ] 19.3 Run full Jest suite (`npm test`) — all unit tests pass, coverage >= 80% across all new services: `DelegationService`, `AnalyticsService`, `ScaffoldService`, `ComplianceService`, `TierRateLimiter`
|
||||
- [ ] 19.4 Run `npm run build` in `portal/` with Elements integration — zero errors; verify `/api-explorer` page renders Elements `<API>` component
|
||||
- [ ] 19.5 Run `npm run build` in `cli/` — zero errors; run `node dist/index.js scaffold --help` — shows correct options; run `node dist/index.js --help` — shows `scaffold` command listed
|
||||
- [ ] 19.6 Apply database migrations `008_add_delegation_chains.sql` and `009_add_analytics_aggregates.sql` against a test database — verify migrations run without errors and tables are created with correct schemas
|
||||
- [ ] 19.7 Run integration tests for all Phase 5 endpoints — delegation (create, verify, revoke), analytics (usage-summary, agent-activity, token-trends), tiers (GET /tiers, POST /billing/upgrade), scaffold (all 5 languages), AGNTCY (compliance-report, agent-card)
|
||||
- [ ] 19.8 Run `npm run test:agntcy` — all 25+ interoperability test cases pass
|
||||
- [ ] 19.9 Verify feature flags: `A2A_ENABLED=false` → delegation routes return 404; `ANALYTICS_ENABLED=false` → analytics routes return 404; `TIER_RATE_LIMITING_ENABLED=false` → flat rate limiter used; `AGNTCY_ENABLED=false` → AGNTCY routes return 404
|
||||
- [ ] 19.10 Verify tier rate limiting: free tenant receives 429 at 61st request/minute; pro tenant allows 600 requests/minute; tier cache refresh within 60s after Stripe webhook updates subscription
|
||||
- [ ] 19.11 Verify scaffold security: `GET /sdk/scaffold/:agentId` response ZIP never contains a real `client_secret` value — `.env.example` placeholder only
|
||||
- [ ] 19.12 Commit all Phase 5 work on `main` — one conventional commit per workstream (e.g., `feat(phase-5): WS1 — Rust SDK`, `feat(phase-5): WS2 — A2A Authorization`, etc.)
|
||||
- [ ] 11.1 Run `cargo build` and `cargo clippy -- -D warnings` in `sdk-rust/` — zero warnings; run `cargo test` — all unit tests pass
|
||||
- [ ] 11.2 Run `tsc --noEmit` across API, portal, and CLI — zero TypeScript errors
|
||||
- [ ] 11.3 Run full Jest suite (`npm test`) — all unit tests pass, coverage >= 80% across all new services: `DelegationService`, `ScaffoldService`
|
||||
- [ ] 11.4 Run `npm run build` in `portal/` with Elements integration — zero errors; verify `/api-explorer` page renders Elements `<API>` component
|
||||
- [ ] 11.5 Run `npm run build` in `cli/` — zero errors; run `node dist/index.js scaffold --help` — shows correct options; run `node dist/index.js --help` — shows `scaffold` command listed
|
||||
- [ ] 11.6 Apply database migration `008_add_delegation_chains.sql` against a test database — verify migration runs without errors and table is created with correct schema
|
||||
- [ ] 11.7 Run integration tests for all Phase 5 endpoints — delegation (create, verify, revoke), scaffold (all 5 languages)
|
||||
- [ ] 11.8 Verify feature flag: `A2A_ENABLED=false` → delegation routes return 404
|
||||
- [ ] 11.9 Verify scaffold security: `GET /sdk/scaffold/:agentId` response ZIP never contains a real `client_secret` value — `.env.example` placeholder only
|
||||
- [ ] 11.10 Commit all Phase 5 work on `main` — one conventional commit per workstream: `feat(phase-5): WS1 — Rust SDK`, `feat(phase-5): WS2 — A2A Authorization`, `feat(phase-5): WS5 — Developer Experience`
|
||||
|
||||
Reference in New Issue
Block a user