1- " use strict" ;
1+ ' use strict' ;
22
3- const fs = require ( "fs" ) ;
4- const path = require ( " path" ) ;
5- const Ajv = require ( " ajv" ) ;
3+ const fs = require ( 'fs' ) ;
4+ const path = require ( ' path' ) ;
5+ const Ajv = require ( ' ajv' ) ;
66const {
77 createPluginVerifier,
8- } = require ( " ../security/plugin-signature-verifier.js" ) ;
8+ } = require ( ' ../security/plugin-signature-verifier.js' ) ;
99
1010class PluginRegistry {
1111 constructor ( options = { } ) {
1212 this . _plugins = new Map ( ) ;
1313 this . _validTypes = new Set ( [
14- " loader" ,
15- " embedder" ,
16- " retriever" ,
17- " reranker" ,
18- " llm" ,
19- " evaluator" ,
14+ ' loader' ,
15+ ' embedder' ,
16+ ' retriever' ,
17+ ' reranker' ,
18+ ' llm' ,
19+ ' evaluator' ,
2020 ] ) ;
2121 this . _contracts = new Map ( ) ;
2222 this . _contractWarningsShown = new Set ( ) ; // Track warnings to show only once per type
@@ -43,7 +43,7 @@ class PluginRegistry {
4343 this . _contractSchemaValidator = this . _ajv . compile ( this . _contractSchema ) ;
4444 } catch ( error ) {
4545 if (
46- process . env . NODE_ENV !== " production" &&
46+ process . env . NODE_ENV !== ' production' &&
4747 ! this . _disableContractWarnings
4848 ) {
4949 console . warn (
@@ -55,8 +55,8 @@ class PluginRegistry {
5555 }
5656
5757 // Environment-aware signature verification defaults
58- const isDevelopment = process . env . NODE_ENV === " development" ;
59- const isProduction = process . env . NODE_ENV === " production" ;
58+ const isDevelopment = process . env . NODE_ENV === ' development' ;
59+ const isProduction = process . env . NODE_ENV === ' production' ;
6060
6161 this . _signatureVerifier = createPluginVerifier ( {
6262 enabled :
@@ -82,15 +82,15 @@ class PluginRegistry {
8282 try {
8383 const schemaPath = path . join (
8484 __dirname ,
85- " ../../contracts/contract-schema.json" ,
85+ ' ../../contracts/contract-schema.json' ,
8686 ) ;
8787 if ( fs . existsSync ( schemaPath ) ) {
88- const schemaContent = fs . readFileSync ( schemaPath , " utf8" ) ;
88+ const schemaContent = fs . readFileSync ( schemaPath , ' utf8' ) ;
8989 return JSON . parse ( schemaContent ) ;
9090 }
9191 } catch ( error ) {
9292 if (
93- process . env . NODE_ENV !== " production" &&
93+ process . env . NODE_ENV !== ' production' &&
9494 ! this . _disableContractWarnings
9595 ) {
9696 console . warn (
@@ -150,24 +150,24 @@ class PluginRegistry {
150150 */
151151 _formatSchemaErrors ( errors ) {
152152 if ( ! errors || errors . length === 0 ) {
153- return " Unknown schema validation error" ;
153+ return ' Unknown schema validation error' ;
154154 }
155155
156156 const messages = errors . map ( ( err ) => {
157- const path = err . instancePath || err . dataPath || "/" ;
158- const message = err . message || " validation failed" ;
157+ const path = err . instancePath || err . dataPath || '/' ;
158+ const message = err . message || ' validation failed' ;
159159
160160 if ( err . params ) {
161161 const params = Object . entries ( err . params )
162162 . map ( ( [ key , value ] ) => `${ key } =${ JSON . stringify ( value ) } ` )
163- . join ( ", " ) ;
163+ . join ( ', ' ) ;
164164 return ` - ${ path } : ${ message } (${ params } )` ;
165165 }
166166
167167 return ` - ${ path } : ${ message } ` ;
168168 } ) ;
169169
170- return messages . join ( "\n" ) ;
170+ return messages . join ( '\n' ) ;
171171 }
172172
173173 /**
@@ -201,11 +201,11 @@ class PluginRegistry {
201201 *
202202 * @since 2.2.4
203203 */
204- _warnMissingContract ( type , context = " load" ) {
204+ _warnMissingContract ( type , context = ' load' ) {
205205 // Skip if warnings disabled or in production
206206 if (
207207 this . _disableContractWarnings ||
208- process . env . NODE_ENV === " production"
208+ process . env . NODE_ENV === ' production'
209209 ) {
210210 return ;
211211 }
@@ -255,22 +255,22 @@ class PluginRegistry {
255255 }
256256
257257 _loadContracts ( ) {
258- const contractsDir = path . join ( __dirname , " ../../contracts" ) ;
258+ const contractsDir = path . join ( __dirname , ' ../../contracts' ) ;
259259
260260 try {
261261 const contractFiles = {
262- loader : " loader-contract.json" ,
263- embedder : " embedder-contract.json" ,
264- retriever : " retriever-contract.json" ,
265- llm : " llm-contract.json" ,
266- reranker : " reranker-contract.json" ,
262+ loader : ' loader-contract.json' ,
263+ embedder : ' embedder-contract.json' ,
264+ retriever : ' retriever-contract.json' ,
265+ llm : ' llm-contract.json' ,
266+ reranker : ' reranker-contract.json' ,
267267 } ;
268268
269269 for ( const [ type , filename ] of Object . entries ( contractFiles ) ) {
270270 try {
271271 const contractPath = path . join ( contractsDir , filename ) ;
272272 if ( fs . existsSync ( contractPath ) ) {
273- const contractContent = fs . readFileSync ( contractPath , " utf8" ) ;
273+ const contractContent = fs . readFileSync ( contractPath , ' utf8' ) ;
274274 const contract = JSON . parse ( contractContent ) ;
275275
276276 // Validate contract against schema
@@ -287,7 +287,7 @@ class PluginRegistry {
287287 error . validationErrors = validation . errors ;
288288 error . contractType = type ;
289289
290- if ( process . env . NODE_ENV === " production" ) {
290+ if ( process . env . NODE_ENV === ' production' ) {
291291 // In production, log error but continue (fail open)
292292 console . error ( `[PLUGIN_REGISTRY] ERROR: ${ error . message } ` ) ; // eslint-disable-line no-console
293293 } else {
@@ -299,17 +299,17 @@ class PluginRegistry {
299299 this . _contracts . set ( type , contract ) ;
300300 } else {
301301 // Use new warning method for missing contracts
302- this . _warnMissingContract ( type , " load" ) ;
302+ this . _warnMissingContract ( type , ' load' ) ;
303303 }
304304 } catch ( error ) {
305305 // Re-throw validation errors in development mode
306- if ( error . validationErrors && process . env . NODE_ENV !== " production" ) {
306+ if ( error . validationErrors && process . env . NODE_ENV !== ' production' ) {
307307 throw error ;
308308 }
309309
310310 // Contract loading is optional - don't fail if missing
311311 if (
312- process . env . NODE_ENV !== " production" &&
312+ process . env . NODE_ENV !== ' production' &&
313313 ! this . _disableContractWarnings
314314 ) {
315315 console . warn (
@@ -320,13 +320,13 @@ class PluginRegistry {
320320 }
321321 } catch ( error ) {
322322 // Re-throw validation errors in development mode
323- if ( error . validationErrors && process . env . NODE_ENV !== " production" ) {
323+ if ( error . validationErrors && process . env . NODE_ENV !== ' production' ) {
324324 throw error ;
325325 }
326326
327327 // Contracts directory may not exist in all environments
328328 if (
329- process . env . NODE_ENV !== " production" &&
329+ process . env . NODE_ENV !== ' production' &&
330330 ! this . _disableContractWarnings
331331 ) {
332332 console . warn (
@@ -340,21 +340,21 @@ class PluginRegistry {
340340 const contract = this . _contracts . get ( category ) ;
341341 if ( ! contract ) {
342342 // Use new warning method when registering a plugin without a contract
343- this . _warnMissingContract ( category , " register" ) ;
343+ this . _warnMissingContract ( category , ' register' ) ;
344344 return ; // No contract to validate against
345345 }
346346
347347 // Check if plugin has metadata
348348 if ( ! impl . metadata ) {
349- throw new Error ( " Plugin missing metadata property" ) ;
349+ throw new Error ( ' Plugin missing metadata property' ) ;
350350 }
351351
352- if ( ! impl . metadata . name || typeof impl . metadata . name !== " string" ) {
353- throw new Error ( " Plugin metadata must have a name property" ) ;
352+ if ( ! impl . metadata . name || typeof impl . metadata . name !== ' string' ) {
353+ throw new Error ( ' Plugin metadata must have a name property' ) ;
354354 }
355355
356- if ( ! impl . metadata . version || typeof impl . metadata . version !== " string" ) {
357- throw new Error ( " Plugin metadata must have a version property" ) ;
356+ if ( ! impl . metadata . version || typeof impl . metadata . version !== ' string' ) {
357+ throw new Error ( ' Plugin metadata must have a version property' ) ;
358358 }
359359
360360 if ( ! impl . metadata . type || impl . metadata . type !== category ) {
@@ -369,7 +369,7 @@ class PluginRegistry {
369369 throw new Error ( `Plugin missing required method: ${ methodName } ` ) ;
370370 }
371371
372- if ( typeof impl [ methodName ] !== " function" ) {
372+ if ( typeof impl [ methodName ] !== ' function' ) {
373373 throw new Error ( `Plugin method '${ methodName } ' must be a function` ) ;
374374 }
375375 }
@@ -386,7 +386,7 @@ class PluginRegistry {
386386 for ( const [ methodName , methodSpec ] of Object . entries (
387387 contract . properties ,
388388 ) ) {
389- if ( methodSpec . type === " function" ) {
389+ if ( methodSpec . type === ' function' ) {
390390 methods . push ( methodName ) ;
391391 }
392392 }
@@ -396,14 +396,14 @@ class PluginRegistry {
396396 }
397397
398398 async register ( category , name , impl , manifest = null ) {
399- if ( ! category || typeof category !== " string" ) {
400- throw new Error ( " Category must be a non-empty string" ) ;
399+ if ( ! category || typeof category !== ' string' ) {
400+ throw new Error ( ' Category must be a non-empty string' ) ;
401401 }
402- if ( ! name || typeof name !== " string" ) {
403- throw new Error ( " Name must be a non-empty string" ) ;
402+ if ( ! name || typeof name !== ' string' ) {
403+ throw new Error ( ' Name must be a non-empty string' ) ;
404404 }
405405 if ( impl == null ) {
406- throw new Error ( " Implementation cannot be null or undefined" ) ;
406+ throw new Error ( ' Implementation cannot be null or undefined' ) ;
407407 }
408408 if ( ! this . _validTypes . has ( category ) ) {
409409 throw new Error ( `Unknown plugin type: ${ category } ` ) ;
@@ -450,7 +450,7 @@ class PluginRegistry {
450450 }
451451
452452 // Emit audit entry for successful verification
453- this . _emitAuditEntry ( " plugin_verified" , {
453+ this . _emitAuditEntry ( ' plugin_verified' , {
454454 pluginName,
455455 signerId : manifest . signerId ,
456456 version : manifest . version ,
@@ -459,10 +459,10 @@ class PluginRegistry {
459459 } ) ;
460460 } catch ( error ) {
461461 // Emit audit entry for failed verification
462- this . _emitAuditEntry ( " plugin_verification_failed" , {
462+ this . _emitAuditEntry ( ' plugin_verification_failed' , {
463463 pluginName,
464- signerId : manifest . signerId || " unknown" ,
465- version : manifest . version || " unknown" ,
464+ signerId : manifest . signerId || ' unknown' ,
465+ version : manifest . version || ' unknown' ,
466466 verified : false ,
467467 error : error . message ,
468468 timestamp : new Date ( ) . toISOString ( ) ,
@@ -481,15 +481,15 @@ class PluginRegistry {
481481 const auditEntry = {
482482 timestamp : new Date ( ) . toISOString ( ) ,
483483 action,
484- component : " plugin_registry" ,
484+ component : ' plugin_registry' ,
485485 ...details ,
486486 } ;
487487
488488 // In production, this should go to a secure audit log
489- if ( process . env . NODE_ENV === " production" ) {
490- console . warn ( " [AUDIT]" , JSON . stringify ( auditEntry ) ) ; // eslint-disable-line no-console
489+ if ( process . env . NODE_ENV === ' production' ) {
490+ console . warn ( ' [AUDIT]' , JSON . stringify ( auditEntry ) ) ; // eslint-disable-line no-console
491491 } else {
492- console . log ( " [AUDIT]" , auditEntry ) ; // eslint-disable-line no-console
492+ console . log ( ' [AUDIT]' , auditEntry ) ; // eslint-disable-line no-console
493493 }
494494 }
495495
@@ -530,8 +530,8 @@ class PluginRegistry {
530530
531531// Create singleton instance with default security settings
532532const registry = new PluginRegistry ( {
533- verifySignatures : process . env . NODE_ENV === " production" ,
534- failClosed : process . env . NODE_ENV === " production" ,
533+ verifySignatures : process . env . NODE_ENV === ' production' ,
534+ failClosed : process . env . NODE_ENV === ' production' ,
535535} ) ;
536536
537537// CJS+ESM interop pattern
0 commit comments