From e95455a9b355e304c969202d01428bf5cf90f6c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 09:49:59 +0000 Subject: [PATCH 1/3] Initial plan From 81f84041648b8dec7335c1948ff2f9a0e7d5ece4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 09:56:14 +0000 Subject: [PATCH 2/3] Fix TypeScript compilation errors in packages/core/src/security/ - Rename PluginConfigValidator interface to IPluginConfigValidator to avoid conflict - Fix import paths in test files (security/ subfolder) - Fix logger.error calls to use correct signature (message, error?, meta?) - Fix globalThis.window checks using type assertions - Add missing 'certified: false' field to all PluginCapability test objects - Add type annotation for ZodIssue in formatZodErrors - Cast configSchema to any for partial() method call Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/core/src/plugin-loader.ts | 5 +++-- .../src/security/plugin-config-validator.test.ts | 6 +++--- .../core/src/security/plugin-config-validator.ts | 7 ++++--- .../security/plugin-permission-enforcer.test.ts | 15 ++++++++++++--- .../src/security/plugin-signature-verifier.ts | 10 +++++----- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/core/src/plugin-loader.ts b/packages/core/src/plugin-loader.ts index 8e402e8f16..f54dc9f440 100644 --- a/packages/core/src/plugin-loader.ts +++ b/packages/core/src/plugin-loader.ts @@ -32,10 +32,11 @@ export interface ServiceRegistration { } /** - * Plugin Configuration Validator + * Plugin Configuration Validator Interface * Uses Zod for runtime validation of plugin configurations + * @deprecated Use the PluginConfigValidator class from security module instead */ -export interface PluginConfigValidator { +export interface IPluginConfigValidator { schema: z.ZodSchema; validate(config: any): any; } diff --git a/packages/core/src/security/plugin-config-validator.test.ts b/packages/core/src/security/plugin-config-validator.test.ts index dc028a15e7..d11f119177 100644 --- a/packages/core/src/security/plugin-config-validator.test.ts +++ b/packages/core/src/security/plugin-config-validator.test.ts @@ -1,8 +1,8 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { z } from 'zod'; -import { PluginConfigValidator } from '../plugin-config-validator.js'; -import { createLogger } from '../../logger.js'; -import type { PluginMetadata } from '../../plugin-loader.js'; +import { PluginConfigValidator } from './plugin-config-validator.js'; +import { createLogger } from '../logger.js'; +import type { PluginMetadata } from '../plugin-loader.js'; describe('PluginConfigValidator', () => { let validator: PluginConfigValidator; diff --git a/packages/core/src/security/plugin-config-validator.ts b/packages/core/src/security/plugin-config-validator.ts index a70e67772f..369fc69667 100644 --- a/packages/core/src/security/plugin-config-validator.ts +++ b/packages/core/src/security/plugin-config-validator.ts @@ -62,7 +62,7 @@ export class PluginConfigValidator { ...formattedErrors.map(e => ` - ${e.path}: ${e.message}`), ].join('\n'); - this.logger.error(errorMessage, { + this.logger.error(errorMessage, undefined, { plugin: plugin.name, errors: formattedErrors, }); @@ -89,7 +89,8 @@ export class PluginConfigValidator { try { // Use Zod's partial() method for partial validation - const partialSchema = plugin.configSchema.partial(); + // Cast to ZodObject to access partial() method + const partialSchema = (plugin.configSchema as any).partial(); const validatedConfig = partialSchema.parse(partialConfig); this.logger.debug(`✅ Partial config validated: ${plugin.name}`); @@ -172,7 +173,7 @@ export class PluginConfigValidator { // Private methods private formatZodErrors(error: z.ZodError): Array<{path: string; message: string}> { - return error.errors.map(e => ({ + return error.errors.map((e: z.ZodIssue) => ({ path: e.path.join('.') || 'root', message: e.message, })); diff --git a/packages/core/src/security/plugin-permission-enforcer.test.ts b/packages/core/src/security/plugin-permission-enforcer.test.ts index 1ab7eaed93..7c5faf5c21 100644 --- a/packages/core/src/security/plugin-permission-enforcer.test.ts +++ b/packages/core/src/security/plugin-permission-enforcer.test.ts @@ -1,8 +1,8 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { PluginPermissionEnforcer, SecurePluginContext } from '../plugin-permission-enforcer.js'; -import { createLogger } from '../../logger.js'; +import { PluginPermissionEnforcer, SecurePluginContext } from './plugin-permission-enforcer.js'; +import { createLogger } from '../logger.js'; import type { PluginCapability } from '@objectstack/spec/system'; -import type { PluginContext } from '../../types.js'; +import type { PluginContext } from '../types.js'; describe('PluginPermissionEnforcer', () => { let enforcer: PluginPermissionEnforcer; @@ -23,6 +23,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -43,6 +44,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -63,6 +65,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -82,6 +85,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -106,6 +110,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -125,6 +130,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -146,6 +152,7 @@ describe('PluginPermissionEnforcer', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -189,6 +196,7 @@ describe('SecurePluginContext', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; @@ -221,6 +229,7 @@ describe('SecurePluginContext', () => { version: { major: 1, minor: 0, patch: 0 }, }, conformance: 'full', + certified: false, }, ]; diff --git a/packages/core/src/security/plugin-signature-verifier.ts b/packages/core/src/security/plugin-signature-verifier.ts index 57212b6470..0766bbf426 100644 --- a/packages/core/src/security/plugin-signature-verifier.ts +++ b/packages/core/src/security/plugin-signature-verifier.ts @@ -3,7 +3,7 @@ import type { PluginMetadata } from '../plugin-loader.js'; // Conditionally import crypto for Node.js environments let cryptoModule: typeof import('crypto') | null = null; -if (typeof window === 'undefined') { +if (typeof (globalThis as any).window === 'undefined') { try { // Dynamic import for Node.js crypto module // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -132,7 +132,7 @@ export class PluginSignatureVerifier { if (!isValid) { const error = `Signature verification failed for plugin: ${plugin.name}`; - this.logger.error(error, { plugin: plugin.name, publisherId }); + this.logger.error(error, undefined, { plugin: plugin.name, publisherId }); throw new Error(error); } @@ -190,7 +190,7 @@ export class PluginSignatureVerifier { private handleUnsignedPlugin(plugin: PluginMetadata): SignatureVerificationResult { if (this.config.strictMode) { const error = `Plugin missing signature (strict mode): ${plugin.name}`; - this.logger.error(error, { plugin: plugin.name }); + this.logger.error(error, undefined, { plugin: plugin.name }); throw new Error(error); } @@ -220,7 +220,7 @@ export class PluginSignatureVerifier { private computePluginHash(plugin: PluginMetadata): string { // In browser environment, use SubtleCrypto - if (typeof window !== 'undefined') { + if (typeof (globalThis as any).window !== 'undefined') { return this.computePluginHashBrowser(plugin); } @@ -287,7 +287,7 @@ export class PluginSignatureVerifier { publicKey: string ): Promise { // In browser environment, use SubtleCrypto - if (typeof window !== 'undefined') { + if (typeof (globalThis as any).window !== 'undefined') { return this.verifyCryptoSignatureBrowser(data, signature, publicKey); } From f99abfd0e2077d4f254cf90ef901bc8aac39a0dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:00:16 +0000 Subject: [PATCH 3/3] Fix remaining TypeScript errors: use issues instead of errors, change silent to error log level - Fix ZodError.errors to ZodError.issues for Zod 4.x compatibility - Change test log level from 'silent' to 'error' (silent not supported) - Fix getService mock type signature with generic parameter Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/core/src/security/plugin-config-validator.test.ts | 2 +- packages/core/src/security/plugin-config-validator.ts | 4 ++-- .../core/src/security/plugin-permission-enforcer.test.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/src/security/plugin-config-validator.test.ts b/packages/core/src/security/plugin-config-validator.test.ts index d11f119177..5e5604df40 100644 --- a/packages/core/src/security/plugin-config-validator.test.ts +++ b/packages/core/src/security/plugin-config-validator.test.ts @@ -9,7 +9,7 @@ describe('PluginConfigValidator', () => { let logger: ReturnType; beforeEach(() => { - logger = createLogger({ level: 'silent' }); + logger = createLogger({ level: 'error' }); validator = new PluginConfigValidator(logger); }); diff --git a/packages/core/src/security/plugin-config-validator.ts b/packages/core/src/security/plugin-config-validator.ts index 369fc69667..817e20b672 100644 --- a/packages/core/src/security/plugin-config-validator.ts +++ b/packages/core/src/security/plugin-config-validator.ts @@ -172,8 +172,8 @@ export class PluginConfigValidator { // Private methods - private formatZodErrors(error: z.ZodError): Array<{path: string; message: string}> { - return error.errors.map((e: z.ZodIssue) => ({ + private formatZodErrors(error: z.ZodError): Array<{path: string; message: string}> { + return error.issues.map((e: z.ZodIssue) => ({ path: e.path.join('.') || 'root', message: e.message, })); diff --git a/packages/core/src/security/plugin-permission-enforcer.test.ts b/packages/core/src/security/plugin-permission-enforcer.test.ts index 7c5faf5c21..0524c3fb93 100644 --- a/packages/core/src/security/plugin-permission-enforcer.test.ts +++ b/packages/core/src/security/plugin-permission-enforcer.test.ts @@ -9,7 +9,7 @@ describe('PluginPermissionEnforcer', () => { let logger: ReturnType; beforeEach(() => { - logger = createLogger({ level: 'silent' }); + logger = createLogger({ level: 'error' }); enforcer = new PluginPermissionEnforcer(logger); }); @@ -172,12 +172,12 @@ describe('SecurePluginContext', () => { let mockBaseContext: PluginContext; beforeEach(() => { - logger = createLogger({ level: 'silent' }); + logger = createLogger({ level: 'error' }); enforcer = new PluginPermissionEnforcer(logger); mockBaseContext = { registerService: () => {}, - getService: (name: string) => ({ name }), + getService: (name: string): T => ({ name } as any), getServices: () => new Map(), hook: () => {}, trigger: async () => {},