/** * Download Provenance Store * * Records WHERE each downloaded plugin binary came from: channel (source type), * source-specific identifier, version, and the artifact's sha1/sha256 digests. * Written to ~/.pluginator/provenance.json at download time (Phase 2 * identification-engine groundwork — channel provenance: the same release * version is a DIFFERENT binary per channel, so knowing the origin channel of * an installed JAR lets update checks prefer same-channel updates). * * ## LOCAL-ONLY — companion-service submission shape * * This store never leaves the machine. The Phase 7 companion service * (.plans/2026-06-09/02-companion-service-design.md §5) will read these * records — behind an explicit opt-in setting — and map them to the * submission shape `{ sha256, sha1?, channel, projectId, version, * observedVia: 'download' }`. Until that ships, nothing here is transmitted. * * ## PRIVACY (absolute rule) * * Records must contain NOTHING buyer-identifying. SpigotMC/Polymart premium * watermarks embed the BUYER's user id and license keys — watermark-derived * values beyond {channel, resourceId} must never be written to this store, * logged, or persisted anywhere. Only channel/identifier/version/digest data * belongs here. * * ## Design note: sync + swallow is intentional * * Same precedent as NotificationStore (src/core/notifications/ * notification-store.ts): provenance is non-critical bookkeeping recorded on * the download success path. A corrupt or missing provenance.json must never * crash a download or block higher-priority operations — corrupt files load * as an empty store and are overwritten on the next save. * * @since v2.12.4 (roadmap Phase 2, assignment B3) */ /** Bounded history: most recent N download records kept per plugin */ export declare const MAX_HISTORY_PER_PLUGIN = 5; /** * One downloaded artifact's provenance. Contains nothing buyer-identifying * (see module doc privacy rule). */ export interface ProvenanceRecord { /** Consistent plugin name used for tracking (not the API display title) */ pluginName: string; /** Channel the artifact came from — a PluginSourceType value, or 'unknown' */ sourceType: string; /** Source-specific identifier (resource id, project slug, owner/repo, ...); '' when unknown */ identifier: string; /** Channel-reported version string of the downloaded artifact */ version: string; /** sha-256 of the downloaded file (64-char lowercase hex) */ sha256: string; /** sha-1 of the downloaded file (40-char lowercase hex) */ sha1: string; /** URL the artifact was fetched from */ downloadUrl: string; /** ISO 8601 timestamp of when the download completed */ recordedAt: string; } export declare class ProvenanceStore { private data; private storePath; private loaded; constructor(storePath?: string); /** Load records from disk. Corrupt/missing file → empty store, never throws. */ load(): void; /** * Record a completed download and persist. Re-recording the SAME binary * (matching sha256 + version + sourceType as the current latest) replaces * the latest entry instead of flushing distinct versions out of the * bounded history. */ recordDownload(record: ProvenanceRecord): void; /** Latest provenance record for a plugin (case-insensitive), or null */ getProvenance(pluginName: string): ProvenanceRecord | null; /** Bounded download history for a plugin (case-insensitive), newest first */ getHistory(pluginName: string): ProvenanceRecord[]; /** Latest record per plugin */ getAll(): ProvenanceRecord[]; private save; } /** * Get or create the global provenance store. * @param options.storePath Pins the store file on FIRST call (tests use a temp dir) */ export declare function getProvenanceStore(options?: { storePath?: string; }): ProvenanceStore; /** Reset the global provenance store (mainly for testing) */ export declare function resetProvenanceStore(): void; //# sourceMappingURL=provenance-store.d.ts.map