@onlineapps/conn-orch-validator 6.0.1 → 8.0.0

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 (102) hide show
  1. package/CHANGELOG.md +2591 -2
  2. package/README.md +1075 -7
  3. package/docs/DESIGN.md +3 -1
  4. package/manifests/biz-service.manifest.json +658 -0
  5. package/manifests/library.manifest.json +324 -0
  6. package/package.json +12 -6
  7. package/src/CookbookTestRunner.js +422 -104
  8. package/src/CookbookTestUtils.js +7 -8
  9. package/src/ServiceReadinessValidator.js +78 -42
  10. package/src/ValidationOrchestrator.js +298 -75
  11. package/src/cli/biz-ci-gate.js +176 -33
  12. package/src/cli/oa-lint-scripts.js +221 -0
  13. package/src/cli/oa-sync-template.js +1020 -0
  14. package/src/cli/oa-validate.js +474 -0
  15. package/src/helpers/README.md +12 -2
  16. package/src/helpers/createServiceReadinessTests.js +75 -6
  17. package/src/index.js +33 -3
  18. package/src/lint/scripts/lintScripts.js +298 -0
  19. package/src/manifest/checks/composeRunnerBlock.js +222 -0
  20. package/src/manifest/checks/composeShape.js +165 -0
  21. package/src/manifest/checks/contractBridge.js +181 -0
  22. package/src/manifest/checks/discoveryOrphan.js +50 -0
  23. package/src/manifest/checks/docsLintBridge.js +553 -0
  24. package/src/manifest/checks/fileAbsent.js +35 -0
  25. package/src/manifest/checks/gitTracked.js +204 -0
  26. package/src/manifest/checks/index.js +111 -0
  27. package/src/manifest/checks/libraryContext.js +226 -0
  28. package/src/manifest/checks/libraryDocs.js +75 -0
  29. package/src/manifest/checks/libraryPackage.js +272 -0
  30. package/src/manifest/checks/librarySource.js +274 -0
  31. package/src/manifest/checks/libraryTests.js +121 -0
  32. package/src/manifest/checks/libraryWorkspace.js +293 -0
  33. package/src/manifest/checks/readmeRegion.js +135 -0
  34. package/src/manifest/checks/scriptHeaders.js +79 -0
  35. package/src/manifest/checks/serviceConfig.js +390 -0
  36. package/src/manifest/checks/serviceConnectors.js +81 -0
  37. package/src/manifest/checks/serviceDb.js +388 -0
  38. package/src/manifest/checks/serviceFiles.js +754 -0
  39. package/src/manifest/checks/serviceIdentityRows.js +351 -0
  40. package/src/manifest/checks/serviceRuntime.js +295 -0
  41. package/src/manifest/checks/serviceScripts.js +213 -0
  42. package/src/manifest/deployabilitySignal.js +121 -0
  43. package/src/manifest/discovery.js +386 -0
  44. package/src/manifest/loadManifest.js +62 -0
  45. package/src/manifest/manifestShape.js +446 -0
  46. package/src/manifest/report.js +245 -0
  47. package/src/manifest/runManifest.js +449 -0
  48. package/src/manifest/serviceIdentity.js +140 -0
  49. package/src/manifest/walk.js +74 -0
  50. package/src/manifest/workspaceRoot.js +242 -0
  51. package/src/mocks/MockMQClient.js +13 -30
  52. package/src/mocks/MockRegistry.js +4 -2
  53. package/src/mocks/MockStorage.js +4 -2
  54. package/src/sync/docsRegion.js +463 -0
  55. package/src/sync/generatedRegion.js +228 -0
  56. package/src/sync/readmeLocation.js +182 -0
  57. package/src/sync/readmePointer.js +477 -0
  58. package/src/sync/serviceTemplate.js +583 -0
  59. package/src/sync/sharedEnv.js +162 -0
  60. package/src/sync/uniformFiles.js +474 -0
  61. package/src/utils/bizCiGateContract.js +131 -7
  62. package/src/utils/connectorContract.js +97 -7
  63. package/src/utils/cookbookFormat.js +81 -40
  64. package/src/utils/deployContract.js +213 -13
  65. package/src/utils/envContract.js +57 -1
  66. package/src/utils/handlerRef.js +181 -0
  67. package/src/utils/installContract.js +287 -41
  68. package/src/utils/libCompat.js +29 -7
  69. package/src/utils/migrationOrder.js +163 -0
  70. package/src/utils/preValidation.js +20 -7
  71. package/src/utils/setupDatabase.js +194 -13
  72. package/src/utils/testCoverageContract.js +539 -0
  73. package/src/utils/testNamespace.js +247 -23
  74. package/src/utils/throwawaySchema.js +207 -0
  75. package/src/validators/ServiceStructureValidator.js +21 -20
  76. package/templates/business-service/.dockerignore +42 -0
  77. package/templates/business-service/.gitlab-ci.yml +290 -0
  78. package/templates/business-service/Dockerfile +27 -0
  79. package/templates/business-service/README.md +213 -0
  80. package/templates/business-service/config/biz-docs-lint.tree.json +10 -0
  81. package/templates/business-service/config/env-templates/__SERVICE_NAME__.env +4 -0
  82. package/templates/business-service/config/env-templates/shared.env +65 -0
  83. package/templates/business-service/config/service/config.json +14 -0
  84. package/templates/business-service/config/service/integration-contract.json +12 -0
  85. package/templates/business-service/config/service/operations.json +41 -0
  86. package/templates/business-service/docker-compose.production.yml +60 -0
  87. package/templates/business-service/docker-compose.yml +93 -0
  88. package/templates/business-service/docs/80-setup/INSTALL.md +101 -0
  89. package/templates/business-service/docs/80-setup/PLATFORM_MATRIX.md +65 -0
  90. package/templates/business-service/docs/80-setup/README.md +18 -0
  91. package/templates/business-service/docs/80-setup/VALIDATION.md +78 -0
  92. package/templates/business-service/docs/README.md +18 -0
  93. package/templates/business-service/gitignore +42 -0
  94. package/templates/business-service/index.js +10 -0
  95. package/templates/business-service/init.sh +54 -0
  96. package/templates/business-service/jest.config.js +6 -0
  97. package/templates/business-service/package.json.template +31 -0
  98. package/templates/business-service/scripts/verify-deploy-uniform.sh +180 -0
  99. package/templates/business-service/src/handlers/v3/echo.js +39 -0
  100. package/templates/business-service/tests/cookbooks/echo.json +36 -0
  101. package/templates/business-service/tests/unit/handler.test.js +78 -0
  102. package/src/WorkflowTestRunner.js +0 -402
@@ -0,0 +1,324 @@
1
+ {
2
+ "uniform": "library",
3
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §10-§15",
4
+ "owner": "BIZ-general",
5
+ "blocking_severities": [
6
+ "publish"
7
+ ],
8
+ "verdict": {
9
+ "blocked": "NOT PUBLISHABLE",
10
+ "clear": "PUBLISHABLE",
11
+ "incomplete": "INCOMPLETE: {count} publish row(s) not run ({ids}). Fix: run the uniform from the api checkout — npx oa-validate --library --all --workspace <workspace root>"
12
+ },
13
+ "discovery": {
14
+ "library": {
15
+ "concern": "which directories wear this uniform, and who says they exist",
16
+ "pattern": "api/shared/**/package.json",
17
+ "exclude": [
18
+ "**/node_modules/**",
19
+ "**/tests/fixtures/**"
20
+ ],
21
+ "from": {
22
+ "path": "api/config/libraries.json",
23
+ "list": "libraries",
24
+ "names": "keys"
25
+ },
26
+ "categories": {
27
+ "core": {
28
+ "layer": "L1",
29
+ "concern": "no @onlineapps dependency at all - the foundation every other layer may reach for",
30
+ "may_depend_on": [],
31
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
32
+ },
33
+ "connector": {
34
+ "layer": "L2",
35
+ "concern": "one external resource each, reached by injection; consumed by services and by orchestration",
36
+ "may_depend_on": [
37
+ "core",
38
+ "connector"
39
+ ],
40
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
41
+ },
42
+ "orchestration": {
43
+ "layer": "L3",
44
+ "concern": "coordinates connectors; consumed by services and by runtime",
45
+ "may_depend_on": [
46
+ "core",
47
+ "connector",
48
+ "orchestration"
49
+ ],
50
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
51
+ },
52
+ "runtime": {
53
+ "layer": "L4",
54
+ "concern": "what a running service boots into; consumed by services",
55
+ "may_depend_on": [
56
+ "core",
57
+ "connector",
58
+ "orchestration",
59
+ "runtime"
60
+ ],
61
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
62
+ },
63
+ "tooling": {
64
+ "layer": "none",
65
+ "concern": "developers and CI, never a running service",
66
+ "may_depend_on": [
67
+ "core",
68
+ "connector",
69
+ "orchestration",
70
+ "runtime",
71
+ "tooling"
72
+ ],
73
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
74
+ }
75
+ },
76
+ "rows": [
77
+ {
78
+ "id": "U-ORPHAN",
79
+ "check": "library-orphan",
80
+ "severity": "publish",
81
+ "owner": "BIZ-general",
82
+ "why": "a package on disk the SSOT does not know is published by nothing and pinned by nobody; a name in the SSOT with no package is a version declared for code that does not exist",
83
+ "fix": "declare the package in api/config/libraries.json (libraries), or remove it from api/shared/",
84
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md § Confirmation 20260909-biz-service-manifest-005"
85
+ },
86
+ {
87
+ "id": "U-MISMATCH",
88
+ "check": "library-category",
89
+ "severity": "publish",
90
+ "owner": "BIZ-general",
91
+ "why": "the category is the one fact about a library that cannot be derived - it is the intent, and the dependency graph is the measurement it is checked against",
92
+ "fix": "declare \"oa\": { \"category\": \"<core|connector|orchestration|runtime|tooling>\" } in package.json, and make the dependencies agree with the category's may_depend_on",
93
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md § Confirmation 20260909-biz-service-manifest-005"
94
+ }
95
+ ]
96
+ }
97
+ },
98
+ "duties": {
99
+ "all": {
100
+ "concern": "what every library owes, whatever it is for",
101
+ "applies_to": "*",
102
+ "rows": [
103
+ {
104
+ "id": "L-MAIN",
105
+ "check": "library-main",
106
+ "severity": "publish",
107
+ "owner": "BIZ-general",
108
+ "why": "a package whose entry point is undeclared or missing installs and then fails at the consumer's first require",
109
+ "fix": "declare \"main\" in package.json and make it point at a file that exists",
110
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
111
+ },
112
+ {
113
+ "id": "L-ENGINES",
114
+ "check": "library-engines",
115
+ "severity": "publish",
116
+ "owner": "BIZ-general",
117
+ "why": "one Node major runs the whole platform; a library declaring another one lets npm install it into a runtime nobody tested it on",
118
+ "fix": "set engines.node to the platform major, e.g. \">=24.0.0 <25\"",
119
+ "doc": "api/docs/governance/confirmations/node-runtime-version.md § Confirmation 20260908-node-runtime-version-003",
120
+ "from": {
121
+ "path": "api/.nvmrc",
122
+ "text": true
123
+ }
124
+ },
125
+ {
126
+ "id": "L-TESTS",
127
+ "check": "library-tests",
128
+ "severity": "publish",
129
+ "owner": "BIZ-general",
130
+ "why": "no production code without a test (architecture-principles §10); a package with no unit tier has nothing to run before publishing",
131
+ "fix": "add tests/unit with at least one *.test.js",
132
+ "doc": ".claude/rules/architecture-principles.md §10"
133
+ },
134
+ {
135
+ "id": "L-TEST-SCRIPT",
136
+ "check": "library-test-script",
137
+ "severity": "publish",
138
+ "owner": "BIZ-general",
139
+ "why": "the publish path runs `npm test`; a package without that script is published without a run",
140
+ "fix": "declare scripts.test in package.json",
141
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
142
+ },
143
+ {
144
+ "id": "L-PACK-TESTS",
145
+ "check": "library-pack-tests",
146
+ "severity": "publish",
147
+ "owner": "BIZ-general",
148
+ "why": "tests in the published tarball ship fixtures and dev assumptions into every consumer; the effect is what matters, and a files allowlist achieves it without .npmignore",
149
+ "fix": "add a files allowlist to package.json that omits tests, or exclude tests/ in .npmignore",
150
+ "doc": ".claude/rules/architecture-principles.md § Shared Packages"
151
+ },
152
+ {
153
+ "id": "L-PINS",
154
+ "check": "library-pins",
155
+ "severity": "publish",
156
+ "owner": "BIZ-general",
157
+ "why": "the same commit must install the same code; the manifest is the single owner of every @onlineapps version",
158
+ "fix": "run api/scripts/sync-versions-to-exact.sh, or publish the version the package needs and sync the manifest",
159
+ "doc": ".claude/rules/architecture-principles.md § Version pinning",
160
+ "from": {
161
+ "path": "api/config/libraries.json",
162
+ "list": "libraries",
163
+ "names": "keys"
164
+ }
165
+ },
166
+ {
167
+ "id": "L-NO-FILE-RANGE",
168
+ "check": "library-dep-range",
169
+ "severity": "publish",
170
+ "owner": "BIZ-general",
171
+ "why": "a range or a file: reference makes the installed code depend on the day and on the machine",
172
+ "fix": "pin the exact version the SSOT declares - no ^, no ~, no file:",
173
+ "doc": ".claude/rules/architecture-principles.md § Version pinning"
174
+ },
175
+ {
176
+ "id": "L-CHANGELOG",
177
+ "check": "file-present",
178
+ "path": "CHANGELOG.md",
179
+ "severity": "publish",
180
+ "owner": "BIZ-general",
181
+ "why": "a published version whose change nobody wrote down is a version nobody can reason about afterwards",
182
+ "fix": "add CHANGELOG.md with an entry for the version being published",
183
+ "doc": "api/docs/guides/library-publishing-process.md"
184
+ },
185
+ {
186
+ "id": "L-README",
187
+ "check": "library-readme",
188
+ "severity": "publish",
189
+ "owner": "BIZ-general",
190
+ "why": "a README that cannot say which fact class it owns has no reason to exist, and nobody can tell a live one from a stale one",
191
+ "fix": "give README.md the node header - \"> Owns: <the fact class this file is the single owner of>\" and \"> Status: current|draft|archived\"",
192
+ "doc": "api/docs/standards/INFRA-DOC-STANDARD.md"
193
+ },
194
+ {
195
+ "id": "L-README-REGION",
196
+ "check": "library-readme-region",
197
+ "path": "README.md",
198
+ "severity": "publish",
199
+ "owner": "BIZ-general",
200
+ "why": "the same duty as L-README one row up, on the half of the file that is generated: L-README asks whether the node header is there, this row asks whether the rendered uniform pointer still says what the manifest says. A separate row because the two have separate fixes - one is written by a human, the other by a command",
201
+ "fix": "npx oa-sync-template readme-uniform --all",
202
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md § Confirmation 20260909-biz-service-manifest-005"
203
+ },
204
+ {
205
+ "id": "L-CONSUMER",
206
+ "check": "library-consumer",
207
+ "severity": "publish",
208
+ "owner": "BIZ-general",
209
+ "why": "a library nobody depends on is either unwired or dead, and the third option does not exist",
210
+ "fix": "wire the package into the consumer that should use it, or delete it - git keeps the history",
211
+ "doc": ".claude/rules/change-discipline.md § Removing something removes its declaration",
212
+ "consumer_patterns": [
213
+ "api_biz/*/package.json",
214
+ "api/infra/*/package.json",
215
+ "api/shared/**/package.json",
216
+ "api/package.json"
217
+ ]
218
+ }
219
+ ]
220
+ },
221
+ "core": {
222
+ "concern": "layer L1 - the foundation",
223
+ "applies_to": "core",
224
+ "rows": [
225
+ {
226
+ "id": "L-CORE-DEPS",
227
+ "check": "library-core-deps",
228
+ "severity": "publish",
229
+ "owner": "BIZ-general",
230
+ "why": "core is L1 by construction, not by intention - one @onlineapps dependency and it is a connector wearing the wrong name",
231
+ "fix": "remove the @onlineapps dependency, or declare the category the graph shows",
232
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
233
+ },
234
+ {
235
+ "id": "L-CORE-EXPORTS",
236
+ "check": "library-core-exports",
237
+ "severity": "publish",
238
+ "owner": "BIZ-general",
239
+ "why": "everything above L1 imports from here, so what the package exports is its contract and must be explicit",
240
+ "fix": "declare exports in package.json, or make main resolve to a module that exports named symbols",
241
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
242
+ }
243
+ ]
244
+ },
245
+ "connector": {
246
+ "concern": "layer L2 - one external resource each",
247
+ "applies_to": "connector",
248
+ "rows": [
249
+ {
250
+ "id": "L-CONNECTOR-ENV",
251
+ "check": "library-source-env",
252
+ "severity": "publish",
253
+ "owner": "BIZ-general",
254
+ "why": "a connector receives its dependencies, it does not go looking for them; reading the environment outside the config module is the hidden input DI exists to remove - the module is one file or one directory, the concept is the same",
255
+ "fix": "take the value through the constructor and read the environment in the config module only - src/config/ or src/config.js",
256
+ "doc": ".claude/rules/architecture-principles.md §1",
257
+ "allowed": [
258
+ "src/config/",
259
+ "src/config.js"
260
+ ]
261
+ }
262
+ ]
263
+ },
264
+ "runtime": {
265
+ "concern": "layer L4 - what a running service boots into",
266
+ "applies_to": "runtime",
267
+ "rows": [
268
+ {
269
+ "id": "L-RUNTIME-CLIENT",
270
+ "check": "library-runtime-client",
271
+ "severity": "publish",
272
+ "owner": "BIZ-general",
273
+ "why": "storage and database access has one unified rail; a runtime package holding its own client is a second one",
274
+ "fix": "depend on the connector that owns the resource instead of on the client library",
275
+ "doc": "api/.claude/rules/package-management.md § Storage Architecture",
276
+ "forbidden_packages": [
277
+ "minio",
278
+ "mysql2",
279
+ "pg",
280
+ "sequelize"
281
+ ]
282
+ }
283
+ ]
284
+ },
285
+ "tooling": {
286
+ "concern": "developers and CI, never a running service",
287
+ "applies_to": "tooling",
288
+ "rows": [
289
+ {
290
+ "id": "L-TOOLING",
291
+ "check": "library-tooling",
292
+ "severity": "publish",
293
+ "owner": "BIZ-general",
294
+ "why": "tooling is reached by a command, not by an import; a service carrying it in dependencies ships a developer tool into production",
295
+ "fix": "declare a bin entry, and move the package out of every service's dependencies",
296
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11",
297
+ "service_pattern": "api_biz/*/package.json"
298
+ }
299
+ ]
300
+ }
301
+ },
302
+ "guidance": {
303
+ "L-LINT": {
304
+ "why": "not a row: three eslint configs, four lint scripts and no gate anywhere in api/shared (measured 2026-09-09). Under this manifest exactly one of two things is true - one shared config in this package, run by the publish gate, or no config anywhere. Leave-as-is is the defect state, not an option; the execution is d.213.",
305
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §14"
306
+ },
307
+ "L-LOGGER-ERROR-CONTRACT": {
308
+ "why": "not a row: 002 §11 asks a connector to implement the logger contract and the error contract, but names no observable that decides it. A pin on @onlineapps/logger-contract is not the duty - 2 of 8 connectors carry one and that says nothing about behaviour. No check, so not a rule (001 §6).",
309
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
310
+ },
311
+ "L-BOOT-PHASES": {
312
+ "why": "not a row: 002 §11 asks a runtime package to ship its boot phases with [Context] Problem - Fix messages. Which phases a package owns is not declared anywhere, so nothing can decide the duty. No check, so not a rule (001 §6).",
313
+ "doc": ".claude/rules/architecture-principles.md §5"
314
+ },
315
+ "L-EXPORT-MAJOR": {
316
+ "why": "not a row: a removed or renamed export must bump the major, which needs the previous published version's exports to compare against. That comparison belongs to the publish path, where the registry is reachable - the candidate check is a diff of exports against the published version in publish-library.sh (d.214).",
317
+ "doc": ".claude/rules/architecture-principles.md § Shared Packages"
318
+ },
319
+ "L-TEST-SCRIPT-BODY": {
320
+ "why": "not a row: 002 §11 asks for a test script equal to the category's canonical body, and no canonical body is decided. Measured today: 2 bodies for scripts.test, 3 for scripts.test:unit, and the split follows no category. L-TEST-SCRIPT therefore checks existence only.",
321
+ "doc": "api/docs/governance/confirmations/biz-service-manifest.md §11"
322
+ }
323
+ }
324
+ }
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@onlineapps/conn-orch-validator",
3
- "version": "6.0.1",
3
+ "version": "8.0.0",
4
4
  "description": "Validation orchestrator for OA Drive microservices - coordinates validation across all layers (base, infra, orch, business)",
5
+ "oa": {
6
+ "category": "orchestration"
7
+ },
5
8
  "main": "src/index.js",
6
9
  "bin": {
7
- "oa-biz-ci-gate": "src/cli/biz-ci-gate.js"
10
+ "oa-biz-ci-gate": "src/cli/biz-ci-gate.js",
11
+ "oa-lint-scripts": "src/cli/oa-lint-scripts.js",
12
+ "oa-sync-template": "src/cli/oa-sync-template.js",
13
+ "oa-validate": "src/cli/oa-validate.js"
8
14
  },
9
15
  "scripts": {
10
- "test": "jest",
16
+ "test": "npm run test:unit",
11
17
  "test:unit": "jest tests/unit",
12
- "test:integration": "jest tests/integration",
13
18
  "test:coverage": "jest --coverage"
14
19
  },
15
20
  "keywords": [
@@ -23,13 +28,14 @@
23
28
  "author": "OnlineApps",
24
29
  "license": "PROPRIETARY",
25
30
  "dependencies": {
26
- "@onlineapps/service-validator-core": "1.0.15"
31
+ "@onlineapps/logger-contract": "1.1.0",
32
+ "@onlineapps/service-validator-core": "2.0.0"
27
33
  },
28
34
  "devDependencies": {
29
35
  "jest": "^29.5.0"
30
36
  },
31
37
  "engines": {
32
- "node": ">=14.0.0"
38
+ "node": ">=24.0.0 <25"
33
39
  },
34
40
  "directories": {
35
41
  "doc": "docs",