@objectstack/core 0.8.2 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/API_REGISTRY.md +392 -0
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +36 -0
  4. package/dist/api-registry-plugin.d.ts +54 -0
  5. package/dist/api-registry-plugin.d.ts.map +1 -0
  6. package/dist/api-registry-plugin.js +53 -0
  7. package/dist/api-registry-plugin.test.d.ts +2 -0
  8. package/dist/api-registry-plugin.test.d.ts.map +1 -0
  9. package/dist/api-registry-plugin.test.js +332 -0
  10. package/dist/api-registry.d.ts +259 -0
  11. package/dist/api-registry.d.ts.map +1 -0
  12. package/dist/api-registry.js +599 -0
  13. package/dist/api-registry.test.d.ts +2 -0
  14. package/dist/api-registry.test.d.ts.map +1 -0
  15. package/dist/api-registry.test.js +957 -0
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +5 -0
  19. package/dist/logger.d.ts +1 -0
  20. package/dist/logger.d.ts.map +1 -1
  21. package/dist/logger.js +35 -11
  22. package/dist/plugin-loader.d.ts +3 -2
  23. package/dist/plugin-loader.d.ts.map +1 -1
  24. package/dist/plugin-loader.js +13 -11
  25. package/dist/qa/adapter.d.ts +14 -0
  26. package/dist/qa/adapter.d.ts.map +1 -0
  27. package/dist/qa/adapter.js +1 -0
  28. package/dist/qa/http-adapter.d.ts +16 -0
  29. package/dist/qa/http-adapter.d.ts.map +1 -0
  30. package/dist/qa/http-adapter.js +107 -0
  31. package/dist/qa/index.d.ts +4 -0
  32. package/dist/qa/index.d.ts.map +1 -0
  33. package/dist/qa/index.js +3 -0
  34. package/dist/qa/runner.d.ts +27 -0
  35. package/dist/qa/runner.d.ts.map +1 -0
  36. package/dist/qa/runner.js +157 -0
  37. package/dist/security/index.d.ts +14 -0
  38. package/dist/security/index.d.ts.map +1 -0
  39. package/dist/security/index.js +13 -0
  40. package/dist/security/plugin-config-validator.d.ts +79 -0
  41. package/dist/security/plugin-config-validator.d.ts.map +1 -0
  42. package/dist/security/plugin-config-validator.js +166 -0
  43. package/dist/security/plugin-config-validator.test.d.ts +2 -0
  44. package/dist/security/plugin-config-validator.test.d.ts.map +1 -0
  45. package/dist/security/plugin-config-validator.test.js +223 -0
  46. package/dist/security/plugin-permission-enforcer.d.ts +154 -0
  47. package/dist/security/plugin-permission-enforcer.d.ts.map +1 -0
  48. package/dist/security/plugin-permission-enforcer.js +323 -0
  49. package/dist/security/plugin-permission-enforcer.test.d.ts +2 -0
  50. package/dist/security/plugin-permission-enforcer.test.d.ts.map +1 -0
  51. package/dist/security/plugin-permission-enforcer.test.js +205 -0
  52. package/dist/security/plugin-signature-verifier.d.ts +96 -0
  53. package/dist/security/plugin-signature-verifier.d.ts.map +1 -0
  54. package/dist/security/plugin-signature-verifier.js +250 -0
  55. package/examples/api-registry-example.ts +557 -0
  56. package/package.json +2 -2
  57. package/src/api-registry-plugin.test.ts +391 -0
  58. package/src/api-registry-plugin.ts +86 -0
  59. package/src/api-registry.test.ts +1089 -0
  60. package/src/api-registry.ts +736 -0
  61. package/src/index.ts +6 -0
  62. package/src/logger.ts +36 -11
  63. package/src/plugin-loader.ts +17 -13
  64. package/src/qa/adapter.ts +14 -0
  65. package/src/qa/http-adapter.ts +114 -0
  66. package/src/qa/index.ts +3 -0
  67. package/src/qa/runner.ts +179 -0
  68. package/src/security/index.ts +29 -0
  69. package/src/security/plugin-config-validator.test.ts +276 -0
  70. package/src/security/plugin-config-validator.ts +191 -0
  71. package/src/security/plugin-permission-enforcer.test.ts +251 -0
  72. package/src/security/plugin-permission-enforcer.ts +408 -0
  73. package/src/security/plugin-signature-verifier.ts +359 -0
package/dist/index.d.ts CHANGED
@@ -10,5 +10,9 @@ export * from './types.js';
10
10
  export * from './logger.js';
11
11
  export * from './plugin-loader.js';
12
12
  export * from './enhanced-kernel.js';
13
+ export * from './api-registry.js';
14
+ export * from './api-registry-plugin.js';
15
+ export * as QA from './qa/index.js';
16
+ export * from './security/index.js';
13
17
  export type { Logger, IHttpServer, IHttpRequest, IHttpResponse, RouteHandler, Middleware, IDataEngine, DriverInterface } from '@objectstack/spec/contracts';
14
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AAGrC,YAAY,EACR,MAAM,EACN,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EAClB,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAC;AAGpC,cAAc,qBAAqB,CAAC;AAGpC,YAAY,EACR,MAAM,EACN,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EAClB,MAAM,6BAA6B,CAAC"}
package/dist/index.js CHANGED
@@ -10,3 +10,8 @@ export * from './types.js';
10
10
  export * from './logger.js';
11
11
  export * from './plugin-loader.js';
12
12
  export * from './enhanced-kernel.js';
13
+ export * from './api-registry.js';
14
+ export * from './api-registry-plugin.js';
15
+ export * as QA from './qa/index.js';
16
+ // Export security utilities
17
+ export * from './security/index.js';
package/dist/logger.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare class ObjectLogger implements Logger {
20
20
  private isNode;
21
21
  private pinoLogger?;
22
22
  private pinoInstance?;
23
+ private require?;
23
24
  constructor(config?: Partial<LoggerConfig>);
24
25
  /**
25
26
  * Initialize Pino logger for Node.js
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;gBAEf,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAwB9C;;OAEG;IACH,OAAO,CAAC,cAAc;IA+EtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY;IAYjD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;IAIzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAM;gBAEV,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAwB9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAuGtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY;IAYjD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;IAIzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
package/dist/logger.js CHANGED
@@ -42,8 +42,12 @@ export class ObjectLogger {
42
42
  if (!this.isNode)
43
43
  return;
44
44
  try {
45
- // Dynamic import for Pino (Node.js only)
46
- const pino = require('pino');
45
+ // Create require function dynamically for Node.js (avoids bundling issues in browser)
46
+ // @ts-ignore - dynamic import of Node.js module
47
+ const { createRequire } = eval('require("module")');
48
+ this.require = createRequire(import.meta.url);
49
+ // Synchronous import for Pino using createRequire (works in ESM)
50
+ const pino = this.require('pino');
47
51
  // Build Pino options
48
52
  const pinoOptions = {
49
53
  level: this.config.level,
@@ -60,15 +64,35 @@ export class ObjectLogger {
60
64
  const targets = [];
61
65
  // Console transport
62
66
  if (this.config.format === 'pretty') {
63
- targets.push({
64
- target: 'pino-pretty',
65
- options: {
66
- colorize: true,
67
- translateTime: 'SYS:standard',
68
- ignore: 'pid,hostname'
69
- },
70
- level: this.config.level
71
- });
67
+ // Check if pino-pretty is available
68
+ let hasPretty = false;
69
+ try {
70
+ this.require.resolve('pino-pretty');
71
+ hasPretty = true;
72
+ }
73
+ catch (e) {
74
+ // ignore
75
+ }
76
+ if (hasPretty) {
77
+ targets.push({
78
+ target: 'pino-pretty',
79
+ options: {
80
+ colorize: true,
81
+ translateTime: 'SYS:standard',
82
+ ignore: 'pid,hostname'
83
+ },
84
+ level: this.config.level
85
+ });
86
+ }
87
+ else {
88
+ console.warn('[Logger] pino-pretty not found. Install it for pretty logging: pnpm add -D pino-pretty');
89
+ // Fallback to text/simple
90
+ targets.push({
91
+ target: 'pino/file',
92
+ options: { destination: 1 },
93
+ level: this.config.level
94
+ });
95
+ }
72
96
  }
73
97
  else if (this.config.format === 'json') {
74
98
  // JSON to stdout
@@ -28,10 +28,11 @@ export interface ServiceRegistration {
28
28
  dependencies?: string[];
29
29
  }
30
30
  /**
31
- * Plugin Configuration Validator
31
+ * Plugin Configuration Validator Interface
32
32
  * Uses Zod for runtime validation of plugin configurations
33
+ * @deprecated Use the PluginConfigValidator class from security module instead
33
34
  */
34
- export interface PluginConfigValidator {
35
+ export interface IPluginConfigValidator {
35
36
  schema: z.ZodSchema;
36
37
  validate(config: any): any;
37
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"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"}
@@ -230,25 +230,27 @@ export class PluginLoader {
230
230
  const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
231
231
  return semverRegex.test(version);
232
232
  }
233
- validatePluginConfig(plugin) {
233
+ validatePluginConfig(plugin, config) {
234
234
  if (!plugin.configSchema) {
235
235
  return;
236
236
  }
237
- // TODO: Configuration validation implementation
238
- // This requires plugin config to be passed during loading
239
- // For now, just validate that the schema exists
240
- this.logger.debug(`Plugin ${plugin.name} has configuration schema (validation not yet implemented)`);
237
+ if (!config) {
238
+ this.logger.debug(`Plugin ${plugin.name} has configuration schema but no config provided`);
239
+ return;
240
+ }
241
+ // Configuration validation is now implemented in PluginConfigValidator
242
+ // This is a placeholder that logs the validation would happen
243
+ // The actual validation should be done by the caller when config is available
244
+ this.logger.debug(`Plugin ${plugin.name} has configuration schema (use PluginConfigValidator for validation)`);
241
245
  }
242
246
  async verifyPluginSignature(plugin) {
243
247
  if (!plugin.signature) {
244
248
  return;
245
249
  }
246
- // TODO: Plugin signature verification implementation
247
- // In a real implementation:
248
- // 1. Extract public key from trusted source
249
- // 2. Verify signature against plugin code hash
250
- // 3. Throw error if verification fails
251
- this.logger.debug(`Plugin ${plugin.name} signature verification (not yet implemented)`);
250
+ // Plugin signature verification is now implemented in PluginSignatureVerifier
251
+ // This is a placeholder that logs the verification would happen
252
+ // The actual verification should be done by the caller with proper security config
253
+ this.logger.debug(`Plugin ${plugin.name} has signature (use PluginSignatureVerifier for verification)`);
252
254
  }
253
255
  async getSingletonService(registration) {
254
256
  let instance = this.serviceInstances.get(registration.name);
@@ -0,0 +1,14 @@
1
+ import { QA } from '@objectstack/spec';
2
+ /**
3
+ * Interface for executing test actions against a target system.
4
+ * The target could be a local Kernel instance or a remote API.
5
+ */
6
+ export interface TestExecutionAdapter {
7
+ /**
8
+ * Execute a single test action.
9
+ * @param action The action to perform (create_record, api_call, etc.)
10
+ * @returns The result of the action (e.g. created record, API response)
11
+ */
12
+ execute(action: QA.TestAction, context: Record<string, unknown>): Promise<unknown>;
13
+ }
14
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/qa/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import { QA } from '@objectstack/spec';
2
+ import { TestExecutionAdapter } from './adapter.js';
3
+ export declare class HttpTestAdapter implements TestExecutionAdapter {
4
+ private baseUrl;
5
+ private authToken?;
6
+ constructor(baseUrl: string, authToken?: string | undefined);
7
+ execute(action: QA.TestAction, _context: Record<string, unknown>): Promise<unknown>;
8
+ private createRecord;
9
+ private updateRecord;
10
+ private deleteRecord;
11
+ private readRecord;
12
+ private queryRecords;
13
+ private rawApiCall;
14
+ private handleResponse;
15
+ }
16
+ //# sourceMappingURL=http-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-adapter.d.ts","sourceRoot":"","sources":["../../src/qa/http-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,qBAAa,eAAgB,YAAW,oBAAoB;IAC9C,OAAO,CAAC,OAAO;IAAU,OAAO,CAAC,SAAS,CAAC;gBAAnC,OAAO,EAAE,MAAM,EAAU,SAAS,CAAC,EAAE,MAAM,YAAA;IAEzD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;YAiC3E,YAAY;YASZ,YAAY;YAWZ,YAAY;YAUZ,UAAU;YAUV,YAAY;YAUZ,UAAU;YAaV,cAAc;CAW7B"}
@@ -0,0 +1,107 @@
1
+ export class HttpTestAdapter {
2
+ constructor(baseUrl, authToken) {
3
+ this.baseUrl = baseUrl;
4
+ this.authToken = authToken;
5
+ }
6
+ async execute(action, _context) {
7
+ const headers = {
8
+ 'Content-Type': 'application/json',
9
+ };
10
+ if (this.authToken) {
11
+ headers['Authorization'] = `Bearer ${this.authToken}`;
12
+ }
13
+ // If action.user is specified, maybe add a specific header for impersonation if supported?
14
+ if (action.user) {
15
+ headers['X-Run-As'] = action.user;
16
+ }
17
+ switch (action.type) {
18
+ case 'create_record':
19
+ return this.createRecord(action.target, action.payload || {}, headers);
20
+ case 'update_record':
21
+ return this.updateRecord(action.target, action.payload || {}, headers);
22
+ case 'delete_record':
23
+ return this.deleteRecord(action.target, action.payload || {}, headers);
24
+ case 'read_record':
25
+ return this.readRecord(action.target, action.payload || {}, headers);
26
+ case 'query_records':
27
+ return this.queryRecords(action.target, action.payload || {}, headers);
28
+ case 'api_call':
29
+ return this.rawApiCall(action.target, action.payload || {}, headers);
30
+ case 'wait':
31
+ const ms = Number(action.payload?.duration || 1000);
32
+ return new Promise(resolve => setTimeout(() => resolve({ waited: ms }), ms));
33
+ default:
34
+ throw new Error(`Unsupported action type in HttpAdapter: ${action.type}`);
35
+ }
36
+ }
37
+ async createRecord(objectName, data, headers) {
38
+ const response = await fetch(`${this.baseUrl}/api/data/${objectName}`, {
39
+ method: 'POST',
40
+ headers,
41
+ body: JSON.stringify(data)
42
+ });
43
+ return this.handleResponse(response);
44
+ }
45
+ async updateRecord(objectName, data, headers) {
46
+ const id = data._id || data.id;
47
+ if (!id)
48
+ throw new Error('Update record requires _id or id in payload');
49
+ const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {
50
+ method: 'PUT',
51
+ headers,
52
+ body: JSON.stringify(data)
53
+ });
54
+ return this.handleResponse(response);
55
+ }
56
+ async deleteRecord(objectName, data, headers) {
57
+ const id = data._id || data.id;
58
+ if (!id)
59
+ throw new Error('Delete record requires _id or id in payload');
60
+ const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {
61
+ method: 'DELETE',
62
+ headers
63
+ });
64
+ return this.handleResponse(response);
65
+ }
66
+ async readRecord(objectName, data, headers) {
67
+ const id = data._id || data.id;
68
+ if (!id)
69
+ throw new Error('Read record requires _id or id in payload');
70
+ const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {
71
+ method: 'GET',
72
+ headers
73
+ });
74
+ return this.handleResponse(response);
75
+ }
76
+ async queryRecords(objectName, data, headers) {
77
+ // Assuming query via POST or GraphQL-like endpoint
78
+ const response = await fetch(`${this.baseUrl}/api/data/${objectName}/query`, {
79
+ method: 'POST',
80
+ headers,
81
+ body: JSON.stringify(data)
82
+ });
83
+ return this.handleResponse(response);
84
+ }
85
+ async rawApiCall(endpoint, data, headers) {
86
+ const method = data.method || 'GET';
87
+ const body = data.body ? JSON.stringify(data.body) : undefined;
88
+ const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;
89
+ const response = await fetch(url, {
90
+ method,
91
+ headers,
92
+ body
93
+ });
94
+ return this.handleResponse(response);
95
+ }
96
+ async handleResponse(response) {
97
+ if (!response.ok) {
98
+ const text = await response.text();
99
+ throw new Error(`HTTP Error ${response.status}: ${text}`);
100
+ }
101
+ const contentType = response.headers.get('content-type');
102
+ if (contentType && contentType.includes('application/json')) {
103
+ return response.json();
104
+ }
105
+ return response.text();
106
+ }
107
+ }
@@ -0,0 +1,4 @@
1
+ export * from './adapter.js';
2
+ export * from './runner.js';
3
+ export * from './http-adapter.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/qa/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './adapter.js';
2
+ export * from './runner.js';
3
+ export * from './http-adapter.js';
@@ -0,0 +1,27 @@
1
+ import { QA } from '@objectstack/spec';
2
+ import { TestExecutionAdapter } from './adapter.js';
3
+ export interface TestResult {
4
+ scenarioId: string;
5
+ passed: boolean;
6
+ steps: StepResult[];
7
+ error?: unknown;
8
+ duration: number;
9
+ }
10
+ export interface StepResult {
11
+ stepName: string;
12
+ passed: boolean;
13
+ error?: unknown;
14
+ output?: unknown;
15
+ duration: number;
16
+ }
17
+ export declare class TestRunner {
18
+ private adapter;
19
+ constructor(adapter: TestExecutionAdapter);
20
+ runSuite(suite: QA.TestSuite): Promise<TestResult[]>;
21
+ runScenario(scenario: QA.TestScenario): Promise<TestResult>;
22
+ private runStep;
23
+ private resolveVariables;
24
+ private getValueByPath;
25
+ private assert;
26
+ }
27
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/qa/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,oBAAoB;IAE3C,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQpD,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;YA4EnD,OAAO;IAyBrB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,MAAM;CA8Bf"}
@@ -0,0 +1,157 @@
1
+ export class TestRunner {
2
+ constructor(adapter) {
3
+ this.adapter = adapter;
4
+ }
5
+ async runSuite(suite) {
6
+ const results = [];
7
+ for (const scenario of suite.scenarios) {
8
+ results.push(await this.runScenario(scenario));
9
+ }
10
+ return results;
11
+ }
12
+ async runScenario(scenario) {
13
+ const startTime = Date.now();
14
+ const context = {}; // Variable context
15
+ // Initialize context from initial payload if needed? Currently schema doesn't have initial context prop on Scenario
16
+ // But we defined TestContextSchema separately.
17
+ // Setup
18
+ if (scenario.setup) {
19
+ for (const step of scenario.setup) {
20
+ try {
21
+ await this.runStep(step, context);
22
+ }
23
+ catch (e) {
24
+ return {
25
+ scenarioId: scenario.id,
26
+ passed: false,
27
+ steps: [],
28
+ error: `Setup failed: ${e instanceof Error ? e.message : String(e)}`,
29
+ duration: Date.now() - startTime
30
+ };
31
+ }
32
+ }
33
+ }
34
+ const stepResults = [];
35
+ let scenarioPassed = true;
36
+ let scenarioError = undefined;
37
+ // Main Steps
38
+ for (const step of scenario.steps) {
39
+ const stepStartTime = Date.now();
40
+ try {
41
+ const output = await this.runStep(step, context);
42
+ stepResults.push({
43
+ stepName: step.name,
44
+ passed: true,
45
+ output,
46
+ duration: Date.now() - stepStartTime
47
+ });
48
+ }
49
+ catch (e) {
50
+ scenarioPassed = false;
51
+ scenarioError = e;
52
+ stepResults.push({
53
+ stepName: step.name,
54
+ passed: false,
55
+ error: e,
56
+ duration: Date.now() - stepStartTime
57
+ });
58
+ break; // Stop on first failure
59
+ }
60
+ }
61
+ // Teardown (run even if failed)
62
+ if (scenario.teardown) {
63
+ for (const step of scenario.teardown) {
64
+ try {
65
+ await this.runStep(step, context);
66
+ }
67
+ catch (e) {
68
+ // Log teardown failure but don't override main failure if it exists
69
+ if (scenarioPassed) {
70
+ scenarioPassed = false;
71
+ scenarioError = `Teardown failed: ${e instanceof Error ? e.message : String(e)}`;
72
+ }
73
+ }
74
+ }
75
+ }
76
+ return {
77
+ scenarioId: scenario.id,
78
+ passed: scenarioPassed,
79
+ steps: stepResults,
80
+ error: scenarioError,
81
+ duration: Date.now() - startTime
82
+ };
83
+ }
84
+ async runStep(step, context) {
85
+ // 1. Resolve Variables with Context (Simple interpolation or just pass context?)
86
+ // For now, assume adpater handles context resolution or we do basic replacement
87
+ const resolvedAction = this.resolveVariables(step.action, context);
88
+ // 2. Execute Action
89
+ const result = await this.adapter.execute(resolvedAction, context);
90
+ // 3. Capture Outputs
91
+ if (step.capture) {
92
+ for (const [varName, path] of Object.entries(step.capture)) {
93
+ context[varName] = this.getValueByPath(result, path);
94
+ }
95
+ }
96
+ // 4. Run Assertions
97
+ if (step.assertions) {
98
+ for (const assertion of step.assertions) {
99
+ this.assert(result, assertion, context);
100
+ }
101
+ }
102
+ return result;
103
+ }
104
+ resolveVariables(action, _context) {
105
+ // TODO: Implement JSON path variable substitution stringify/parse
106
+ // For now returning as is
107
+ return action;
108
+ }
109
+ getValueByPath(obj, path) {
110
+ if (!path)
111
+ return obj;
112
+ const parts = path.split('.');
113
+ let current = obj;
114
+ for (const part of parts) {
115
+ if (current === null || current === undefined)
116
+ return undefined;
117
+ current = current[part];
118
+ }
119
+ return current;
120
+ }
121
+ assert(result, assertion, _context) {
122
+ const actual = this.getValueByPath(result, assertion.field);
123
+ // Resolve expected value if it's a variable ref?
124
+ const expected = assertion.expectedValue; // Simplify for now
125
+ switch (assertion.operator) {
126
+ case 'equals':
127
+ if (actual !== expected)
128
+ throw new Error(`Assertion failed: ${assertion.field} expected ${expected}, got ${actual}`);
129
+ break;
130
+ case 'not_equals':
131
+ if (actual === expected)
132
+ throw new Error(`Assertion failed: ${assertion.field} expected not ${expected}, got ${actual}`);
133
+ break;
134
+ case 'contains':
135
+ if (Array.isArray(actual)) {
136
+ if (!actual.includes(expected))
137
+ throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);
138
+ }
139
+ else if (typeof actual === 'string') {
140
+ if (!actual.includes(String(expected)))
141
+ throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);
142
+ }
143
+ break;
144
+ case 'not_null':
145
+ if (actual === null || actual === undefined)
146
+ throw new Error(`Assertion failed: ${assertion.field} is null`);
147
+ break;
148
+ case 'is_null':
149
+ if (actual !== null && actual !== undefined)
150
+ throw new Error(`Assertion failed: ${assertion.field} is not null`);
151
+ break;
152
+ // ... Add other operators
153
+ default:
154
+ throw new Error(`Unknown assertion operator: ${assertion.operator}`);
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Security Module
3
+ *
4
+ * Provides security features for the ObjectStack microkernel:
5
+ * - Plugin signature verification
6
+ * - Plugin configuration validation
7
+ * - Permission and capability enforcement
8
+ *
9
+ * @module @objectstack/core/security
10
+ */
11
+ export { PluginSignatureVerifier, type PluginSignatureConfig, type SignatureVerificationResult, } from './plugin-signature-verifier.js';
12
+ export { PluginConfigValidator, createPluginConfigValidator, } from './plugin-config-validator.js';
13
+ export { PluginPermissionEnforcer, SecurePluginContext, createPluginPermissionEnforcer, type PluginPermissions, type PermissionCheckResult, } from './plugin-permission-enforcer.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,8BAA8B,EAC9B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Security Module
3
+ *
4
+ * Provides security features for the ObjectStack microkernel:
5
+ * - Plugin signature verification
6
+ * - Plugin configuration validation
7
+ * - Permission and capability enforcement
8
+ *
9
+ * @module @objectstack/core/security
10
+ */
11
+ export { PluginSignatureVerifier, } from './plugin-signature-verifier.js';
12
+ export { PluginConfigValidator, createPluginConfigValidator, } from './plugin-config-validator.js';
13
+ export { PluginPermissionEnforcer, SecurePluginContext, createPluginPermissionEnforcer, } from './plugin-permission-enforcer.js';
@@ -0,0 +1,79 @@
1
+ import type { Logger } from '@objectstack/spec/contracts';
2
+ import type { PluginMetadata } from '../plugin-loader.js';
3
+ /**
4
+ * Plugin Configuration Validator
5
+ *
6
+ * Validates plugin configurations against Zod schemas to ensure:
7
+ * 1. Type safety - all config values have correct types
8
+ * 2. Business rules - values meet constraints (min/max, regex, etc.)
9
+ * 3. Required fields - all mandatory configuration is provided
10
+ * 4. Default values - missing optional fields get defaults
11
+ *
12
+ * Architecture:
13
+ * - Uses Zod for runtime validation
14
+ * - Provides detailed error messages with field paths
15
+ * - Supports nested configuration objects
16
+ * - Allows partial validation for incremental updates
17
+ *
18
+ * Usage:
19
+ * ```typescript
20
+ * const validator = new PluginConfigValidator(logger);
21
+ * const validConfig = validator.validatePluginConfig(plugin, userConfig);
22
+ * ```
23
+ */
24
+ export declare class PluginConfigValidator {
25
+ private logger;
26
+ constructor(logger: Logger);
27
+ /**
28
+ * Validate plugin configuration against its Zod schema
29
+ *
30
+ * @param plugin - Plugin metadata with configSchema
31
+ * @param config - User-provided configuration
32
+ * @returns Validated and typed configuration
33
+ * @throws Error with detailed validation errors
34
+ */
35
+ validatePluginConfig<T = any>(plugin: PluginMetadata, config: any): T;
36
+ /**
37
+ * Validate partial configuration (for incremental updates)
38
+ *
39
+ * @param plugin - Plugin metadata
40
+ * @param partialConfig - Partial configuration to validate
41
+ * @returns Validated partial configuration
42
+ */
43
+ validatePartialConfig<T = any>(plugin: PluginMetadata, partialConfig: any): Partial<T>;
44
+ /**
45
+ * Get default configuration from schema
46
+ *
47
+ * @param plugin - Plugin metadata
48
+ * @returns Default configuration object
49
+ */
50
+ getDefaultConfig<T = any>(plugin: PluginMetadata): T | undefined;
51
+ /**
52
+ * Check if configuration is valid without throwing
53
+ *
54
+ * @param plugin - Plugin metadata
55
+ * @param config - Configuration to check
56
+ * @returns True if valid, false otherwise
57
+ */
58
+ isConfigValid(plugin: PluginMetadata, config: any): boolean;
59
+ /**
60
+ * Get configuration errors without throwing
61
+ *
62
+ * @param plugin - Plugin metadata
63
+ * @param config - Configuration to check
64
+ * @returns Array of validation errors, or empty array if valid
65
+ */
66
+ getConfigErrors(plugin: PluginMetadata, config: any): Array<{
67
+ path: string;
68
+ message: string;
69
+ }>;
70
+ private formatZodErrors;
71
+ }
72
+ /**
73
+ * Create a plugin config validator
74
+ *
75
+ * @param logger - Logger instance
76
+ * @returns Plugin config validator
77
+ */
78
+ export declare function createPluginConfigValidator(logger: Logger): PluginConfigValidator;
79
+ //# sourceMappingURL=plugin-config-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-config-validator.d.ts","sourceRoot":"","sources":["../../src/security/plugin-config-validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B;;;;;;;OAOG;IACH,oBAAoB,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAqCrE;;;;;;OAMG;IACH,qBAAqB,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IA4BtF;;;;;OAKG;IACH,gBAAgB,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,SAAS;IAiBhE;;;;;;OAMG;IACH,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO;IAS3D;;;;;;OAMG;IACH,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAgB5F,OAAO,CAAC,eAAe;CAMxB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAEjF"}