feat(phase-3): workstream 4 — AGNTCY Federation
Implements cross-IdP token verification for the AGNTCY ecosystem: - Migration 015: federation_partners table (issuer, jwks_uri, allowed_organizations JSONB, status, expires_at) - FederationService: registerPartner (JWKS validation at registration), listPartners, getPartner, updatePartner, deletePartner, verifyFederatedToken (alg:none rejected, RS256/ES256 only, allowedOrganizations filter, expiry enforcement) - JWKS caching in Redis (TTL: FEDERATION_JWKS_CACHE_TTL_SECONDS); cache invalidated on partner delete and jwks_uri change - FederationController + routes: 5 admin:orgs endpoints + POST /federation/verify (agents:read) - OPA policy: 5 federation admin endpoint → admin:orgs mappings - 499 unit tests passing; 94.69% statement coverage on FederationService Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
151
src/types/federation.ts
Normal file
151
src/types/federation.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Federation type definitions for SentryAgent.ai AgentIdP.
|
||||
* Covers federation partner management and cross-IdP token verification.
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Federation Partner Status
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Lifecycle status of a federation partner.
|
||||
* - 'active' — partner is trusted; tokens accepted.
|
||||
* - 'suspended' — partner is temporarily disabled; tokens rejected.
|
||||
* - 'expired' — partner's expires_at has passed; tokens rejected.
|
||||
*/
|
||||
export type FederationPartnerStatus = 'active' | 'suspended' | 'expired';
|
||||
|
||||
// ============================================================================
|
||||
// Federation Partner (database row)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Represents a row in the `federation_partners` table.
|
||||
* A federation partner is an external IdP whose tokens this IdP trusts.
|
||||
*/
|
||||
export interface IFederationPartner {
|
||||
/** UUID primary key. */
|
||||
id: string;
|
||||
/** Human-readable partner name. */
|
||||
name: string;
|
||||
/** Issuer URL — must match the `iss` claim in federated tokens. */
|
||||
issuer: string;
|
||||
/** URL of the partner's JWKS endpoint. */
|
||||
jwks_uri: string;
|
||||
/**
|
||||
* Allowlist of organization_id values accepted from this partner.
|
||||
* An empty array means all organizations are accepted.
|
||||
*/
|
||||
allowed_organizations: string[];
|
||||
/** Current lifecycle status. */
|
||||
status: FederationPartnerStatus;
|
||||
/** Timestamp when this partner was registered. */
|
||||
created_at: Date;
|
||||
/** Timestamp of the last update. */
|
||||
updated_at: Date;
|
||||
/** Optional expiry timestamp. NULL means the partner never expires. */
|
||||
expires_at: Date | null;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Request / Response shapes
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Request body for registering a new federation partner.
|
||||
* POST /api/v1/federation/trust
|
||||
*/
|
||||
export interface ICreatePartnerRequest {
|
||||
/** Human-readable partner name. */
|
||||
name: string;
|
||||
/** Issuer URL of the external IdP. */
|
||||
issuer: string;
|
||||
/** URL of the partner's JWKS endpoint (must be reachable at registration time). */
|
||||
jwks_uri: string;
|
||||
/**
|
||||
* Optional allowlist of organization_id values to accept from this partner.
|
||||
* Defaults to empty array (all organizations accepted).
|
||||
*/
|
||||
allowed_organizations?: string[];
|
||||
/** Optional ISO 8601 date-time string after which the partner will be expired. */
|
||||
expires_at?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request body for updating an existing federation partner.
|
||||
* PATCH /api/v1/federation/partners/:id
|
||||
* All fields are optional; only provided fields are updated.
|
||||
*/
|
||||
export interface IUpdatePartnerRequest {
|
||||
/** Updated human-readable partner name. */
|
||||
name?: string;
|
||||
/** Updated JWKS endpoint URL. Cache will be invalidated if this changes. */
|
||||
jwks_uri?: string;
|
||||
/** Updated organization allowlist. */
|
||||
allowed_organizations?: string[];
|
||||
/** Updated lifecycle status. */
|
||||
status?: FederationPartnerStatus;
|
||||
/**
|
||||
* Updated expiry timestamp.
|
||||
* Pass an ISO 8601 string to set a new expiry, or null to clear it.
|
||||
*/
|
||||
expires_at?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request body for verifying a federated token.
|
||||
* POST /api/v1/federation/verify
|
||||
*/
|
||||
export interface IFederationVerifyRequest {
|
||||
/** The JWT token string to verify. */
|
||||
token: string;
|
||||
/**
|
||||
* Optional issuer hint. If provided, the token's `iss` claim must match this value exactly.
|
||||
* Useful to prevent issuer confusion when multiple partners share JWKS.
|
||||
*/
|
||||
expected_issuer?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result returned by a successful federated token verification.
|
||||
*/
|
||||
export interface IFederationVerifyResult {
|
||||
/** Whether the token is valid (true when verification passed). */
|
||||
valid: boolean;
|
||||
/** The issuer (`iss` claim) of the verified token. */
|
||||
issuer: string;
|
||||
/** The subject (`sub` claim) of the verified token. */
|
||||
subject: string;
|
||||
/**
|
||||
* The `organization_id` claim from the token, if present.
|
||||
* Populated when the external IdP includes this standard SentryAgent claim.
|
||||
*/
|
||||
organization_id?: string;
|
||||
/** All claims from the verified token payload. */
|
||||
claims: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decoded claims payload of a federated JWT token.
|
||||
* Matches the standard JWT claims plus optional SentryAgent extensions.
|
||||
* Used internally by FederationService during token verification.
|
||||
*/
|
||||
export interface IFederatedTokenClaims {
|
||||
/** Issuer — identifies the external IdP. */
|
||||
iss: string;
|
||||
/** Subject — identifies the agent in the external IdP. */
|
||||
sub: string;
|
||||
/** Audience — the intended recipient(s) of the token. */
|
||||
aud: string | string[];
|
||||
/** Issued-at time (Unix seconds). */
|
||||
iat: number;
|
||||
/** Expiry time (Unix seconds). */
|
||||
exp: number;
|
||||
/**
|
||||
* Optional organization_id claim.
|
||||
* When present, used to enforce the partner's allowed_organizations filter.
|
||||
*/
|
||||
organization_id?: string;
|
||||
/** Additional claims from the token payload. */
|
||||
[key: string]: unknown;
|
||||
}
|
||||
Reference in New Issue
Block a user