@onlineapps/service-validator-core 1.0.8 → 1.0.10

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 (40) hide show
  1. package/README.md +0 -0
  2. package/jest.config.js +0 -0
  3. package/package.json +5 -1
  4. package/src/config.js +30 -0
  5. package/src/defaults.js +17 -0
  6. package/src/index.js +1 -1
  7. package/src/security/ValidationProofCodec.js +0 -0
  8. package/src/security/ValidationProofVerifier.js +0 -0
  9. package/src/security/certificateManager.js +0 -0
  10. package/src/security/tokenManager.js +17 -12
  11. package/src/types/ValidationProofSchema.js +0 -0
  12. package/src/utils/FingerprintUtils.js +16 -3
  13. package/src/validators/connectorValidator.js +0 -0
  14. package/src/validators/endpointValidator.js +0 -0
  15. package/src/validators/healthValidator.js +0 -0
  16. package/src/validators/openApiValidator.js +0 -0
  17. package/tests/component/validation-flow.test.js +10 -0
  18. package/tests/integration/real-validation.test.js +11 -1
  19. package/tests/unit/ValidationCore.test.js +10 -0
  20. package/coverage/clover.xml +0 -468
  21. package/coverage/coverage-final.json +0 -8
  22. package/coverage/lcov-report/base.css +0 -224
  23. package/coverage/lcov-report/block-navigation.js +0 -87
  24. package/coverage/lcov-report/favicon.png +0 -0
  25. package/coverage/lcov-report/index.html +0 -146
  26. package/coverage/lcov-report/prettify.css +0 -1
  27. package/coverage/lcov-report/prettify.js +0 -2
  28. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  29. package/coverage/lcov-report/sorter.js +0 -210
  30. package/coverage/lcov-report/src/index.html +0 -116
  31. package/coverage/lcov-report/src/index.js.html +0 -643
  32. package/coverage/lcov-report/src/security/certificateManager.js.html +0 -799
  33. package/coverage/lcov-report/src/security/index.html +0 -131
  34. package/coverage/lcov-report/src/security/tokenManager.js.html +0 -622
  35. package/coverage/lcov-report/src/validators/connectorValidator.js.html +0 -787
  36. package/coverage/lcov-report/src/validators/endpointValidator.js.html +0 -577
  37. package/coverage/lcov-report/src/validators/healthValidator.js.html +0 -655
  38. package/coverage/lcov-report/src/validators/index.html +0 -161
  39. package/coverage/lcov-report/src/validators/openApiValidator.js.html +0 -517
  40. package/coverage/lcov.info +0 -982
package/README.md CHANGED
File without changes
package/jest.config.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@onlineapps/service-validator-core",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Core validation logic for microservices",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
7
7
  "test": "jest",
8
+ "test:unit": "jest tests/unit",
9
+ "test:component": "jest tests/component",
10
+ "test:integration": "jest tests/integration",
8
11
  "test:coverage": "jest --coverage",
9
12
  "lint": "eslint src/"
10
13
  },
@@ -17,6 +20,7 @@
17
20
  "license": "MIT",
18
21
  "dependencies": {
19
22
  "ajv": "^8.12.0",
23
+ "@onlineapps/runtime-config": "1.0.2",
20
24
  "jsonwebtoken": "^9.0.2",
21
25
  "uuid": "^9.0.1"
22
26
  },
package/src/config.js ADDED
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Runtime configuration schema for @onlineapps/service-validator-core.
5
+ *
6
+ * Priority:
7
+ * 1) Explicit config
8
+ * 2) ENV
9
+ * 3) Module-owned defaults
10
+ *
11
+ * IMPORTANT:
12
+ * - Token secret is required (NO FALLBACKS).
13
+ */
14
+
15
+ const { createRuntimeConfig } = require('@onlineapps/runtime-config');
16
+ const DEFAULTS = require('./defaults');
17
+
18
+ const runtimeCfg = createRuntimeConfig({
19
+ defaults: DEFAULTS,
20
+ schema: {
21
+ tokenSecret: { env: 'VALIDATION_TOKEN_SECRET', required: true },
22
+ tokenExpiresIn: { env: 'VALIDATION_TOKEN_EXPIRES_IN', defaultKey: 'tokenExpiresIn' },
23
+ tokenAlgorithm: { env: 'VALIDATION_TOKEN_ALGORITHM', defaultKey: 'tokenAlgorithm' },
24
+ tokenIssuer: { env: 'VALIDATION_TOKEN_ISSUER', defaultKey: 'tokenIssuer' },
25
+ }
26
+ });
27
+
28
+ module.exports = runtimeCfg;
29
+
30
+
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Module-owned defaults for @onlineapps/service-validator-core.
5
+ *
6
+ * Ownership rule:
7
+ * - This module owns token behavior defaults (expiry, algorithm, issuer).
8
+ * - Secret is NOT defaulted (must be provided via explicit config or ENV).
9
+ */
10
+
11
+ module.exports = {
12
+ tokenExpiresIn: '24h',
13
+ tokenAlgorithm: 'HS256',
14
+ tokenIssuer: 'validation-core',
15
+ };
16
+
17
+
package/src/index.js CHANGED
@@ -30,7 +30,7 @@ class ValidationCore {
30
30
  health: new HealthValidator()
31
31
  };
32
32
 
33
- this.tokenManager = new TokenManager();
33
+ this.tokenManager = new TokenManager(this.config.token || {});
34
34
  this.certificateManager = new CertificateManager();
35
35
  this.proofVerifier = new ValidationProofVerifier({
36
36
  maxProofAge: config.maxProofAge,
File without changes
File without changes
File without changes
@@ -1,22 +1,27 @@
1
1
  const jwt = require('jsonwebtoken');
2
2
  const crypto = require('crypto');
3
3
  const FingerprintUtils = require('../utils/FingerprintUtils');
4
+ const runtimeCfg = require('../config');
4
5
 
5
6
  class TokenManager {
6
7
  constructor(config = {}) {
7
- this.secret = config.secret || process.env.VALIDATION_TOKEN_SECRET || this.generateSecret();
8
- this.expiresIn = config.expiresIn || '24h';
9
- this.algorithm = config.algorithm || 'HS256';
10
- this.issuer = config.issuer || 'validation-core';
11
- this.usedTokens = new Set(); // Track used tokens for single-use enforcement
12
- }
8
+ let resolved;
9
+ try {
10
+ resolved = runtimeCfg.resolve({
11
+ tokenSecret: config.secret,
12
+ tokenExpiresIn: config.expiresIn,
13
+ tokenAlgorithm: config.algorithm,
14
+ tokenIssuer: config.issuer,
15
+ });
16
+ } catch (err) {
17
+ throw new Error('[TokenManager] Missing configuration - tokenSecret is required (set VALIDATION_TOKEN_SECRET env or pass config.secret)');
18
+ }
13
19
 
14
- /**
15
- * Generate a secure secret if none provided
16
- * @returns {string} Generated secret
17
- */
18
- generateSecret() {
19
- return crypto.randomBytes(64).toString('hex');
20
+ this.secret = resolved.tokenSecret;
21
+ this.expiresIn = resolved.tokenExpiresIn;
22
+ this.algorithm = resolved.tokenAlgorithm;
23
+ this.issuer = resolved.tokenIssuer;
24
+ this.usedTokens = new Set(); // Track used tokens for single-use enforcement
20
25
  }
21
26
 
22
27
  /**
File without changes
@@ -39,9 +39,22 @@ class FingerprintUtils {
39
39
  } else if (typeof data === 'string') {
40
40
  input = data;
41
41
  } else if (typeof data === 'object' && data !== null) {
42
- // Serialize object with optional key sorting
43
- const keys = sortKeys ? Object.keys(data).sort() : Object.keys(data);
44
- input = JSON.stringify(data, keys);
42
+ // Deep sort object keys for deterministic fingerprinting
43
+ const deepSort = (obj) => {
44
+ if (Array.isArray(obj)) {
45
+ return obj.map(deepSort);
46
+ }
47
+ if (obj !== null && typeof obj === 'object') {
48
+ return Object.keys(obj)
49
+ .sort()
50
+ .reduce((acc, key) => {
51
+ acc[key] = deepSort(obj[key]);
52
+ return acc;
53
+ }, {});
54
+ }
55
+ return obj;
56
+ };
57
+ input = JSON.stringify(deepSort(data));
45
58
  } else {
46
59
  // Primitives (number, boolean, null, undefined)
47
60
  input = String(data);
File without changes
File without changes
File without changes
File without changes
@@ -2,10 +2,20 @@ const ValidationCore = require('../../src/index');
2
2
 
3
3
  describe('Validation Flow Component Tests @component', () => {
4
4
  let validationCore;
5
+ let oldSecret;
5
6
 
6
7
  beforeEach(() => {
8
+ oldSecret = process.env.VALIDATION_TOKEN_SECRET;
9
+ process.env.VALIDATION_TOKEN_SECRET = 'test-validation-secret';
7
10
  validationCore = new ValidationCore();
8
11
  });
12
+ afterEach(() => {
13
+ if (oldSecret === undefined) {
14
+ delete process.env.VALIDATION_TOKEN_SECRET;
15
+ } else {
16
+ process.env.VALIDATION_TOKEN_SECRET = oldSecret;
17
+ }
18
+ });
9
19
 
10
20
  describe('Complete validation workflow', () => {
11
21
  it('should perform full validation and generate token', async () => {
@@ -4,10 +4,20 @@ const path = require('path');
4
4
 
5
5
  describe('ValidationCore Integration Tests @integration', () => {
6
6
  let validationCore;
7
+ let oldSecret;
7
8
 
8
9
  beforeEach(() => {
10
+ oldSecret = process.env.VALIDATION_TOKEN_SECRET;
11
+ process.env.VALIDATION_TOKEN_SECRET = 'test-validation-secret';
9
12
  validationCore = new ValidationCore();
10
13
  });
14
+ afterEach(() => {
15
+ if (oldSecret === undefined) {
16
+ delete process.env.VALIDATION_TOKEN_SECRET;
17
+ } else {
18
+ process.env.VALIDATION_TOKEN_SECRET = oldSecret;
19
+ }
20
+ });
11
21
 
12
22
  describe('Real service validation', () => {
13
23
  it('should validate a complete service configuration', async () => {
@@ -20,7 +30,7 @@ describe('ValidationCore Integration Tests @integration', () => {
20
30
  description: 'Simple hello/goodbye service'
21
31
  },
22
32
  servers: [
23
- { url: 'http://localhost:3000', description: 'Local development' }
33
+ { url: 'http://127.0.0.1:3000', description: 'Local development' }
24
34
  ],
25
35
  paths: {
26
36
  '/health': {
@@ -2,10 +2,20 @@ const ValidationCore = require('../../src/index');
2
2
 
3
3
  describe('ValidationCore Unit Tests @unit', () => {
4
4
  let validationCore;
5
+ let oldSecret;
5
6
 
6
7
  beforeEach(() => {
8
+ oldSecret = process.env.VALIDATION_TOKEN_SECRET;
9
+ process.env.VALIDATION_TOKEN_SECRET = 'test-validation-secret';
7
10
  validationCore = new ValidationCore();
8
11
  });
12
+ afterEach(() => {
13
+ if (oldSecret === undefined) {
14
+ delete process.env.VALIDATION_TOKEN_SECRET;
15
+ } else {
16
+ process.env.VALIDATION_TOKEN_SECRET = oldSecret;
17
+ }
18
+ });
9
19
 
10
20
  describe('constructor', () => {
11
21
  it('should initialize with default config', () => {