import type { FastifyInstance } from 'fastify'; import type { Logger } from 'pino'; import type { AgentConfig, CertTarget, SecretTarget } from '../lib/config.js'; import type { ChildProcessState } from '../services/child-process-manager.js'; /** * Plugin metadata and lifecycle hooks */ export interface AgentPlugin { /** Unique plugin name (e.g., 'payara', 'kubernetes') */ name: string; /** Semver version */ version: string; /** Optional description */ description?: string; /** * Called once when plugin is loaded, before daemon starts. * Use for initialization, validation, setting up state. */ onInit?(ctx: PluginContext): Promise; /** * Called when daemon is starting, after WebSocket is connected. * Use for startup tasks like checking external service health. */ onStart?(ctx: PluginContext): Promise; /** * Called when daemon is shutting down. * Use for cleanup, closing connections, etc. */ onStop?(ctx: PluginContext): Promise; /** * Register HTTP routes on the health server (port 9100). * Use for custom endpoints like /deploy, /status, etc. * Routes will be registered under /plugins// */ routes?(fastify: FastifyInstance, ctx: PluginContext): Promise; /** * React to certificate deployment events. * Called AFTER successful deployment. */ onCertificateDeployed?(event: CertificateDeployedEvent, ctx: PluginContext): Promise; /** * React to secret deployment events. * Called AFTER successful deployment. */ onSecretDeployed?(event: SecretDeployedEvent, ctx: PluginContext): Promise; /** * React to API key rotation events. * Called AFTER key is rotated and config updated. */ onKeyRotated?(event: KeyRotatedEvent, ctx: PluginContext): Promise; /** * React to child process lifecycle events (exec mode). */ onChildProcessEvent?(event: ChildProcessEvent, ctx: PluginContext): Promise; /** * React to secret change events (via WebSocket subscription). * Called when a watched secret is updated in the vault. */ onSecretChanged?(event: SecretChangedEvent, ctx: PluginContext): Promise; /** * Contribute to health check response. * Return status object that will be merged into /health response. */ healthCheck?(ctx: PluginContext): Promise; } /** * Factory function signature for configurable plugins */ export type PluginFactory> = (config: TConfig) => AgentPlugin; /** * Plugin auto-update configuration */ export interface PluginAutoUpdateConfig { /** Enable auto-update for this plugin (default: inherits from agent config) */ enabled?: boolean; /** Release channel: 'latest', 'beta', 'next' (default: 'latest') */ channel?: 'latest' | 'beta' | 'next'; } /** * Plugin configuration in agent config.json */ export interface PluginConfig { /** npm package name (e.g., '@zincapp/znvault-plugin-payara') */ package?: string; /** Local file path (alternative to package) */ path?: string; /** Plugin-specific configuration passed to factory */ config?: Record; /** Enable/disable plugin (default: true) */ enabled?: boolean; /** Auto-update settings for this plugin */ autoUpdate?: PluginAutoUpdateConfig; } /** * Plugin version info for update checking */ export interface PluginVersionInfo { /** Plugin package name */ package: string; /** Currently installed version */ current: string; /** Latest available version */ latest: string; /** Whether an update is available */ updateAvailable: boolean; } /** * Context provided to plugins - safe access to agent internals */ export interface PluginContext { /** Pino logger scoped to plugin name */ logger: Logger; /** Agent configuration (read-only snapshot) */ config: Readonly; /** Vault URL */ vaultUrl: string; /** Current tenant ID (may be undefined in config-from-vault mode before config fetch) */ tenantId: string | undefined; /** * Fetch a secret from vault by alias or ID. * Returns decrypted value. */ getSecret(aliasOrId: string): Promise; /** * Get certificate content by ID or name. */ getCertificate(certIdOrName: string): Promise; /** * Get configured certificate targets */ getCertTargets(): CertTarget[]; /** * Get configured secret targets */ getSecretTargets(): SecretTarget[]; /** * Request child process restart (exec mode only). * No-op if not in exec mode. * @param reason Human-readable reason for restart */ restartChild(reason: string): Promise; /** * Get current child process state (exec mode only). * Returns null if not in exec mode. */ getChildState(): ChildProcessState | null; /** * Emit custom event to other plugins. * @param event Event name * @param data Event payload */ emit(event: string, data: unknown): void; /** * Listen for custom events from other plugins. * @param event Event name * @param handler Event handler */ on(event: string, handler: (data: unknown) => void): void; /** * Remove event listener * @param event Event name * @param handler Handler to remove */ off(event: string, handler: (data: unknown) => void): void; /** * Plugin-specific persistent storage (JSON file in config dir). */ storage: PluginStorage; } /** * Secret value returned by getSecret */ export interface SecretValue { /** Secret ID */ id: string; /** Secret alias (if any) */ alias?: string; /** Decrypted secret data */ data: Record; /** Secret version */ version: number; /** Secret type */ type: string; } /** * Certificate content returned by getCertificate */ export interface CertificateContent { /** Certificate ID */ id: string; /** Certificate name */ name: string; /** PEM-encoded certificate */ certificate: string; /** PEM-encoded private key */ privateKey: string; /** PEM-encoded CA chain */ chain?: string; /** Full chain (cert + chain) */ fullchain?: string; /** Certificate fingerprint (SHA-256) */ fingerprint: string; /** Expiration date */ expiresAt: string; /** Subject common name */ commonName: string; /** Subject alternative names */ subjectAltNames?: string[]; } /** * Simple key-value storage for plugins */ export interface PluginStorage { /** * Get a value from storage * @param key Storage key * @returns Value or undefined if not found */ get(key: string): T | undefined; /** * Set a value in storage * @param key Storage key * @param value Value to store (must be JSON-serializable) */ set(key: string, value: T): void; /** * Delete a value from storage * @param key Storage key */ delete(key: string): void; /** * Clear all storage for this plugin */ clear(): void; /** * Check if a key exists * @param key Storage key */ has(key: string): boolean; /** * Get all keys */ keys(): string[]; } /** * Emitted after a certificate is successfully deployed to disk */ export interface CertificateDeployedEvent { /** Certificate ID */ certId: string; /** Certificate name */ name: string; /** Output paths where certificate components were written */ paths: { /** Combined cert+key path (for HAProxy) */ combined?: string; /** Certificate-only path */ cert?: string; /** Private key path */ key?: string; /** CA chain path */ chain?: string; /** Full chain path (cert + chain) */ fullchain?: string; }; /** Certificate fingerprint (SHA-256) */ fingerprint: string; /** Expiration date (ISO timestamp) */ expiresAt: string; /** Common name from certificate */ commonName: string; /** Whether this was an update (true) or initial sync (false) */ isUpdate: boolean; } /** * Emitted after a secret is successfully deployed to disk */ export interface SecretDeployedEvent { /** Secret ID */ secretId: string; /** Secret alias */ alias?: string; /** Secret name (from target config) */ name: string; /** Output file path (undefined for subscribe-only 'none' format) */ path?: string; /** Output format used */ format: 'env' | 'json' | 'yaml' | 'raw' | 'template' | 'none'; /** Secret version */ version: number; /** Whether this was an update (true) or initial sync (false) */ isUpdate: boolean; } /** * Emitted after managed API key is rotated */ export interface KeyRotatedEvent { /** Managed key name */ keyName: string; /** New key prefix (first 10 chars + ...) for logging */ newPrefix: string; /** When grace period expires (ISO timestamp) */ graceExpiresAt?: string; /** Next rotation time (ISO timestamp) */ nextRotationAt?: string; /** Rotation mode */ rotationMode: 'scheduled' | 'on-use' | 'on-bind'; } /** * Emitted on child process lifecycle events (exec mode) */ export interface ChildProcessEvent { /** Event type */ type: 'started' | 'stopped' | 'restarting' | 'crashed' | 'max_restarts'; /** Process ID (for 'started') */ pid?: number; /** Exit code (for 'stopped', 'crashed') */ exitCode?: number; /** Signal that killed process (for 'stopped', 'crashed') */ signal?: string; /** Reason for restart (for 'restarting') */ reason?: string; /** Restart count (for 'max_restarts') */ restartCount?: number; } /** * Emitted when a watched secret is changed in the vault */ export interface SecretChangedEvent { /** Secret ID */ secretId: string; /** Secret alias */ alias: string; /** New secret version */ version: number; /** Whether this was a value update (true) or metadata only (false) */ valueChanged: boolean; /** Timestamp of change */ changedAt: string; } /** * Plugin health status for /health endpoint */ export interface PluginHealthStatus { /** Plugin name */ name: string; /** Health status */ status: 'healthy' | 'degraded' | 'unhealthy'; /** Human-readable message */ message?: string; /** Additional details */ details?: Record; } /** * Loaded plugin state (internal) */ export interface LoadedPlugin { /** Plugin instance */ plugin: AgentPlugin; /** Plugin configuration */ config?: Record; /** Plugin status */ status: 'loaded' | 'initialized' | 'running' | 'stopped' | 'error'; /** Error if status is 'error' */ error?: Error; } /** * Plugin event type mapping for dispatcher */ export interface PluginEventMap { certificateDeployed: CertificateDeployedEvent; secretDeployed: SecretDeployedEvent; keyRotated: KeyRotatedEvent; childProcess: ChildProcessEvent; secretChanged: SecretChangedEvent; } /** * Plugin event handler names */ export declare const PLUGIN_EVENT_HANDLERS: { readonly certificateDeployed: "onCertificateDeployed"; readonly secretDeployed: "onSecretDeployed"; readonly keyRotated: "onKeyRotated"; readonly childProcess: "onChildProcessEvent"; readonly secretChanged: "onSecretChanged"; }; //# sourceMappingURL=types.d.ts.map