import { ManifestV3 } from '@kb-labs/plugin-contracts'; /** * @module @kb-labs/core-discovery/types * Core types for marketplace-based entity discovery. */ interface EntitySignature { /** Signing algorithm (e.g., 'ed25519', 'sha256-rsa') */ algorithm: string; /** Base64-encoded signature bytes */ value: string; /** Identity of the signer (e.g., 'kb-labs-platform') */ signer: string; /** ISO timestamp of when the signature was created */ signedAt: string; /** List of checks the entity passed (e.g., ['integrity', 'types', 'lint', 'tests']) */ verifiedChecks: string[]; } type EntityKind = 'plugin' | 'adapter' | 'cli-command' | 'rest-route' | 'ws-channel' | 'workflow' | 'webhook' | 'job' | 'cron' | 'studio-widget' | 'studio-menu' | 'studio-layout' | 'skill' | 'hook' | (string & {}); interface MarketplaceLock { schema: 'kb.marketplace/2'; installed: Record; } interface MarketplaceEntry { /** Installed version (semver) */ version: string; /** SRI integrity hash (sha256-...) */ integrity: string; /** Resolved path to the package root (e.g., ./node_modules/@scope/pkg) */ resolvedPath: string; /** ISO timestamp of installation */ installedAt: string; /** How this package was installed */ source: 'marketplace' | 'local'; /** * Trust level: 'trusted' = signed by KB Labs Registry (sealed, no self-upgrade). * 'untrusted' = installed from npm/local/workspace. Default: 'untrusted'. */ trust?: 'trusted' | 'untrusted'; /** Platform-issued signature (optional, for verified packages) */ signature?: EntitySignature; /** Primary entity kind — discriminator for filtering (e.g., 'plugin', 'adapter') */ primaryKind: EntityKind; /** All entity kinds this package provides (extracted from manifest) */ provides: EntityKind[]; /** Whether the entity is active (default: true) */ enabled?: boolean; /** * Canonical install spec (e.g. 'kb:handle/name', '@scope/pkg@version'). * Optional, populated when the source preserves the original spec form. */ spec?: string; } interface DiscoveredPlugin { /** Plugin identifier (@scope/name) */ id: string; /** Plugin version (semver) */ version: string; /** Path to the package root */ packageRoot: string; /** How this plugin was installed */ source: { kind: 'marketplace' | 'local'; path: string; }; /** Display metadata */ display?: { name?: string; description?: string; }; /** SRI integrity from marketplace.lock */ integrity?: string; /** Platform signature from marketplace.lock */ signature?: EntitySignature; /** Entity kinds extracted from manifest */ provides: EntityKind[]; } interface DiscoveryResult { /** Successfully discovered plugins */ plugins: DiscoveredPlugin[]; /** Loaded manifests keyed by plugin ID */ manifests: Map; /** Diagnostic events from the discovery process */ diagnostics: DiagnosticEvent[]; } type DiagnosticSeverity = 'error' | 'warning' | 'info' | 'debug'; interface DiagnosticEvent { /** Severity level */ severity: DiagnosticSeverity; /** Machine-readable code for programmatic handling */ code: DiagnosticCode; /** Human-readable description of the issue */ message: string; /** Contextual information about the affected entity */ context?: { pluginId?: string; entityKind?: EntityKind; entityId?: string; filePath?: string; }; /** Unix timestamp of when the event occurred */ ts: number; /** Error stack trace (for errors) */ stack?: string; /** Suggested fix for the issue */ remediation?: string; } type DiagnosticCode = 'LOCK_NOT_FOUND' | 'LOCK_PARSE_ERROR' | 'LOCK_SCHEMA_INVALID' | 'MANIFEST_NOT_FOUND' | 'MANIFEST_PARSE_ERROR' | 'MANIFEST_VALIDATION_ERROR' | 'MANIFEST_LOAD_TIMEOUT' | 'INTEGRITY_MISMATCH' | 'SIGNATURE_INVALID' | 'SIGNATURE_MISSING' | 'DEPENDENCY_MISSING' | 'ENTITY_CONFLICT' | 'PLUGIN_DISABLED' | 'PACKAGE_NOT_FOUND' | (string & {}); /** * @module @kb-labs/core-discovery/discovery-manager * Marketplace-based discovery: reads .kb/marketplace.lock, loads & validates manifests. */ interface DiscoveryOptions { /** Workspace root directory (default: process.cwd()) */ root?: string; /** * Platform installation root (e.g. ~/kb-platform). * When set and different from root, both lock files are read: * project lock wins, platform lock fills gaps. */ platformRoot?: string; /** Timeout for each manifest import in milliseconds (default: 5000) */ importTimeoutMs?: number; /** Whether to verify integrity hashes (default: true) */ verifyIntegrity?: boolean; } /** * Discovers installed entities by reading the marketplace lock file * and loading manifests from the resolved paths. * * There is no filesystem scanning — every entity must be registered * in .kb/marketplace.lock via `kb marketplace install` or `kb marketplace link`. */ declare class DiscoveryManager { private readonly root; private readonly platformRoot; private readonly importTimeoutMs; private readonly verifyIntegrity; constructor(opts?: DiscoveryOptions); /** * Run full discovery pipeline. * * When platformRoot is set, both lock files are merged: * project lock (this.root) is read first and wins on conflicts. * Platform lock fills in any entries not present in the project. * * 1. Read .kb/marketplace.lock (project first, then platform) * 2. For each entry → resolve path → load manifest → validate → verify integrity * 3. Return aggregated result with diagnostics */ discover(): Promise; /** * Read and merge marketplace.lock from project root and (optionally) platform root. * Returns a map of packageId → { entry, root } where root is the directory * the entry's resolvedPath should be resolved against. * Project entries win over platform entries on conflict. */ private readMergedLock; private processEntry; /** * Verify the SRI integrity hash of a package by hashing its package.json. */ private checkIntegrity; } /** * Extract which entity kinds a manifest provides by inspecting its sections. */ declare function extractEntityKinds(manifest: ManifestV3): EntityKind[]; /** * @module @kb-labs/core-discovery/diagnostics * Structured diagnostic collector for the discovery pipeline. */ /** * Collects diagnostic events during discovery. * Passed through the pipeline so every step can report issues. */ declare class DiagnosticCollector { private readonly events; /** Record a diagnostic event */ add(severity: DiagnosticSeverity, code: DiagnosticCode, message: string, opts?: { pluginId?: string; entityKind?: EntityKind; entityId?: string; filePath?: string; stack?: string; remediation?: string; }): void; error(code: DiagnosticCode, message: string, opts?: Parameters[3]): void; warning(code: DiagnosticCode, message: string, opts?: Parameters[3]): void; info(code: DiagnosticCode, message: string, opts?: Parameters[3]): void; debug(code: DiagnosticCode, message: string, opts?: Parameters[3]): void; /** Return all collected events (immutable copy) */ getEvents(): DiagnosticEvent[]; /** Check if any errors were collected */ hasErrors(): boolean; /** Count events by severity */ countBySeverity(): Record; } /** * @module @kb-labs/core-discovery/marketplace-lock * Read / write / validate .kb/marketplace.lock */ /** * Load the marketplace lock file from the given workspace root. * Returns null if the file does not exist or is invalid. */ declare function readMarketplaceLock(root: string, diag: DiagnosticCollector): Promise; /** * Write the marketplace lock file atomically (tmp → rename). */ declare function writeMarketplaceLock(root: string, lock: MarketplaceLock): Promise; /** * Add or update an entry in the marketplace lock. * Preserves the existing `enabled` flag when the entry already exists — * re-installing a disabled package must not silently re-enable it. */ declare function addToMarketplaceLock(root: string, packageId: string, entry: MarketplaceEntry): Promise; /** * Remove an entry from the marketplace lock. * Returns true if the entry existed and was removed. */ declare function removeFromMarketplaceLock(root: string, packageId: string): Promise; /** Create an empty marketplace lock */ declare function createEmptyLock(): MarketplaceLock; /** Create a marketplace entry */ declare function createMarketplaceEntry(opts: { version: string; integrity: string; resolvedPath: string; source: 'marketplace' | 'local'; primaryKind: EntityKind; provides: EntityKind[]; signature?: EntitySignature; trust?: 'trusted' | 'untrusted'; spec?: string; }): MarketplaceEntry; /** * Mark a plugin as enabled in the marketplace lock. * Returns false if the package is not installed. */ declare function enablePlugin(root: string, packageId: string): Promise; /** * Mark a plugin as disabled in the marketplace lock. * Returns false if the package is not installed. */ declare function disablePlugin(root: string, packageId: string): Promise; /** * @module @kb-labs/core-discovery/manifest-loader * Safe dynamic import of plugin manifests with timeout protection. */ /** * Attempt to locate and load a ManifestV3 from a package root directory. * * Resolution order: * 1. package.json `kbLabs.manifest` or `kb.manifest` field (relative path) * 2. `kb.plugin.json` in package root * 3. Manifest exported from package entry point (`dist/index.js`) */ declare function loadManifest(packageRoot: string, diag: DiagnosticCollector, timeoutMs?: number): Promise; /** * @module @kb-labs/core-discovery/integrity * SRI integrity computation and parsing for marketplace packages. * * Packages are identified by a hash of their package.json (not the full tarball). * This keeps verification fast and stable across tarball recompression. */ /** * Compute the SRI integrity string for an arbitrary file. * * Format: `sha256-` (SubResource Integrity convention). * Throws if the file cannot be read. */ declare function computeFileIntegrity(filePath: string): Promise; /** * Compute the SRI integrity string for a package by hashing its package.json. * Kept for backwards compatibility — delegates to computeFileIntegrity. */ declare function computePackageIntegrity(pkgRoot: string): Promise; /** * Compute the SRI integrity string for a manifest file (e.g. dist/index.js). * Used by CLI discovery to detect when a plugin was rebuilt. */ declare function computeManifestIntegrity(manifestPath: string): Promise; /** * Parse an SRI integrity string (e.g. `sha256-`) into its components. * Returns `null` when the value is malformed. */ declare function parseIntegrity(value: string): { algorithm: string; hash: string; } | null; export { type DiagnosticCode, DiagnosticCollector, type DiagnosticEvent, type DiagnosticSeverity, type DiscoveredPlugin, DiscoveryManager, type DiscoveryOptions, type DiscoveryResult, type EntityKind, type EntitySignature, type MarketplaceEntry, type MarketplaceLock, addToMarketplaceLock, computeFileIntegrity, computeManifestIntegrity, computePackageIntegrity, createEmptyLock, createMarketplaceEntry, disablePlugin, enablePlugin, extractEntityKinds, loadManifest, parseIntegrity, readMarketplaceLock, removeFromMarketplaceLock, writeMarketplaceLock };