feat(phase-4): WS5 — GitHub Actions OIDC token exchange and trust policies

- POST /oidc/token: GitHub OIDC JWT exchange (bootstrap + agent-scoped modes)
- POST/GET/DELETE /oidc/trust-policies: trust policy CRUD with enforcement
- DB migration 022: oidc_trust_policies table with provider/repo/branch/agent_id
- GitHub Actions: register-agent and issue-token actions with full READMEs
- Trust policy enforcement rejects token exchanges not matching registered policies
- Bootstrap mode issues agents:write token for new agent registration without agentId

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SentryAgent.ai Developer
2026-04-02 10:37:39 +00:00
parent 89c99b666d
commit fefbf1e3ea
15 changed files with 1432 additions and 18 deletions

View File

@@ -35,6 +35,8 @@ import { createKafkaProducer } from './adapters/KafkaAdapter.js';
import { AgentController } from './controllers/AgentController.js';
import { MarketplaceController } from './controllers/MarketplaceController.js';
import { OIDCTrustPolicyController } from './controllers/OIDCTrustPolicyController.js';
import { OIDCTokenExchangeController } from './controllers/OIDCTokenExchangeController.js';
import { TokenController } from './controllers/TokenController.js';
import { CredentialController } from './controllers/CredentialController.js';
import { AuditController } from './controllers/AuditController.js';
@@ -47,6 +49,9 @@ import { ComplianceController } from './controllers/ComplianceController.js';
import { createAgentsRouter } from './routes/agents.js';
import { createMarketplaceRouter } from './routes/marketplace.js';
import { createOIDCTrustPoliciesRouter } from './routes/oidcTrustPolicies.js';
import { createOIDCTokenExchangeRouter } from './routes/oidcTokenExchange.js';
import { OIDCTrustPolicyService } from './services/OIDCTrustPolicyService.js';
import { createTokenRouter } from './routes/token.js';
import { createCredentialsRouter } from './routes/credentials.js';
import { createAuditRouter } from './routes/audit.js';
@@ -227,6 +232,11 @@ export async function createApp(): Promise<Application> {
const webhookController = new WebhookController(webhookService);
const marketplaceController = new MarketplaceController(marketplaceService);
// OIDC trust policy management + GitHub Actions token exchange
const oidcTrustPolicyService = new OIDCTrustPolicyService(pool);
const oidcTrustPolicyController = new OIDCTrustPolicyController(oidcTrustPolicyService);
const oidcTokenExchangeController = new OIDCTokenExchangeController(oidcTrustPolicyService, privateKey);
// ────────────────────────────────────────────────────────────────
// Compliance services and background jobs (SOC 2 Type II)
// ────────────────────────────────────────────────────────────────
@@ -277,6 +287,12 @@ export async function createApp(): Promise<Application> {
app.use(`${API_BASE}`, createComplianceRouter(complianceController));
app.use(`${API_BASE}/marketplace`, createMarketplaceRouter(marketplaceController));
// OIDC trust-policy management (authenticated) and token exchange (unauthenticated)
// Both routers mount under ${API_BASE}/oidc — trust-policy routes use /trust-policies prefix,
// token exchange uses /token, so there are no path conflicts.
app.use(`${API_BASE}/oidc`, createOIDCTrustPoliciesRouter(oidcTrustPolicyController, authMiddleware));
app.use(`${API_BASE}/oidc`, createOIDCTokenExchangeRouter(oidcTokenExchangeController));
// ────────────────────────────────────────────────────────────────
// Dashboard static assets (served from dashboard/dist/)
// Placed after API routes so API routes take precedence.