@onlineapps/conn-orch-validator 8.1.0 → 10.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.
- package/CHANGELOG.md +412 -0
- package/README.md +83 -9
- package/docs/DESIGN.md +21 -7
- package/manifests/biz-service.manifest.json +28 -5
- package/package.json +3 -3
- package/src/CookbookTestRunner.js +84 -16
- package/src/ValidationOrchestrator.js +73 -20
- package/src/cli/biz-ci-gate.js +28 -14
- package/src/cli/oa-sync-template.js +23 -8
- package/src/cli/oa-validate.js +7 -1
- package/src/index.js +21 -13
- package/src/lint/scripts/lintScripts.js +65 -18
- package/src/manifest/checks/composeRunnerBlock.js +37 -20
- package/src/manifest/checks/discoveryOrphan.js +2 -1
- package/src/manifest/checks/docsLintBridge.js +79 -21
- package/src/manifest/checks/gitTracked.js +12 -1
- package/src/manifest/checks/libraryPackage.js +3 -1
- package/src/manifest/checks/libraryWorkspace.js +18 -3
- package/src/manifest/checks/readmeRegion.js +9 -1
- package/src/manifest/checks/serviceConfig.js +29 -12
- package/src/manifest/checks/serviceFiles.js +34 -7
- package/src/manifest/checks/serviceIdentityRows.js +3 -1
- package/src/manifest/checks/serviceRuntime.js +3 -1
- package/src/manifest/discovery.js +25 -7
- package/src/manifest/runManifest.js +58 -7
- package/src/manifest/workspaceRoot.js +91 -5
- package/src/sync/serviceTemplate.js +76 -7
- package/src/sync/sharedEnv.js +11 -4
- package/src/sync/uniformFiles.js +91 -21
- package/src/utils/bizCiGateContract.js +25 -1
- package/src/utils/installContract.js +46 -5
- package/src/utils/libCompat.js +39 -19
- package/src/utils/preValidation.js +56 -11
- package/src/utils/stepFailure.js +106 -19
- package/src/utils/testCoverageContract.js +60 -2
- package/src/utils/throwawaySchema.js +92 -7
- package/src/validatorIdentity.js +31 -0
- package/src/validators/ServiceStructureValidator.js +41 -15
- package/src/validators/ValidationProofGenerator.js +73 -34
- package/templates/business-service/.dockerignore +9 -1
- package/templates/business-service/.gitlab-ci.yml +97 -30
- package/templates/business-service/README.md +14 -5
- package/templates/business-service/config/env-templates/__SERVICE_NAME__.env +17 -5
- package/templates/business-service/config/env-templates/shared.env +7 -1
- package/templates/business-service/docs/80-setup/INSTALL.md +13 -6
- package/templates/business-service/docs/80-setup/PLATFORM_MATRIX.md +1 -1
- package/templates/business-service/docs/80-setup/VALIDATION.md +1 -1
- package/templates/business-service/jest.config.js +9 -1
- package/templates/business-service/package.json.template +1 -1
- package/src/mocks/MockStorage.js +0 -188
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,418 @@ All notable changes to this package. Follows [Keep a Changelog](https://keepacha
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [10.0.0] — 2026-09-16
|
|
8
|
+
|
|
9
|
+
### Removed — `MockStorage` (d.583)
|
|
10
|
+
|
|
11
|
+
Dvojník bez konzumenta (po d.576) smazán i se souborem a vlastním testem; `MockMQClient`/`MockRegistry` zůstávají
|
|
12
|
+
(interní čtenáři), povrch exportů beze změny (17 jmen).
|
|
13
|
+
|
|
14
|
+
### Changed — `tests/cookbooks` je podmínka bootu, ne doporučení (d.584)
|
|
15
|
+
|
|
16
|
+
Chybějící nebo prázdný adresář = error `MISSING_COOKBOOKS` (severity boot; orchestrátor fail-fast na kroku 1) místo dvou
|
|
17
|
+
warningů, které nechaly absenci projít až k odmítnutému důkazu. `tests/unit`/`tests/integration` zůstávají doporučením
|
|
18
|
+
(uniforma jejich existenci nevymáhá). Jedna kolej s F-DOCKERIGNORE (`!tests/cookbooks`). Kaskáda: žádná — 8/8 služeb recepty má.
|
|
19
|
+
|
|
20
|
+
### Changed — F-DOCKERIGNORE vylučuje testovací strom, `tests/cookbooks` zůstává v obrazu (d.560)
|
|
21
|
+
|
|
22
|
+
`tests/` všech 8 služeb jelo do produkčního obrazu (`COPY . .`, ingest 632 K). Pravidlo `dockerignoreEntries()` = gitignore ∪
|
|
23
|
+
{`tests`, `**/tests`} ∖ {`tests/cookbooks`}: testy do artefaktu nepatří (analogie `L-PACK-TESTS`), cookbooky jsou deklarace
|
|
24
|
+
Tier-1, které boot čte ve fázi 0.2 — obraz bez nich nenaběhne (`ValidationProofGenerator` odmítne důkaz s `testsRun 0`).
|
|
25
|
+
Blok `oa-dockerignore v1` je výstup pravidla; ověřeno skutečným buildem (BuildKit `!tests/cookbooks`). Běžec netrpí (bind mount).
|
|
26
|
+
Kaskáda: služby přegenerují `.dockerignore` (`oa-sync-template`).
|
|
27
|
+
|
|
28
|
+
### Fixed — šablona `jest.config.js` má `testTimeout` 120 000 ms (d.580)
|
|
29
|
+
|
|
30
|
+
30 s na sdíleném dev stroji (load 47–94, běžci víc služeb) shazovalo `beforeAll` sad, které samostatně projdou (BIZ-converter);
|
|
31
|
+
limit má chytat zaseknutý test, ne frontu na procesor. `maxWorkers: 1` beze změny (konf `biz-memory-limits` 001). Řádek F-JEST
|
|
32
|
+
generovaný → služby přegenerují `jest.config.js`.
|
|
33
|
+
|
|
34
|
+
### Removed — koncept `mockInfrastructure` (d.576)
|
|
35
|
+
|
|
36
|
+
Volba konstruktoru `CookbookTestRunner` i pole `test.mockInfrastructure` v receptu se odmítají JMÉNEM (hlášky s `Fix:`,
|
|
37
|
+
recept navíc se jménem souboru); `src/index.js` nepublikuje `MockMQClient`/`MockRegistry`/`MockStorage` ani `createMock*`
|
|
38
|
+
(surface 23 → 17 jmen). Krok se dispatchuje in-process proti vlastnímu v3 handleru, DB je skutečná — `this.mqClient`/
|
|
39
|
+
`this.registry` nikdo nečetl, mimo balíček 0 konzumentů (konf `declaration-removal` 001). Nahrazuje řádek „Documentation —
|
|
40
|
+
`mockInfrastructure` staví nápodobu MQ a registry" (d.521). DOPAD kaskády: recepty s tím polem (converter `ping.json`, meta 2,
|
|
41
|
+
hello 12) a volba v bootstrap testech (converter, ingest, hello, emailer) prevalidaci shodí, dokud služba pole neodstraní.
|
|
42
|
+
|
|
43
|
+
### Fixed — agregát běhu sčítá jen změřené hodnoty (d.576b)
|
|
44
|
+
|
|
45
|
+
`results.totalTests/passedTests/failedTests` přes `readStepMeasurement()`; `|| 0` byl zdroj neměřené nuly, kvůli které
|
|
46
|
+
odmítnutí generátoru (d.524) nikdy nevystřelilo. Změřená nula zůstává nulou. Smazán mrtvý `createEncodedProof` v testu.
|
|
47
|
+
|
|
48
|
+
### Fixed — throwaway schéma odmítne příkaz kvalifikovaný cizím schématem (d.538)
|
|
49
|
+
|
|
50
|
+
`<schema>.<tabulka>` jiného než throwaway schématu poslal příkaz testu do živého schématu (změřeno: řádek přistál v živé
|
|
51
|
+
tabulce). Jediná výjimka je read-only `information_schema` (22 živých migrací ve 4 repech). Úvodní `USE` se dál stripuje —
|
|
52
|
+
standard `repository-installation-sql-contract.md` o `USE` neříká nic; zpřísnění patří vlastníkovi standardu.
|
|
53
|
+
|
|
54
|
+
### Fixed — hlavičková brána instalačního kontraktu kryje i `database.seeds` mimo `migrations/**` (d.541)
|
|
55
|
+
|
|
56
|
+
Konf `installation-sql-contract-scope` 003: rozsah hlavičky je, co instalátor aplikuje. Deklarovaný chybějící seed =
|
|
57
|
+
nález, ne ENOENT. Změřeno nad 8 repy: žádné nezčervená (ingest opravil `bfd04b9`).
|
|
58
|
+
|
|
59
|
+
### Fixed — každá NOT RUN věta nese nápravu, padlý recept své jméno, `docsLintBridge.js` je zase text (d.523)
|
|
60
|
+
|
|
61
|
+
`biz-ci-gate.js` hlásil u odmítnutého receptu `step_id: undefined`; 5× `describeNotRun` a `runManifest` bez `Fix:` →
|
|
62
|
+
jeden vlastník `describeWorkspaceFix`; duplicitní blok a NUL v `docsLintBridge.js`; `uniformFiles.js` lepil druhý `Fix:`.
|
|
63
|
+
`biz-ci-gate.js` má mód 755 jako ostatní CLI (`bin` + shebang).
|
|
64
|
+
|
|
65
|
+
### Changed — validační důkaz píše výhradně `ValidationProofGenerator`, i na bootovací cestě (d.524)
|
|
66
|
+
|
|
67
|
+
Druhá kolej v `ValidationOrchestrator` mohla zapsat důkaz s `testsRun: 0`; jméno a verze validátoru se čtou z vlastního
|
|
68
|
+
`package.json` a nelze je přebít (`validatorVersion || '1.0.0'` pryč). Služba bez receptů v `tests/cookbooks/` validaci
|
|
69
|
+
neprojde (dřív psala důkaz, který registry stejně odmítl jako NO_TESTS) — všech 8 biz rep recepty má.
|
|
70
|
+
|
|
71
|
+
### Removed — `ValidationProofGenerator.createValidationError()` (d.524)
|
|
72
|
+
|
|
73
|
+
Bez konzumentů.
|
|
74
|
+
|
|
75
|
+
### Fixed — ctx Tier-1 běžce nese `step_id`, jako produkční `OperationContext` (d.549)
|
|
76
|
+
|
|
77
|
+
Content-resolver 4.0.1 `createDescriptor` bez `step_id` odmítá; producent tak mohl přejít na `ctx.step_id` až teď (BIZ-pdfgen).
|
|
78
|
+
|
|
79
|
+
### Documentation — balíčková kopie `shared.env` má čtenáře; zapsáno k otázce d.536 (d.557)
|
|
80
|
+
|
|
81
|
+
`renderTree` → `oa-sync-template template` → `templateMirror` drží zrcadlo `api/templates/business-service` byte za bytem; zrcadlo
|
|
82
|
+
čtou `biz-deploy-uniform-gate.bats:165` (kopie do fixtury), `redis-requirepass.bats:51,55,164` (kontrakt `REDIS_URL`) a
|
|
83
|
+
`shared-env-sync.bats`. d.536 ukončilo jen čtení VERDIKTEM (`G-SHARED-ENV` renderuje SSOT, `runNew` přepisuje živým renderem).
|
|
84
|
+
Soubor zůstává, šablona má dál 25 souborů.
|
|
85
|
+
|
|
86
|
+
### Added — řádky `S-UNIT-C` a `S-COOK-C`: každý běžcový skript šablony má svůj řádek (d.527)
|
|
87
|
+
|
|
88
|
+
Šablona nesla `test:container` a `test:cookbooks:container` bez řádku manifestu, converter měl `test:bootstrap/unit/integration/
|
|
89
|
+
all/cookbooks:container`, property žádný `*:container` — mapa vydání jmenovala příkaz, který ve službě neexistoval (BIZ-converter
|
|
90
|
+
nález 25). Šablona = výstup řádků: `test:unit:container` (`S-UNIT-C`), `test:cookbooks:container` (`S-COOK-C`) vedle `S-ALL-C`/`S-INT-C`;
|
|
91
|
+
výjimka pro běžcový skript bez řádku zrušena. Kaskáda: 5 služeb přejmenuje `test:container` → `test:unit:container`, hello a pdfgen doplní
|
|
92
|
+
`test:cookbooks:container`.
|
|
93
|
+
|
|
94
|
+
### Changed — env šablona služby nedeklaruje `SERVICE_NAME` (d.539)
|
|
95
|
+
|
|
96
|
+
Identitu vlastní `config/service/config.json` (`ServiceWrapper._serviceName()`, předává se do `MonitoringConnector.init({serviceName})`);
|
|
97
|
+
klíč v env nečetl nikdo, emailer a pdfgen bez něj běží (BIZ-emailer, BIZ-invoicing). Komentář k `MARIADB_MIGRATION_USER/PASSWORD` říká
|
|
98
|
+
hostitelský kontrakt (`env-active/<svc>.env` na boxu, konf `db-migrations-first-deploy` 001 fáze 1); README šablony říká, že F-JEST ruší
|
|
99
|
+
lokální `setupFiles` (env bere běžec z `env_file`).
|
|
100
|
+
|
|
101
|
+
### Changed — `oa-sync-template` chybějící blok `init.sh` vloží (d.552)
|
|
102
|
+
|
|
103
|
+
Řádek F-INIT jen hlídal existující blok a chybějící kázal opsat ručně (`BLOCKED … paste the block from the template once`, BIZ-invoicing);
|
|
104
|
+
hláška „udělej to ručně" u generovaného obsahu je defekt. `insertBlockAfterFunction` + `F-INIT.insert_after_function`: bez kotvy odmítne s `Fix:`.
|
|
105
|
+
|
|
106
|
+
### Removed — scaffold už nerenderuje `scripts/verify-deploy-uniform.sh` do služby (d.555)
|
|
107
|
+
|
|
108
|
+
Oba CI joby ho od d.529 volají z pinovaného balíčku; soubor v repu služby nečetl nikdo. `PACKAGE_ONLY` v renderu, zrcadlo
|
|
109
|
+
`api/templates/business-service/scripts/` smazáno; šablona má 25 souborů.
|
|
110
|
+
|
|
111
|
+
### Fixed — `GIT_CLONE_PATH` uniformního běhu má vlastní slot runneru (d.556)
|
|
112
|
+
|
|
113
|
+
`validate-uniform` běží na každém pipelinu; dva souběžné pipeliny na jednom runneru sdílely build adresář →
|
|
114
|
+
`$CI_BUILDS_DIR/oa-uniform/$CI_CONCURRENT_ID/api_biz/<svc>`.
|
|
115
|
+
|
|
116
|
+
### Added — job `validate-uniform` v generovaném bloku `oa-ci v1`: uniforma běží na každém pipelinu (d.529)
|
|
117
|
+
|
|
118
|
+
Konfirmace `biz-service-manifest` 010 (vlastník 2026-09-16): 008 říká, KDE brána musí být před nasazením, ne že
|
|
119
|
+
se jinde nepouští. Job `validate-uniform` (stage `test`, rules MR/main/devel/production) klonuje `api` a spouští
|
|
120
|
+
celou uniformu biz služby; `deploy-production` zůstává závaznou poslední instancí. `secret_detection` běží i na
|
|
121
|
+
`devel`, kam post-commit zrcadlo posílá každý commit (dosud `pipelines?ref=devel` = 0). `build` na `devel` záměrně
|
|
122
|
+
NEběží — 010 žádá kontrolu z každého commitu, ne obraz; `IMAGE_LATEST` z devel by přepsal `latest` platformy.
|
|
123
|
+
|
|
124
|
+
### Changed — oba běhy uniformy volají `verify-deploy-uniform.sh` z pinovaného balíčku (d.529)
|
|
125
|
+
|
|
126
|
+
`scripts/verify-deploy-uniform.sh` neexistoval v žádném z 8 biz repozitářů (jen v šabloně) → `deploy-production`
|
|
127
|
+
padal na prvním kroku `script:`. Oba joby ho volají z `node_modules/@onlineapps/conn-orch-validator/templates/
|
|
128
|
+
business-service/scripts/` — brána i engine z jednoho pinu, žádná kopie do 8 rep; klon `api` přes `$API_CHECKOUT`
|
|
129
|
+
nejde, skript ho sám maže. Rozvržení a runtime obou jobů deklaruje jednou skrytý klíč `.oa-uniform` (`extends`).
|
|
130
|
+
Řádek `G-CI`: `why` přepsáno na dnešní stav (šablona od d.470 nenese `verify-installation-contract:`), `doc` → 010.
|
|
131
|
+
|
|
132
|
+
### Changed — `G-SHARED-ENV` čte SSOT `api/config/shared-env.json` ve workspace, ne render zabalený v balíčku (d.536)
|
|
133
|
+
|
|
134
|
+
Ingest, emailer, hello, invoicing, pdfgen po dovydání 2: řádek porovnával s renderem zabaleným v 9.0.0 (d.229),
|
|
135
|
+
`oa-sync-template shared-env` renderoval z živého SSOT (d.500/d.510) → služba nemohla být zároveň „synced" i
|
|
136
|
+
DEPLOYABLE („10 line(s) differ"). Řádek renderuje SSOT týmž rendererem jako sync; bez dosažitelného workspace
|
|
137
|
+
NOT RUN s `Fix:` (v deploy jobu je `api` naklonované, 008). Kaskáda: každá biz služba po pinu spustí
|
|
138
|
+
`oa-sync-template readme-uniform --target .` (region README nese `from` řádku).
|
|
139
|
+
|
|
140
|
+
### Changed — `oa-validate .` odvozuje kořen workspace od kořene služby (d.540)
|
|
141
|
+
|
|
142
|
+
Z `<workspace>/api_biz/<svc>` bez `--workspace` hlásil validator instalovaný v `node_modules` služby
|
|
143
|
+
`Workspace root: NOT RESOLVED` (kořen hledal jen od balíčku) → U-*/D-* NOT RUN. Třetí otázka: nejbližší předek
|
|
144
|
+
kořene služby s `api/config/services.json`; explicitní `--workspace` dál vyhrává.
|
|
145
|
+
|
|
146
|
+
### Fixed — F-RUNNER porovnává směrem render; zpětná substituce jména služby zrušena (d.531)
|
|
147
|
+
|
|
148
|
+
`normalizeRunnerBlock` nahrazovala jméno služby v bloku zpět na `__SERVICE_NAME__`, takže u služby jménem `meta`
|
|
149
|
+
přepsala i literál v komentáři šablony (`api_biz/meta/docker-compose.yml carries the full numbers`) a řádek hlásil
|
|
150
|
+
nález, zatímco `oa-sync-template docker-compose.yml --check` říkal `unchanged`. Jedna kolej = referenci vyrenderovat
|
|
151
|
+
jménem služby a porovnat (`renderRunnerIdentity`); `normalizeRunnerBlock` smazána (jediný čtenář byl tento řádek).
|
|
152
|
+
|
|
153
|
+
### Changed — důkaz validace odmítá neměřenou nulu; kontrakt odmítá `db: true` bez bloku `database` (d.521)
|
|
154
|
+
|
|
155
|
+
`ValidationProofGenerator.generateProof()` čte `durationMs`, `testsRun`, `testsPassed`, `testsFailed` z agregátu
|
|
156
|
+
runneru JMÉNEM a chybějící měření odmítne místo doplnění `0`; běh, který nic nespustil (`testsRun === 0`), je
|
|
157
|
+
odmítnut u autora, ne až v registru (`ValidationProofCodec.decode()` = NO_TESTS). Integrační kontrakt odmítá
|
|
158
|
+
`requiredConnectors.db: true` bez bloku `database` — směr, který přechodová výjimka F4 nechala otevřený
|
|
159
|
+
(shoda hotová: 7/8 služeb má obojí, pdfgen ani jedno, 0 repozitářů nese `ci-setup-db.js`).
|
|
160
|
+
|
|
161
|
+
### Removed — `ValidationProofGenerator.extractTestSummary()` (d.521)
|
|
162
|
+
|
|
163
|
+
Nula konzumentů od 98d155f1 (2025-09-30); jediné pole nad agregátem, `coverage`, na platformě nic neměří.
|
|
164
|
+
|
|
165
|
+
### Documentation — `mockInfrastructure` staví nápodobu MQ a registry, databázi ne (d.521)
|
|
166
|
+
|
|
167
|
+
README § „What `mockInfrastructure` covers — and what it does not": `run-prevalidation` běží proti skutečnému
|
|
168
|
+
schématu každé služby, která ho deklaruje, a patří až za `ci:gate:setup`; pokrytou množinu připíná test.
|
|
169
|
+
|
|
170
|
+
### Fixed — každá NOT RUN věta nese svou nápravu, každý padlý záznam svou identitu (d.516, d.516b, d.518)
|
|
171
|
+
|
|
172
|
+
Jediný vlastník věty `Fix: run with --workspace pointing at a checkout that carries …` je
|
|
173
|
+
`manifest/workspaceRoot.js` § `describeWorkspaceFix`; berou ji `docsLintBridge` (D-PORT, D-RETIRED, D-LINT),
|
|
174
|
+
`libraryWorkspace.js` § `notRunBecause` (U-ORPHAN, U-MISMATCH, L-PINS, L-CONSUMER, L-TOOLING) a `readmeRegion.js`
|
|
175
|
+
(L-README-REGION). `X-IGNORED` nad stromem bez `.git` jmenuje vlastní nápravu — běh nad klonem, ne nad exportem.
|
|
176
|
+
`results.steps` runneru nese dva druhy záznamů (`kind: step` / `cookbook-load-failure`): odmítnutý recept se hlásí
|
|
177
|
+
jako recept (soubor + chyba), krok bez `step_id` je chyba §5, `validateCookbook` vyžaduje `step_id` jako cookbook-core 5.0.0.
|
|
178
|
+
|
|
179
|
+
### Changed — kontrola se scope vyžadujícím workspace vlastní svou NOT RUN větu (d.518)
|
|
180
|
+
|
|
181
|
+
`runManifest.js` už nepůjčuje výchozí větu „the workspace root is not reachable"; kontrola bez `describeNotRun`
|
|
182
|
+
běh odmítne na každém běhu. Na výchozí větu nedosahovala žádná registrovaná kontrola (`automation-gates.md` §5).
|
|
183
|
+
|
|
184
|
+
### Fixed — `results.steps` říká, co každý záznam je; krok bez `step_id` se neobejde pojmenováním (d.516b)
|
|
185
|
+
|
|
186
|
+
`results.steps` nese dva druhy záznamu a nejsou to oba kroky: výsledek kroku, a záznam, který
|
|
187
|
+
`CookbookTestRunner.runCookbooks` uloží za recept, jejž formátová kontrola odmítla — celý recept, který
|
|
188
|
+
žádný krok nevydal. Splývaly, takže odmítnutý soubor hlásil krok, který neexistuje:
|
|
189
|
+
`cookbook "broken.json" step "step #1": … cookbook format version is missing`. Každý záznam teď svůj druh
|
|
190
|
+
**deklaruje** (`kind: 'step'` / `kind: 'cookbook-load-failure'`) tam, kde vzniká, a nikdo ho nedovozuje
|
|
191
|
+
z chybějícího pole (`architecture-principles.md` §8). Nenačtený recept se hlásí jménem souboru:
|
|
192
|
+
`cookbook "broken.json" could not be run: …`.
|
|
193
|
+
|
|
194
|
+
Teprve na tom stojí druhá polovina: `utils/stepFailure.js` § `describeStepIdentity` **odmítne** záznam
|
|
195
|
+
kroku bez `step_id` místo aby ho pojmenoval pozicí (`step #3 (operation: convert)`). Ta náhrada byla
|
|
196
|
+
správná odpověď, dokud se tvar usazoval — alternativou bylo `undefined`. Dnes je `step_id` povinné od
|
|
197
|
+
`@onlineapps/cookbook-core` 5.0.0 a orchestrátor od d.460 odmítne task krok bez operace
|
|
198
|
+
(`_requireStepOperation`), takže krok bez `step_id` je vadný recept a pravděpodobné jméno ho čte jako
|
|
199
|
+
v pořádku (§3). Pozice zůstává v hlášce — jako to, čím se vadný krok najde, ne jako jeho jméno (§5).
|
|
200
|
+
|
|
201
|
+
`CookbookTestRunner.validateCookbook` nově žádá `step_id` jako první ze tří polí, která cookbook-core 5.0.0
|
|
202
|
+
u task kroku vyžaduje; tím zmizel i `Step ${step.step_id || 'unknown'}` z hlášek o `service`/`operation` —
|
|
203
|
+
případ, který zastupoval, už nenastane. Ověřeno pozitivní kontrolou nad 43 ostrými recepty
|
|
204
|
+
(`api/templates/business-service` + `api_biz/*/tests/cookbooks`): žádný krok bez `step_id`.
|
|
205
|
+
|
|
206
|
+
### Fixed — NOT RUN „workspace není dosažitelný" nese týž Fix (d.516b)
|
|
207
|
+
|
|
208
|
+
`checks/docsLintBridge.js` § `describeNotRun` (obě kontroly) končil u toho, že workspace není — druhý kanál
|
|
209
|
+
vedle toho, který zavřela d.516, a týž nedostatek (`automation-gates.md` §1 požadavek 4). Věta pochází
|
|
210
|
+
z téhož vlastníka, `workspaceRoot.js` § `describeWorkspaceFix`. Ostatní `describeNotRun` (`readmeRegion.js`,
|
|
211
|
+
`libraryWorkspace.js`) a výchozí hláška v `runManifest.js` Fix stále nenesou — nahlášeno, neopraveno.
|
|
212
|
+
|
|
213
|
+
### Fixed — most k dokumentačnímu lintu píše u NOT RUN týž Fix jako chybějící kořen (d.516)
|
|
214
|
+
|
|
215
|
+
`checks/docsLintBridge.js` skládal větu NOT RUN z vlastního textu a končil tam, kde skončil linter:
|
|
216
|
+
`F002:http-ports could not be decided — api_biz/*/docker-compose.yml lives in a sibling checkout this run
|
|
217
|
+
does not have, so the probe could not be evaluated`. Pravda, a nic, co může čtenář udělat — přitom ve
|
|
218
|
+
**stejném běhu** a o **témže chybějícím adresáři** řekl `U-ORPHAN` příkaz (`automation-gates.md` §1
|
|
219
|
+
požadavek 4). Dvě věty pro jednu nápravu jsou druhá kolej (`change-discipline.md` § One rail per concern).
|
|
220
|
+
|
|
221
|
+
Příkaz má teď jednoho vlastníka, `workspaceRoot.js` § `describeWorkspaceFix`; `runManifest.js`
|
|
222
|
+
§ `describeMissingRoots` (d.511) i obě kontroly mostu (`D-PORT`/`D-RETIRED`/`D-LINT`) berou větu odtud.
|
|
223
|
+
Co musí checkout nést, zůstává na volajícím: řádek své kořeny deklaruje a jmenuje, kdežto most dostává
|
|
224
|
+
text od linteru, jehož kanál `skipped` nese jen `{ rule, reason }` (`api/scripts/ci/lint-biz-docs.mjs`
|
|
225
|
+
§ `markSkipped`) — parsovat tu větu by byl soukromý dialekt mezi řádkem a nástrojem, jmenovat sourozence
|
|
226
|
+
zde by z mostu udělalo druhého vlastníka konfigurace prób. Měřeno nad `git archive HEAD` do adresáře bez
|
|
227
|
+
`api_biz`; kontrolní případ: nad workspace, který `api_biz` nese, nejde žádný `D-*` řádek do NOT RUN.
|
|
228
|
+
|
|
229
|
+
### Fixed — `runPreValidation` nehlásí padlý krok pod jménem jeho operace (d.516)
|
|
230
|
+
|
|
231
|
+
`utils/preValidation.js` skládal seznam padlých kroků jako `step_id: step.step_id || step.operation`, takže
|
|
232
|
+
krok bez `step_id` dorazil ke čtenáři výsledku pod **jménem operace** — pole se jmenuje `step_id` a neslo
|
|
233
|
+
něco, co jím není, bez jakékoli stopy po záměně (`architecture-principles.md` §3). Od
|
|
234
|
+
`@onlineapps/cookbook-core` 5.0.0 je `step_id` povinné (`schemas/cookbook.v2.schema.json`
|
|
235
|
+
definitions.TaskStep.required jmenuje step_id, type, service, operation) a od d.460 orchestrátor odmítne
|
|
236
|
+
task krok, který nejmenuje operaci (`_requireStepOperation`), takže krok bez `step_id` je vadný recept —
|
|
237
|
+
a vadný recept má výsledek ukázat, ne ho přejmenovat. Kontrolní případ: krok s oběma poli hlásí své
|
|
238
|
+
vlastní `step_id` beze změny.
|
|
239
|
+
|
|
240
|
+
### Fixed — NOT RUN chybějícího sourozence nese svůj Fix (d.511)
|
|
241
|
+
|
|
242
|
+
`describeMissingRoots` (`src/manifest/runManifest.js`) hlásil, CO chybí, a nikdy CO s tím; věta s příkazem
|
|
243
|
+
se tiskla jen u čistého verdiktu (`report.js` § `describeClearOutcome`), takže běh, který zároveň něco
|
|
244
|
+
našel, Fix neukázal nikde. Příkaz je odvozen z chybějících kořenů. Měřeno nad exportem
|
|
245
|
+
`api_biz/hello-service` vedle klonu api bez `api_biz/`; v rozvržení deploy brány (`<root>/api_biz/<služba>`
|
|
246
|
+
vedle `<root>/api`) je `notRun` prázdné — U-ORPHAN i R-NODE se rozhodnou (R-NODE i bez `api_biz`, d.238).
|
|
247
|
+
|
|
248
|
+
### Added — úplnost manifestu proti šabloně v obou směrech (d.511, nález 18)
|
|
249
|
+
|
|
250
|
+
`tests/unit/templateCoverage.test.js` žádal řádek nebo třídu `own` pro každý soubor šablony; opačný směr
|
|
251
|
+
mlčel — `describeFromProblem` kontroluje tvar reference `from:`, nikdy existenci souboru, takže přejmenovaný
|
|
252
|
+
soubor šablony nechal balíček zelený a spadl až v cizím repu (`[ManifestDiscovery] Packaged file not found`).
|
|
253
|
+
Nově každá `from: { package }` jmenuje soubor, který balíček nese, a každý `files.own.allowed` má v šabloně
|
|
254
|
+
něco za sebou. Rozdíl obou množin je dnes nulový — bez baseline, bez výjimky.
|
|
255
|
+
|
|
256
|
+
### Fixed — `sharedEnv.js` neslibuje kontrolu pole `consumers`, kterou nic nedělá (d.510)
|
|
257
|
+
|
|
258
|
+
Komentář nad `renderSharedEnv` tvrdil, že kdo klíč čte, je „fakt, který kód vlastní a kontrola
|
|
259
|
+
měří". Neměří: pole `keys[].consumers` nečte žádný kód tohoto balíčku (`grep -rn consumers src/`
|
|
260
|
+
vrací jen `MockMQClient` a jednu větu komentáře) a žádná brána jinde — manifest
|
|
261
|
+
`api/config/shared-env.json` to sám říká od d.505 (`_consumers`: „NOTHING measures it").
|
|
262
|
+
Slib mechanismu, který neexistuje, je přesně vada z `doc-code-binding.md` §5: odstavec se čte
|
|
263
|
+
jako krytý, takže se nikdo nepodívá.
|
|
264
|
+
|
|
265
|
+
Komentář teď říká obě poloviny pravdivě: **měřená** je jen ta, že se `consumers` nerenderuje —
|
|
266
|
+
kontrolní případ v `tests/unit/sharedEnv.test.js` polem hne a tvrdí, že vykreslený text se
|
|
267
|
+
nehne; obsah pole drží **review**; a strojová odpověď na „kdo tento název čte" je per služba,
|
|
268
|
+
řádek `C-ENV-READS` (check `env-contract`), který porovnává názvy čtené kódem služby s jejím
|
|
269
|
+
`config/service/integration-contract.json`. Renderer se nezměnil o řádek.
|
|
270
|
+
|
|
271
|
+
### Changed — `LOG_LEVEL` v zabalené šabloně říká, kdo ho čte a kdo ne (d.510)
|
|
272
|
+
|
|
273
|
+
Klíč nese komentář „the log level an infra service's config/logging.json resolves through
|
|
274
|
+
`${LOG_LEVEL}`" — pravdivý o infrastruktuře, mlčící o biz řetězci, kde ho **nečte nikdo**:
|
|
275
|
+
v `shared/*/src` je 66 čtení `process.env` a ani jedno tohoto názvu, `@onlineapps/monitoring-core`
|
|
276
|
+
nečte prostředí vůbec (princip 1) a úroveň bere z konfigurace, kterou dostane. Čtenář biz
|
|
277
|
+
`shared.env` tak mohl klíč přenastavit a čekat účinek, který mít nemůže.
|
|
278
|
+
|
|
279
|
+
Klíč zůstává v jedné sdílené sadě — každá kopie je bajtově shodná s platformní šablonou
|
|
280
|
+
(konfirmace `biz-service-manifest` 003 §18, akceptace bod 4), takže odebrat ho jen biz nositelům
|
|
281
|
+
by znamenalo druhou sadu, tedy změnu konceptu, ne opravu věty. Opravena je věta: `why` nově
|
|
282
|
+
jmenuje infrastrukturní kolej i to, že v biz řetězci je klíč **nesen, ne čten**, a proč tam
|
|
283
|
+
přesto je. `consumers` je srovnán s měřením (přibyly `api_monitoring` a `api_meta_reader`, které
|
|
284
|
+
`LOG_LEVEL` čtou — `src/consumer/config/logging.json`, `src/config.js`).
|
|
285
|
+
|
|
286
|
+
Dopad na konzumenty: vykreslený komentář klíče se změnil, takže `oa-validate` nad biz službou,
|
|
287
|
+
která svůj `shared.env` nepřegenerovala, nahlásí `G-SHARED-ENV`. Náprava je týž jeden běh jako
|
|
288
|
+
u d.500: `npx oa-sync-template shared-env --target .`.
|
|
289
|
+
|
|
290
|
+
### Fixed — `oa-sync-template` neplánuje řádky, ze kterých nemá co renderovat (d.507)
|
|
291
|
+
|
|
292
|
+
`npx oa-sync-template --target . --check` končil v každém biz repu dvěma řádky, které nešlo
|
|
293
|
+
vyřešit: `NOT RUN G-PROD-IMAGE …` a `NOT RUN G-SETUP docs/80-setup/ - the row declares no
|
|
294
|
+
"from" reference`. Oba řádky manifestu žádnou `from:` referenci nedeklarují, protože to nejsou
|
|
295
|
+
soubory renderované z reference — `G-PROD-IMAGE` je požadavek NA obsah souboru (pin digestem),
|
|
296
|
+
`G-SETUP` požadavek na existenci adresáře; odpovídá na ně běh manifestu (`npx oa-validate`).
|
|
297
|
+
Hlášení, se kterým čtenář nemůže nic udělat, je falešná záruka (`automation-gates.md` §5) a
|
|
298
|
+
hláška bez `Fix` (§1 požadavek 4).
|
|
299
|
+
|
|
300
|
+
Množina řádků synchronizace se nově bere podle toho, co manifest už dnes rozlišuje: řádek
|
|
301
|
+
s `from:` referencí je soubor, který běh renderuje (`syncRows`), řádek bez ní se neplánuje
|
|
302
|
+
vůbec. Rozhoduje reference, ne seznam id — nový požadavkový řádek tedy nevyžaduje změnu kódu.
|
|
303
|
+
`uniformRows` zůstává celou deklarací tříd `identical`/`generated`/`contains`, takže CLI umí
|
|
304
|
+
odmítnout `docs/80-setup/` jako požadavek (se jménem řádku a během, který na něj odpovídá), ne
|
|
305
|
+
jako překlep.
|
|
306
|
+
|
|
307
|
+
`NOT RUN` zůstává pro svůj jediný případ: řádek, který běh renderovat MÁ a nedosáhne na svou
|
|
308
|
+
referenci (reference do workspace, běh mimo workspace) — nově i s `Fix: … --workspace <root>`.
|
|
309
|
+
Chování řádků s referencí se nemění (kontrolní případ v `tests/unit/uniformFilesSync.test.js`).
|
|
310
|
+
|
|
311
|
+
Dopad na konzumenty: výstup `--check` nad konformním repem je o dva řádky kratší a neobsahuje
|
|
312
|
+
žádné `NOT RUN`; `oa-sync-template docs/80-setup/ --target .` nově končí exit 2 s vysvětlením
|
|
313
|
+
místo NOT RUN.
|
|
314
|
+
|
|
315
|
+
### Changed — zabalená šablona `shared.env` nese dvě meze souborového logu (d.500)
|
|
316
|
+
|
|
317
|
+
`@onlineapps/monitoring-core` 3.0.0 vyžaduje `file.maxSize` a `file.maxFiles` bez defaultu
|
|
318
|
+
v kódu (`src/logger.js` § `REQUIRED_FILE_BOUNDS`) — služba, která je nedeklaruje, spadne při
|
|
319
|
+
konstrukci loggeru. Hodnoty rozhodl vlastník: `LOG_MAX_SIZE_BYTES=52428800`, `LOG_MAX_FILES=10`
|
|
320
|
+
(`api/docs/governance/confirmations/log-file-bounds.md` 001). Klíče přibyly do manifestu
|
|
321
|
+
`api/config/shared-env.json`, který je vlastníkem klíčové sady, a tím i do zabalené kopie
|
|
322
|
+
`templates/business-service/config/env-templates/shared.env`, kterou čte řádek `G-SHARED-ENV`.
|
|
323
|
+
|
|
324
|
+
Dopad na konzumenty: `oa-validate` nad biz službou, která klíče ve svém `shared.env` nemá,
|
|
325
|
+
nahlásí `G-SHARED-ENV`. Náprava je jeden běh: `npx oa-sync-template shared-env --target .`.
|
|
326
|
+
|
|
327
|
+
### Added — `resolveMigrationPlan` na veřejném API balíčku (d.492)
|
|
328
|
+
|
|
329
|
+
Migrační plán (které `.sql` soubory tvoří množinu a v jakém pořadí) byl dostupný jen z vnitřní
|
|
330
|
+
cesty `@onlineapps/conn-orch-validator/src/utils/setupDatabase`. Cesta dovnitř balíčku není
|
|
331
|
+
kontrakt: každý přesun v `src/utils/` rozbije konzumenta, který na nic takového nepřistoupil.
|
|
332
|
+
Funkce je nově na `src/index.js` jako **tatáž** funkce (test `toBe` proti vnitřnímu modulu), ne
|
|
333
|
+
obal — jedna definice, jedno chování (`change-discipline.md` § One rail per concern). Množina
|
|
334
|
+
exportů se jinak nemění; kontrolní případ v `tests/unit/indexExports.test.js` porovnává celý
|
|
335
|
+
seznam klíčů se snímkem před změnou.
|
|
336
|
+
|
|
337
|
+
Biz repa mají přejít na veřejnou cestu `require('@onlineapps/conn-orch-validator')`; přechod
|
|
338
|
+
v jednotlivých repech patří jejich vláknům (vnitřní cestou dnes importují
|
|
339
|
+
`api_biz/converter/tests/integration/integrationEnv.js` a tři soubory v `api_biz/emailer/tests/`).
|
|
340
|
+
|
|
341
|
+
### Fixed — brána test-coverage hlásila PASS nad prázdnou množinou testů (d.486, nález d.205)
|
|
342
|
+
|
|
343
|
+
Prázdný match je jestí exit 0 bez výstupu a každé porovnání brány iteruje množinu, takže nad
|
|
344
|
+
prázdnou nenašlo protipříklad („0 file(s) matched, 0 run by the test:all chain"). Totéž o krok
|
|
345
|
+
níž — krok řetězu `test:all` mířící do prázdného adresáře. Obojí je nález `TEST_SET_EMPTY` se
|
|
346
|
+
jménem skriptu i vzoru; hlásí se jen tam, kde je kořenem (prázdné T a `TEST_NOT_MATCHED` umlčují
|
|
347
|
+
kontrolu jednotlivých kroků). `TEST_COVERAGE_SCOPE` nové měření jmenuje.
|
|
348
|
+
|
|
349
|
+
### Fixed — R6 odmítá `^`/`~`/`latest` v každé `@onlineapps/*` závislosti, i biz-only (d.485)
|
|
350
|
+
|
|
351
|
+
Kontrola exaktnosti pinu (`libCompat.js`) seděla uvnitř větve `gated`, takže balíček, který
|
|
352
|
+
žádná infra služba neinstaluje, mohl plavat pod zelenou branou (W413). Zúžení podle
|
|
353
|
+
`infraConsumed` dál rozhoduje jen o tom, co se porovnává s infra verzí; exaktní pin platí pro
|
|
354
|
+
každou `@onlineapps/*` závislost bez výjimky (`architecture-principles.md` § Version pinning).
|
|
355
|
+
Hláška je pro gated i biz-only jedna a nese `Fix: npm install <pkg>@<verze> --save-exact`;
|
|
356
|
+
kontrola existence v SSOT předchází kontrole exaktnosti, aby `Fix:` mohl verzi jmenovat.
|
|
357
|
+
|
|
358
|
+
### Added — pravidlo `S010`: invertované tvrzení v bats netvrdí nic (d.482)
|
|
359
|
+
|
|
360
|
+
`lintScripts` čte nově i **kódové** řádky testů a hlásí příkaz s invertovaným návratovým kódem
|
|
361
|
+
ve dvou tvarech, které bats nese: `! cmd` samostatně a `cmd || ! cmd`. Změřeno na bats 1.13.0:
|
|
362
|
+
takový příkaz je vyjmut z `errexit`, takže pod `set -e` **nezpůsobí pád testu**, pokud zrovna
|
|
363
|
+
není posledním příkazem těla — řádek vypadá jako tvrzení a tvrzením je jen náhodou polohy, kterou
|
|
364
|
+
libovolný vložený řádek pod ním tiše zruší. Pravidlo proto hlásí **každý** výskyt a nerozlišuje
|
|
365
|
+
poslední příkaz. Oprava je podmíněný tvar, který návratový kód spotřebuje záměrně a řekne, co našel
|
|
366
|
+
(`if <co nesmí platit>; then echo "[ctx] problem - found: …" >&2; return 1; fi`); `if ! cmd; then … fi`
|
|
367
|
+
je právě ta oprava, ne vada, a nehlásí se. Brána přistává nad již čistým rozsahem — 0 nálezů
|
|
368
|
+
ve 146 souborech, 32 výskytů platformy přepsáno předem — bez baseline a bez skip flagu
|
|
369
|
+
(`automation-gates.md` §3). Norma: `api/docs/standards/SCRIPTS-STANDARD.md` § Enforcement.
|
|
370
|
+
|
|
371
|
+
### Changed — rozsah citací je `tests/**`, ne jen `tests/scripts/` (d.482)
|
|
372
|
+
|
|
373
|
+
`CITATION_SCOPE` je nově `tests` (rekurzivně; přípony `.bats`/`.bash`/`.sh` beze změny), a platí pro
|
|
374
|
+
`S009` i `S010`. Adresář, ve kterém se `S009` narodilo, není jediný, který testy drží: mimo něj leží
|
|
375
|
+
12 shellových souborů (`tests/scripts-docker`, `tests/e2e/helpers`, `tests/fixtures/…`). Pravidlo, které
|
|
376
|
+
čte jeden adresář a sousední ne, má díru, kterou nikdo nevidí — běh ohlásí `0 finding(s)` a nikdy neřekne,
|
|
377
|
+
které soubory neotevřel (`automation-gates.md` §5). Rozsah byl před rozsířením změřen čistý pro obě
|
|
378
|
+
pravidla, takže ani zde není baseline. Jméno konstanty se nemění — exportuje ji CLI do svých hlášek.
|
|
379
|
+
|
|
380
|
+
## [9.0.0] — 2026-09-15
|
|
381
|
+
|
|
382
|
+
### Removed — šablona už nenese job `verify-installation-contract` (d.470)
|
|
383
|
+
|
|
384
|
+
Blok `oa-ci v1` v `templates/business-service/.gitlab-ci.yml` deklaroval job, který pouštěl
|
|
385
|
+
`sh scripts/verify-installation-docs-sql-contract.sh`. Šablona ten skript **nikdy nenesla**
|
|
386
|
+
(`templates/business-service/scripts/` = jen `verify-deploy-uniform.sh`) — osm biz repozitářů mělo
|
|
387
|
+
každý vlastní kopii a mapa vydání d.320 ruší všech osm. Job v bloku tedy sliboval kontrolu, kterou
|
|
388
|
+
nově nascaffoldovaná služba nemůže provést (`automation-gates.md` §5).
|
|
389
|
+
|
|
390
|
+
Norma se nikam neztratila, jen má jednu kolej místo dvou: `install-contract` je ve validatoru
|
|
391
|
+
(`src/utils/installContract.js`) a manifest ji vymáhá řádky `G-SETUP`, `D-DB-PACKAGE` a
|
|
392
|
+
`D-DB-HEADERS`, které běží v uniformě před SSH krokem téhož deploy jobu (konfirmace
|
|
393
|
+
`biz-service-manifest` 008) — a jako podpříkaz `biz-ci-gate verify-install-contract`.
|
|
394
|
+
|
|
395
|
+
### Changed — test job šablony nedělá `REGISTRY_URL` (d.470)
|
|
396
|
+
|
|
397
|
+
`test:` (mimo značky, výchozí job nové služby) deklaroval `REGISTRY_URL: "http://localhost:33100"`.
|
|
398
|
+
Nic, co ten job spouští, ho nečte: `test:ci` je `jest`, `jest.config.js` matchuje
|
|
399
|
+
`**/tests/**/*.test.js` a jediný test šablony požaduje `src/handlers/v3/echo.js`. Klíč byl HTTP
|
|
400
|
+
adresou registru pro `getService()`; konfirmace `biz-discovery-redis` 001 přesunula čtení na Redis
|
|
401
|
+
projekci a `725b25c2` HTTP volání odstranil. Čtyři otázky před rušením deklarace jsou zodpovězeny
|
|
402
|
+
v `api/docs/governance/confirmations/declaration-removal.md` 001. Deklarace klíče v
|
|
403
|
+
`config/env-templates/shared.env` se netýká — tu vlastní `api/config/shared-env.json`.
|
|
404
|
+
|
|
405
|
+
### Changed — deploy job migruje jen tam, kde fáze 1 proběhla (d.477)
|
|
406
|
+
|
|
407
|
+
Krok migrací dělal `touch "$TRACKER"` a poté aplikoval vše, co tracker neznal — na boxu, kde
|
|
408
|
+
fáze 1 nikdy neběžela, by tak deploy aplikoval **celou řadu sám**. Konfirmace
|
|
409
|
+
`api/docs/governance/confirmations/db-migrations-first-deploy.md` 001 dělí práci na dvě fáze a
|
|
410
|
+
první z nich (schéma, účet a první běh téhož běžce ručně podle runbooku) nechává člověku.
|
|
411
|
+
|
|
412
|
+
Tracker `config/runtime/applied-migrations-<schema>.txt` je proto od teď **precondition**, ne
|
|
413
|
+
výstup: chybí-li, job končí fail-fast hláškou `[deploy] Migrations tracker <cesta> missing -
|
|
414
|
+
phase 1 … has not run on this box` a jmenuje runbook `api/docs/setup/INSTALL.md`. Žádný `touch`,
|
|
415
|
+
žádné `mkdir` — krok nezakládá nic, stejně jako nezakládá schéma ani účet. Prázdný tracker
|
|
416
|
+
zůstává platným stavem (fáze 1 bez přenesených souborů). `docs/80-setup/INSTALL.md` šablony
|
|
417
|
+
§ Migrations at deploy time to říká třetí odrážkou.
|
|
418
|
+
|
|
7
419
|
## [8.1.0] — 2026-09-15
|
|
8
420
|
|
|
9
421
|
### Changed — deploy job šablony aplikuje migrace DB mezi `pull` a `up` (d.421)
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ This is **NOT** a development testing tool. This is a **production validation or
|
|
|
23
23
|
2. **Validates configuration** - `config.json`, `operations.json` and `integration-contract.json`, through the manifest rows that own them
|
|
24
24
|
3. **Validates the environment contract** - every `env.required` name is set
|
|
25
25
|
4. **Validates operations** - the v3 handler-registry rules
|
|
26
|
-
5. **Validates business logic** - cookbook tests
|
|
26
|
+
5. **Validates business logic** - cookbook tests against the two mocked doubles named below
|
|
27
27
|
6. **Validates connector integration** - the two declarations agree and the environment backs them
|
|
28
28
|
7. **Generates validation proof** - SHA256 proof carried into registration
|
|
29
29
|
|
|
@@ -58,7 +58,7 @@ runs Tier-1 validation in phase 0.2 — before MQ connects, before registration.
|
|
|
58
58
|
sentences of its own, and the same defect was reported twice
|
|
59
59
|
3. **Environment Contract** - every variable the contract declares `env.required` is set
|
|
60
60
|
4. **Operations Compliance** - every operation declares `handler`, `bundle_scope`, `input`, `output`, and none carries a retired v2 field (`endpoint`, `method`, `path`); a missing `description` is a warning
|
|
61
|
-
5. **Cookbook Tests** - business logic + integration (
|
|
61
|
+
5. **Cookbook Tests** - business logic + integration; every step is dispatched in-process, with no transport, and against the service's real database (see below)
|
|
62
62
|
6. **Connector Integration** - the connector declarations agree and the environment backs them
|
|
63
63
|
7. **Manifest conformance** - the repository against the uniform manifest shipped in this package (see below)
|
|
64
64
|
|
|
@@ -70,6 +70,35 @@ signal saved to `ci/deployability.json`
|
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
73
|
+
## Pre-validation runs in-process — and against the real database
|
|
74
|
+
|
|
75
|
+
A cookbook step is dispatched **in this process**, against the service's own v3
|
|
76
|
+
handler, with no transport of any kind. There is nothing to mock: the ctx slots
|
|
77
|
+
are `null` (pinned by `tests/unit/CookbookTestRunner.ctxShape.test.js`), and a
|
|
78
|
+
handler that needs a schema reaches it the way it reaches it in production — by
|
|
79
|
+
importing the service's own database module. **That connection is real.**
|
|
80
|
+
|
|
81
|
+
`mockInfrastructure` — the option that once built a MockMQClient and a
|
|
82
|
+
MockRegistry for transport dispatch — is retired: the runner and the cookbook
|
|
83
|
+
format both refuse it by name (`tests/unit/mockInfrastructureRetired.test.js`).
|
|
84
|
+
|
|
85
|
+
What the real database requires is ORDER, and the contract is what makes the
|
|
86
|
+
order decidable:
|
|
87
|
+
|
|
88
|
+
- a service that needs a database declares **both** `requiredConnectors.db: true`
|
|
89
|
+
**and** the `database` block; the contract refuses either one standing alone,
|
|
90
|
+
in both directions;
|
|
91
|
+
- `setup-db` therefore builds a schema exactly where one is declared, and reports
|
|
92
|
+
`NOT APPLICABLE` — never `OK` — where none is;
|
|
93
|
+
- `run-prevalidation` (`npm run test:cookbooks`) comes **after** `ci:gate:setup`
|
|
94
|
+
in the job, because by then the schema its handlers will reach exists.
|
|
95
|
+
|
|
96
|
+
Run out of that order, or against a service whose schema was never built, the
|
|
97
|
+
cookbooks fail in the handler's own database error. That is the truthful
|
|
98
|
+
failure.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
73
102
|
## Environment contract (`env` block)
|
|
74
103
|
|
|
75
104
|
One declaration in `config/service/integration-contract.json`, two consumers:
|
|
@@ -373,6 +402,17 @@ the test precisely so that the next file cannot be exempted by editing a test
|
|
|
373
402
|
behind two files that had no row at all: `gitignore` (now `F-GITIGNORE`) and
|
|
374
403
|
`.gitlab-ci.yml` (now `G-CI`).
|
|
375
404
|
|
|
405
|
+
The same suite reads the other two directions, which were silent until d.511 and silent in
|
|
406
|
+
a worse way, because nothing reads a `from:` reference until a run needs it. Every
|
|
407
|
+
`from: { package }` reference the manifest makes must name a file this package carries:
|
|
408
|
+
`describeFromProblem` (`manifestShape.js`) checks a reference's SHAPE and never whether the
|
|
409
|
+
file is there, so a template file renamed or deleted left every suite green here and threw
|
|
410
|
+
`[ManifestDiscovery] Packaged file not found` later — inside whichever repository ran the
|
|
411
|
+
uniform next, a service's CI or a container at boot. And every `files.own.allowed` entry
|
|
412
|
+
must have something behind it in the template, so the class stays a decision about real
|
|
413
|
+
files rather than a list nobody re-derives. Both read the references through `collectRows`,
|
|
414
|
+
the manifest's own walk, so a row that moves into another block cannot fall out of them.
|
|
415
|
+
|
|
376
416
|
#### `.gitignore`: the `contains` class
|
|
377
417
|
|
|
378
418
|
`F-GITIGNORE` compares the ignore ENTRIES the packaged template declares against the
|
|
@@ -628,13 +668,32 @@ the directories it walks (`requiresSiblings({ row, block })`, derived from the r
|
|
|
628
668
|
patterns), and the runner verifies them before running it:
|
|
629
669
|
|
|
630
670
|
```
|
|
631
|
-
NOT RUN L-CONSUMER — sibling root api_biz is not present in this checkout
|
|
671
|
+
NOT RUN L-CONSUMER — sibling root api_biz is not present in this checkout - an absent
|
|
672
|
+
directory is not an empty one, so this row is not answered. Fix: run with --workspace
|
|
673
|
+
pointing at a checkout that carries api_biz.
|
|
632
674
|
```
|
|
633
675
|
|
|
634
676
|
Measured against a `git archive` export of this repository on 2026-09-09: without the gate,
|
|
635
677
|
`--library --all` raised a blocking `L-CONSUMER` on `conn-base-db` about files nobody
|
|
636
678
|
opened. Never a finding, never a pass (`automation-gates.md` §5).
|
|
637
679
|
|
|
680
|
+
The line carries its fix because of where it is read. Measured 2026-09-15 over a
|
|
681
|
+
`git archive` export of `api_biz/hello-service` placed beside an api clone with no
|
|
682
|
+
`api_biz/` around them: the reason ended at "is not present in this checkout", and the
|
|
683
|
+
report's own incomplete-run sentence — the one that does name the command — prints only on
|
|
684
|
+
a CLEAR verdict (`report.js` § `describeClearOutcome`), so a run that also had findings
|
|
685
|
+
named no fix anywhere. `automation-gates.md` §1 requirement 4 asks for the exact command,
|
|
686
|
+
and the sync half of this package already gave it (`src/sync/uniformFiles.js` § `planRow`).
|
|
687
|
+
The command is derived from the missing roots, so a row that starts reading a new sibling
|
|
688
|
+
needs no second edit.
|
|
689
|
+
|
|
690
|
+
In the layout the deploy gate demands — the service at `<root>/api_biz/<service>` beside
|
|
691
|
+
`<root>/api`, which `templates/business-service/.gitlab-ci.yml` asks GitLab for through
|
|
692
|
+
`GIT_CLONE_PATH` — nothing is skipped: measured the same day over that export, `notRun` is
|
|
693
|
+
empty and both `U-ORPHAN` and `R-NODE` decide. `R-NODE` left the NOT RUN list in d.238 and
|
|
694
|
+
decides even where `api_biz` is absent, because the platform major it reads is this
|
|
695
|
+
package's own `engines.node`.
|
|
696
|
+
|
|
638
697
|
One case is neither mode: a service root that does not lie under the given workspace root.
|
|
639
698
|
Filtering there would drop every finding and the empty table would read as "the row
|
|
640
699
|
looked and found nothing", so each row that needs the workspace — `workspace` and `bearer`
|
|
@@ -875,12 +934,17 @@ class — `src/**`, `tests/**`, the content of `docs/**` — are never written.
|
|
|
875
934
|
file, and since d.229 most of them read a file this package carries. The predicate is the
|
|
876
935
|
one the manifest run uses (`rowNeedsWorkspace`), so the `fix` command of `F-INIT`,
|
|
877
936
|
`F-JEST` and `F-RUNNER` can be typed where their finding is now raised: inside the service
|
|
878
|
-
image. A row that does need one is printed `NOT RUN` by name
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
`from:` reference, so nothing says what
|
|
883
|
-
|
|
937
|
+
image. A row that does need one is printed `NOT RUN` by name with the `--workspace` fix,
|
|
938
|
+
never skipped in silence.
|
|
939
|
+
|
|
940
|
+
A row the manifest does not make renderable is **not a row of this run**. Today that is
|
|
941
|
+
`G-PROD-IMAGE` and `G-SETUP`: they declare no `from:` reference, so nothing says what
|
|
942
|
+
their content would be rendered from — the first is a requirement ABOUT a file, the second
|
|
943
|
+
a directory that must exist, and `oa-validate` is the run that answers both. Until d.507
|
|
944
|
+
the sync planned them and printed `NOT RUN`, which every `--check` in every repository
|
|
945
|
+
ended on: a line naming a state its reader could do nothing about, with no `Fix`
|
|
946
|
+
(`automation-gates.md` §5 and §1 requirement 4). Naming a requirement path as an argument
|
|
947
|
+
is refused by what it is, with the run that does answer it. A row whose file
|
|
884
948
|
blocks the write — an `init.sh` carrying no block marker, where inserting one would mean
|
|
885
949
|
choosing a position among somebody's own install steps; an installation document missing a
|
|
886
950
|
section, where writing one would mean rewriting somebody's prose — is printed `BLOCKED`
|
|
@@ -1107,6 +1171,16 @@ services/my-service/
|
|
|
1107
1171
|
```
|
|
1108
1172
|
|
|
1109
1173
|
**Proof Lifecycle:**
|
|
1174
|
+
- **Every number in it is a measurement.** `testsRun`, `testsPassed`,
|
|
1175
|
+
`testsFailed` and `durationMs` are read from the aggregate the runner returns,
|
|
1176
|
+
and a missing one is refused by name rather than filled with `0`: the same
|
|
1177
|
+
number would otherwise stand for both "measured, and it was zero" and "nobody
|
|
1178
|
+
measured this", with no way for a reader to tell them apart. A run that
|
|
1179
|
+
executed nothing — a service whose `tests/cookbooks/` holds no `.json` file —
|
|
1180
|
+
is refused outright: it has no failing step, so it used to publish a signed
|
|
1181
|
+
proof asserting a passing validation of zero tests, which
|
|
1182
|
+
`ValidationProofCodec.decode()` then refused at the registry as `NO_TESTS`,
|
|
1183
|
+
days later and far from the cause.
|
|
1110
1184
|
- **Written:** on every successful validation, i.e. on every boot. There is no
|
|
1111
1185
|
proof cache — the one that existed skipped steps 1-3 and 5-6 to save 6 ms and
|
|
1112
1186
|
bought a window of up to seven days in which validation asserted something no
|
package/docs/DESIGN.md
CHANGED
|
@@ -25,17 +25,31 @@ surface was removed together with the now-retired `ServiceValidator` /
|
|
|
25
25
|
- **Production-ready** — the exact same code runs locally, in CI and during
|
|
26
26
|
wrapper startup.
|
|
27
27
|
- **Fail-fast** — missing logger, missing operations.json: immediate throw.
|
|
28
|
-
`serviceUrl` is
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
`serviceUrl` is not among them because it is gone: it fed the retired
|
|
29
|
+
`/health` probe (ADR 0005), and neither `ValidationOrchestrator` nor
|
|
30
|
+
`CookbookTestRunner` reads, stores or documents it any more
|
|
31
|
+
(`tests/unit/ValidationOrchestrator.unit.test.js` § Constructor). Nor is one
|
|
32
|
+
passed: `ServiceWrapper._createValidationOrchestrator()` builds the
|
|
33
|
+
orchestrator from four options and this is not one of them
|
|
34
|
+
(`tests/unit/preValidation.test.js` § the runner is built with the service
|
|
35
|
+
identity and no retired options).
|
|
31
36
|
|
|
32
37
|
## Components
|
|
33
38
|
|
|
34
|
-
###
|
|
39
|
+
### Internal test doubles — not published
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
The package exports no infrastructure doubles. `mockInfrastructure`, the option
|
|
42
|
+
that built them, is retired (d.576): a cookbook step is dispatched in-process
|
|
43
|
+
against the service's own v3 handler, so there is no transport to stand in for
|
|
44
|
+
and the database a handler reaches is the real one
|
|
45
|
+
(`tests/unit/mockInfrastructureRetired.test.js`).
|
|
46
|
+
|
|
47
|
+
- `MockRegistry` — the registry stand-in of `helpers/createServiceReadinessTests`,
|
|
48
|
+
internal to the package
|
|
49
|
+
- `MockMQClient` — used by `tests/unit/RegistrationFlow.test.js` alone
|
|
50
|
+
|
|
51
|
+
A double with no consumer is not kept: `MockStorage` was deleted with its own
|
|
52
|
+
unit test in d.583 (`tests/unit/mockInfrastructureRetired.test.js`).
|
|
39
53
|
|
|
40
54
|
### Production Validation
|
|
41
55
|
|