@onlineapps/conn-orch-validator 12.1.1 → 13.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 +607 -0
- package/README.md +126 -19
- package/manifests/biz-service.manifest.json +15 -2
- package/manifests/library.manifest.json +4 -4
- package/package.json +11 -3
- package/src/CookbookTestRunner.js +275 -105
- package/src/CookbookTestUtils.js +79 -68
- package/src/ServiceReadinessValidator.js +42 -52
- package/src/ValidationOrchestrator.js +65 -44
- package/src/cli/biz-ci-gate.js +2 -2
- package/src/cli/oa-sync-template.js +97 -47
- package/src/cli/oa-validate.js +44 -10
- package/src/helpers/README.md +6 -6
- package/src/helpers/createServiceReadinessTests.js +87 -33
- package/src/index.js +14 -5
- package/src/lint/scripts/lintScripts.js +11 -4
- package/src/manifest/checks/libraryContext.js +6 -3
- package/src/manifest/checks/libraryDocs.js +174 -4
- package/src/manifest/checks/libraryTests.js +200 -19
- package/src/manifest/checks/scriptHeaders.js +6 -13
- package/src/manifest/checks/serviceConfig.js +36 -16
- package/src/manifest/checks/serviceConnectors.js +180 -2
- package/src/manifest/checks/serviceDb.js +0 -3
- package/src/manifest/checks/serviceScripts.js +3 -20
- package/src/manifest/runManifest.js +90 -13
- package/src/manifest/workspaceRoot.js +133 -4
- package/src/mocks/MockMQClient.js +2 -2
- package/src/sync/docsRegion.js +2 -2
- package/src/sync/readmeFile.js +30 -0
- package/src/sync/readmeLocation.js +2 -12
- package/src/sync/readmePointer.js +10 -4
- package/src/sync/serviceTemplate.js +9 -11
- package/src/sync/sharedEnv.js +59 -3
- package/src/sync/uniformFiles.js +81 -8
- package/src/utils/bizCiGateContract.js +2 -2
- package/src/utils/connectorContract.js +54 -2
- package/src/utils/cookbookFormat.js +25 -115
- package/src/utils/dbAccountGrants.js +5 -3
- package/src/utils/deployContract.js +153 -28
- package/src/utils/envContract.js +2 -2
- package/src/utils/handlerRef.js +8 -10
- package/src/utils/integrationRun.js +1 -1
- package/src/utils/operationsDocumentRules.js +242 -0
- package/src/utils/operationsRules.js +157 -0
- package/src/utils/resolveHeaders.js +12 -1
- package/src/utils/setupDatabase.js +1 -1
- package/src/utils/stepFailure.js +3 -3
- package/src/utils/stepReferences.js +28 -87
- package/src/utils/throwawaySchema.js +1 -1
- package/src/utils/yamlTopLevel.js +105 -0
- package/src/validators/ServiceStructureValidator.js +67 -152
- package/templates/business-service/.gitlab-ci.yml +203 -37
- package/templates/business-service/README.md +7 -4
- package/templates/business-service/config/env-templates/shared.env +1 -0
- package/templates/business-service/docs/80-setup/INSTALL.md +31 -3
- package/templates/business-service/docs/80-setup/PLATFORM_MATRIX.md +5 -2
- package/templates/business-service/src/config/index.js +15 -0
- package/TESTING_STRATEGY.md +0 -92
- package/jest.config.js +0 -37
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,613 @@ All notable changes to this package. Follows [Keep a Changelog](https://keepacha
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [13.0.0] — 2026-09-27
|
|
8
|
+
|
|
9
|
+
pin: `@onlineapps/cookbook-core` 6.0.0 → 7.0.0
|
|
10
|
+
pin: `@onlineapps/error-handler-core` 3.1.0 → 4.0.0
|
|
11
|
+
pin: `@onlineapps/handler-contract` 1.0.0 (nová závislost)
|
|
12
|
+
pin: `@onlineapps/service-validator-core` 2.1.0 → 2.2.0
|
|
13
|
+
|
|
14
|
+
### Changed — BREAKING — `CookbookTestUtils.createControlFlowStep` vyrábí krok, který schéma V2.1 přijme (d.1060)
|
|
15
|
+
|
|
16
|
+
Generátor dřív vracel tvary, které schéma `@onlineapps/cookbook-core` nezná (`items`, `condition`,
|
|
17
|
+
`cases`/`branches` jako pole, `body` jako objekt), `step_id` s pomlčkou a řídicí krok bez `service`
|
|
18
|
+
(`docs/governance/confirmations/cookbook-execution-owner.md` 002).
|
|
19
|
+
|
|
20
|
+
- `options.service` je povinný; krok ho nese a výchozí vnořené tasky běží v téže službě.
|
|
21
|
+
- Tvary podle schématu: `foreach.iterator` + `body` jako pole, `switch.expression` + `cases` jako objekt,
|
|
22
|
+
`fork_join.branches` jako objekt, nově i typ `steps`; výchozí `step_id` odpovídá `^[a-zA-Z0-9_]+$`.
|
|
23
|
+
- Odmítá se jménem (`[CookbookTestUtils] createControlFlowStep('<typ>') - … Fix: …`): chybějící `service`,
|
|
24
|
+
volba `id` (dřív alias `step_id`) a typ mimo `foreach`, `switch`, `fork_join`, `steps`
|
|
25
|
+
(dřív vrátil napůl postavený krok).
|
|
26
|
+
- Testy: `tests/unit/cookbookStepIdentity.test.js` pouští každý vyrobený krok přes `validateCookbook`
|
|
27
|
+
z `@onlineapps/cookbook-core`; dva staré případy, které tvrdily původní tvar, nahrazeny.
|
|
28
|
+
|
|
29
|
+
### Added — `oa-validate --library <packageDir> --as-version <X.Y.Z>`: `L-CHANGELOG` soudí verzi, která se vydává (d.1040)
|
|
30
|
+
|
|
31
|
+
Brána F10 (`scripts/ci/lib/prepublishGate.js`) dostává od `publish-library.sh` `--as-version
|
|
32
|
+
<NOVÁ>` a posouvala jí jen svá pravidla; uniforma (G7) běžela bez verze a `L-CHANGELOG` četl
|
|
33
|
+
`version` z `package.json` — tedy STAROU verzi. Suchý běh tak pustil chybějící `## [NOVÁ]`
|
|
34
|
+
(d.1033: `error-handler-core --as-version 4.0.0` PASS bez hlavičky) a balíček, jehož stará verze
|
|
35
|
+
záznam neměla, odmítl kvůli verzi, kterou nikdo nevydával (d.1038, `handler-contract`).
|
|
36
|
+
|
|
37
|
+
- CLI: `--as-version <X.Y.Z[-prerelease]>`, jen s `--library <packageDir>`. Bez hodnoty, ve
|
|
38
|
+
špatném tvaru, s `--all` nebo bez `--library` se odmítá jménem (exit 2, `Fix:`).
|
|
39
|
+
- `runManifest({ …, asVersion })` hodnotu na vstupu ověří (`isTargetVersion`, exportováno — jediný
|
|
40
|
+
vlastník tvaru, CLI se ptá téhož) a předá ji každé kontrole jako `asVersion`.
|
|
41
|
+
- `library-changelog-entry` soudí `asVersion`, je-li dána, jinak `version` z `package.json` —
|
|
42
|
+
dvě legitimní otázky (vydání × audit stromu), ne hodnota a její náhrada. Nález říká, kterou
|
|
43
|
+
soudil: `no entry for the version being published (4.0.0, given by --as-version; package.json
|
|
44
|
+
says 3.1.0)`. Bez `--as-version` je chování i text beze změny.
|
|
45
|
+
|
|
46
|
+
Text opravy řádku `L-CHANGELOG` (`manifests/library.manifest.json`) říkal „the version in
|
|
47
|
+
package.json" — při suchém běhu vydání tedy posílal psát záznam pro verzi, ze které se odchází.
|
|
48
|
+
Nově: „the version being published — the one in package.json, or the one --as-version names on a
|
|
49
|
+
publish dry run" (d.1040b).
|
|
50
|
+
|
|
51
|
+
Zapojení do brány (G7 předá `--as-version`) je mimo tento balíček (`scripts/ci/lib/prepublishGate.js`).
|
|
52
|
+
|
|
53
|
+
### Changed — BREAKING: Tier-1 `test.timeout`, který není kladné číslo, se odmítá jménem (d.1001)
|
|
54
|
+
|
|
55
|
+
`_dispatchViaHandler` bral limit kroku jako `testConfig.timeout || this.timeout`. Zapsaná
|
|
56
|
+
`0`, `-1` nebo `NaN` tak tiše propadla na výchozí hodnotu běžce a řetězec `"5"` se dostal
|
|
57
|
+
do `setTimeout` jako řetězec — recept říkal jedno, běh dělal druhé
|
|
58
|
+
(`architecture-principles.md` §3). Nově rozhoduje jedno místo, `_stepTimeout(testConfig)`,
|
|
59
|
+
podle kontraktu `docs/biz/40-cookbooks/testing.md` § The `test` block: klíč chybí → výchozí
|
|
60
|
+
hodnota běžce (volba konstruktoru `timeout`); klíč je a není kladné konečné číslo → krok
|
|
61
|
+
selže dřív, než se handler zavolá (`result.request === null`), s hláškou
|
|
62
|
+
`[CookbookTestRunner] test.timeout must be a positive number of milliseconds - got <hodnota>.
|
|
63
|
+
Expected: … Fix: write a positive number (e.g. "timeout": 5000) in the cookbook's test block,
|
|
64
|
+
or drop the key.` Platná hodnota výchozí přebíjí jako dosud.
|
|
65
|
+
|
|
66
|
+
BREAKING pro recept, který nesl `0`, záporné číslo, `NaN`, `Infinity` nebo číslo jako
|
|
67
|
+
řetězec: dřív prošel, nově jeho kroky selžou. Změřeno před změnou nad 56 recepty
|
|
68
|
+
(`api/cookbooks`, `api_biz/*/tests/cookbooks` na `origin/devel`): 21 bez bloku `test`,
|
|
69
|
+
zbylé nesou `timeout` 5000, 10000 nebo 15000 — žádný recept se tím nemění.
|
|
70
|
+
|
|
71
|
+
### Changed — BREAKING: Tier-1 běžec `correlation_id` a `workflow_id` z kroku nečte (d.1001)
|
|
72
|
+
|
|
73
|
+
Dřív `step.correlation_id || crypto.randomUUID()` a `step.workflow_id || correlationId`.
|
|
74
|
+
Formát kroku (`docs/biz/40-cookbooks/format.md` § Task step, `TaskStep`
|
|
75
|
+
v `cookbook.v2.schema.json`) ani jeden klíč nezná a produkce je z kroku nečte, takže
|
|
76
|
+
identitu běhu vyrábí jen běžec: `correlation_id` = nové `crypto.randomUUID()` pro každý
|
|
77
|
+
krok, `workflow_id` = to samé uuid. Krok, který klíče dál nese, se NEodmítá — `TaskStep`
|
|
78
|
+
drží `additionalProperties: true` záměrně (conf `parked-features` 001) a odmítnutí tady by
|
|
79
|
+
byla druhá kolej proti `@onlineapps/cookbook-core` — klíče se chovají jako každý neznámý
|
|
80
|
+
klíč: nečtou se. BREAKING pro Tier-1: recept, který těmi klíči nastavoval ctx handleru,
|
|
81
|
+
je nově nenastaví. Změřeno: 0 z 56 receptů je na kroku nese.
|
|
82
|
+
|
|
83
|
+
`step.person_id` se NEMĚNÍ a běžec ho čte dál: zda Tier-1 nese jednající osobu a odkud,
|
|
84
|
+
rozhoduje conf `testing-tenant-identity` 001 (koordinátor).
|
|
85
|
+
|
|
86
|
+
Doklad: `tests/unit/CookbookTestRunner.stepTimeoutAndIdentity.test.js` (RED 6 z 12 —
|
|
87
|
+
pět odmítnutí timeoutu a uuid místo hodnoty z kroku; kontrolní: chybějící timeout =
|
|
88
|
+
výchozí běžce, platný ho přebíjí, krok bez klíčů beze změny, `person_id` se čte) a
|
|
89
|
+
`…stepTimeoutAndIdentity.integration.test.js` přes `runCookbook()` s reálnými handlery
|
|
90
|
+
fixture (RED 2 z 3, kontrolní recept `two-steps.json` beze změny). Fixture služba má
|
|
91
|
+
novou operaci `sleep`, podle které je vidět, proti kterému limitu handler běžel.
|
|
92
|
+
|
|
93
|
+
### Fixed — `L-PACK-TESTS` pozná allowlist glob, který pustí `tests/` do tarballu; `tests/` pod `templates/**` výslovně není tier balíčku; kořenový `jest.config.js` z tarballu pryč (d.1002)
|
|
94
|
+
|
|
95
|
+
- **Glob v `files`:** řádek dřív uznal jen doslovný záznam `tests`. Balíček s `files: ["**/*.js"]`
|
|
96
|
+
nebo `["*"]` přitom `tests/unit/*.test.js` do tarballu zabalí (změřeno `npm pack --dry-run --json`)
|
|
97
|
+
a řádek o tom mlčel. Teď záznam, jehož první segment odpovídá `tests` (`tests`, `*`, `**`, …),
|
|
98
|
+
je nález, který ten záznam jmenuje: `the files allowlist entry "**/*.js" reaches tests — the tier
|
|
99
|
+
would ship to every consumer`. Změnil se i text nálezu pro doslovné `tests` (dřív `the files
|
|
100
|
+
allowlist names tests …`). Glob omezený na kořen (`*.js`) adresář nezasáhne a nálezem není.
|
|
101
|
+
- **Šablona:** řádek měří jen `tests/` v kořeni balíčku, tedy jeho vlastní tier. `tests/` pod
|
|
102
|
+
`templates/**` je obsah šablony, kterou balíček vydává záměrně (`templates/business-service/tests/**`
|
|
103
|
+
pro `oa-sync-template --new`), a nálezem není. Teď to říkají docblock kontroly i README; testy
|
|
104
|
+
tvrdí obě strany.
|
|
105
|
+
- **Tarball validatoru:** `.npmignore` vylučuje kořenový `/jest.config.js`. Spouští jen vlastní sadu
|
|
106
|
+
balíčku a po instalaci ho nic nečte: grep `conn-orch-validator/jest` nad `shared/`, `infra/` a
|
|
107
|
+
`origin/devel` všech checkoutů pod `api_biz/` (10) dal 0. `npm pack --dry-run`: 116 → 115 souborů, ubyl právě
|
|
108
|
+
`jest.config.js`; `templates/business-service/jest.config.js` a obě šablonové `tests/**` zůstávají.
|
|
109
|
+
|
|
110
|
+
### Fixed — `L-PACK-TESTS` čte negace `.npmignore` / `.gitignore`: `/tests/` a pozdější `!tests/**` je nález (d.1006)
|
|
111
|
+
|
|
112
|
+
Řádek četl z ignore souboru jen řádky, které `tests/` vylučují, a žádnou negaci — takže
|
|
113
|
+
`.npmignore` s `/tests/` a pod ním `!tests/**` prošel jako „vyloučeno", zatímco
|
|
114
|
+
`npm pack --dry-run --json` tier zabalil. Nově řádek přehrává npm procházku
|
|
115
|
+
(`testsShippedBy` v `src/manifest/checks/libraryTests.js`) nad skutečnými soubory
|
|
116
|
+
`tests/`: každý adresář i soubor soudí poslední řádek, který ho trefí; vyloučený adresář
|
|
117
|
+
se znovu otevře, když ho pozdější `!` vzor se `/` může trefit uvnitř (začíná jménem
|
|
118
|
+
adresáře nebo `**`) — vzor bez `/` (`!*.js`) ho neotevře. Nález jmenuje řádek, který tier
|
|
119
|
+
vrátil: `excludes tests/, then re-includes it with "!tests/**" — …`. Pořadí `files` →
|
|
120
|
+
`.npmignore` → `.gitignore` beze změny (`files` vyhrává, `.npmignore` se pak nečte).
|
|
121
|
+
|
|
122
|
+
Bez nové závislosti: `npm-packlist` ani `@npmcli/arborist` balíček nemá (`npm ls` prázdné),
|
|
123
|
+
a volat `npm` z PATH by bránu udělalo závislou na prostředí (`automation-gates.md` §1.1).
|
|
124
|
+
Že reprodukce odpovídá npm, drží `tests/unit/libraryPackTests.npmPack.integration.test.js`:
|
|
125
|
+
20 tvarů (tabulka `tests/helpers/packTestsShapes.js`, sdílená s unit sadou) změřených
|
|
126
|
+
`npm pack --dry-run --json` (npm 11.12.1); bez `npm` v PATH je sada NOT RUN jménem.
|
|
127
|
+
Nad 29 balíčky `api/shared/**` řádek před i po změně 0 nálezů.
|
|
128
|
+
|
|
129
|
+
Exporty `ignoresTests` a `allowsTests` z `src/manifest/checks/libraryTests.js` odcházejí
|
|
130
|
+
(d.1006b) — čtyři otázky `change-discipline.md` § Removing: (1) vznikly v d.211 jako
|
|
131
|
+
pomocné predikáty řádku a exportovaly se vedle `checks`; (2) nesl je řádek `L-PACK-TESTS`,
|
|
132
|
+
který stojí dál; (3) nečte je nikdo — mimo soubor 0 výskytů v celém `api/` (testy
|
|
133
|
+
včetně) a uvnitř je nahradily `allowlistEntryReachingTests` (d.1002) a `testsShippedBy`
|
|
134
|
+
(d.1006); (4) náhrada je koncepčnější: řádek odpovídá jedním výpočtem nad skutečnými
|
|
135
|
+
soubory, ne predikátem nad textem. Modul exportuje jen `checks`.
|
|
136
|
+
|
|
137
|
+
### Added — Tier-1 běžec zná epilog receptu: `compensationStep` a scope `global_error_handler._failure` (d.945, conf meditest-manual-trigger 009)
|
|
138
|
+
|
|
139
|
+
Recept smí deklarovat `global_error_handler: { strategy: 'compensate', compensationStep: '<poslední krok>' }`.
|
|
140
|
+
Běžec se teď chová jako engine (`WorkflowOrchestrator`, d.934):
|
|
141
|
+
|
|
142
|
+
- běžný běh k epilogovému kroku nikdy nedojde (šťastná cesta ho nespustí);
|
|
143
|
+
- recept s deklarací skončí u PRVNÍHO kroku s `passed === false` (handler vyhodil, nebo `expect`
|
|
144
|
+
nesplněn) a pak jednou spustí `compensationStep`; ve scope je pád jako
|
|
145
|
+
`{{global_error_handler._failure.<pole>}}` se šesti klíči `step_id`, `service`, `operation`,
|
|
146
|
+
`error_type`, `error_code`, `details`. `error_type` je odpověď klasifikátoru enginu (d.982, viz
|
|
147
|
+
`### Changed` níže), `error_code` a `details` jsou hodnoty vyhozené chyby, jinak `null` — nic se
|
|
148
|
+
nedomýšlí;
|
|
149
|
+
- padlý epilog další epilog nespustí;
|
|
150
|
+
- výsledek `runCookbook` nese aditivní `epilogue: { step_id, status, output? | error? }`, jen když
|
|
151
|
+
epilog běžel; počty kroků ani `steps` nemění;
|
|
152
|
+
- recept BEZ deklarace beze změny — včetně toho, že krok bez `expect` po selhání nechá běžet další kroky.
|
|
153
|
+
|
|
154
|
+
`runCookbook` nově volá `validateCookbook` z `@onlineapps/cookbook-core` (od d.980 PRVNÍ a bez
|
|
155
|
+
kopií v běžci — viz `### Changed` níže). Z formátu přibývá, co běžec sám neznal:
|
|
156
|
+
povinný `type` kroku, vzor `step_id` (`^[a-zA-Z0-9_]+$`), typ `workspace_id` (celé číslo — recept
|
|
157
|
+
s jiným odmítne celý, hláška jmenuje cestu klíče), pravidla epilogu (d.933: tvar deklarace; d.942:
|
|
158
|
+
`_failure` jen v epilogu) a odmítnutí pozičního odkazu `{{steps[0]…}}` (d.951: krok se adresuje
|
|
159
|
+
`step_id`, nikdy pozicí — dosud zůstával doslovným textem).
|
|
160
|
+
|
|
161
|
+
Testy a fixtury podle pravdy formátu: `type: "task"` doplněn do receptů fixtur i receptů psaných
|
|
162
|
+
v testech; `step_id` s pomlčkou přejmenovány na podtržítko (`^[a-zA-Z0-9_]+$`); testy workspace
|
|
163
|
+
a závorkového odkazu tvrdí odmítnutí formátem. Fixtura `v3-test-service` má operaci
|
|
164
|
+
`boom-with-details`.
|
|
165
|
+
|
|
166
|
+
### Removed — druhá kolej zákazu klíče `id` u kroku (`utils/cookbookFormat.readCookbookSteps`) (d.985)
|
|
167
|
+
|
|
168
|
+
Zákaz klíče `id` u kroku vlastní cookbook-core (d.983: `Forbidden field 'id' at /steps/<n>/id - this key
|
|
169
|
+
must not be declared here …`). Běží PRVNÍ v Tier-1 (`CookbookTestRunner.validateCookbook`, d.980) i v readiness
|
|
170
|
+
cestě (`CookbookTestUtils.validateCookbook`, d.984), takže kopie v `readCookbookSteps` byla v obou cestách
|
|
171
|
+
nedosažitelná. Hláška `[CookbookFormat] step "<id>" carries "id" - Expected: "step_id" only …` zaniká. Krok
|
|
172
|
+
s `id` se odmítá dál, jen slovy cookbook-core; `readCookbookSteps` zůstává pro čtenáře nevalidovaného receptu
|
|
173
|
+
(`compareCookbooks`, `_operationsOf`, `hasExpectClauses`) a odmítá už jen `steps`, které nejsou pole.
|
|
174
|
+
Test `cookbookStepIdentity.test.js` hlídá, že literál staré hlášky v `src/` nevznikne znovu.
|
|
175
|
+
|
|
176
|
+
### Changed — readiness cesta (`CookbookTestUtils.validateCookbook`) volá `validateCookbook` z `@onlineapps/cookbook-core` PRVNÍ; syntetický recept `createServiceReadinessTests` má `step_id` tvaru `test_<operace>` (d.984)
|
|
177
|
+
|
|
178
|
+
Totéž, co d.980 udělal Tier-1 běžci, teď platí i pro cestu readiness wrapperu
|
|
179
|
+
(`ServiceReadinessValidator.checkCookbookExecution` ← `createServiceReadinessTests`): kopie kontrol
|
|
180
|
+
receptu v `CookbookTestUtils.validateCookbook` jsou pryč a odmítnutí formuluje cookbook-core. Metoda
|
|
181
|
+
dál vrací `{ valid, errors }`; odmítnutí je jediná položka `errors`. Mizí tyto hlášky readiness cesty
|
|
182
|
+
(vpravo podřetězec hlášky cookbook-core, která je nahrazuje):
|
|
183
|
+
|
|
184
|
+
| Mizející hláška readiness cesty | Nově (cookbook-core) |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `Cookbook is required` | `Invalid type for 'root' at /. Expected object, got null.` |
|
|
187
|
+
| `cookbook format version is missing …` | `Missing required field 'version' at /.` |
|
|
188
|
+
| `cookbook format version "<v>" is below the required minimum 2.1.0 …` | `FAIL-FAST: V1 format (1.x.x) is BANNED` / `FAIL-FAST: V2.0 format (2.0.x) is BANNED` |
|
|
189
|
+
| `cookbook format version <v> is not a version string …` | `Invalid format for 'version' at /version. Must match pattern: ^2\.\d+\.\d+$` |
|
|
190
|
+
| `[CookbookFormat] cookbook "steps" is an object, not an array …` | `Invalid type for 'steps' at /steps. Expected array, got object.` |
|
|
191
|
+
| `Steps array is required` | `Missing required field 'steps' at /.` / `must NOT have fewer than 1 items (got 0 items)` |
|
|
192
|
+
| `Step <i>: step_id is required` | `Missing required field 'step_id' at /steps/<i>.` |
|
|
193
|
+
| `Step <i>: type is required` | `Missing required field 'type' at /steps/<i>.` |
|
|
194
|
+
| `Step <i>: service is required for task steps` | `Missing required field 'service' at /steps/<i>.` |
|
|
195
|
+
|
|
196
|
+
Recept, který cookbook-core odmítne, readiness cesta nově odmítne i tehdy, když ho dřív propustila
|
|
197
|
+
(např. `step_id` s pomlčkou, chybějící `operation`). Jiná výjimka než `CookbookValidationError`
|
|
198
|
+
z cookbook-core se nepřevádí na nález; propadne do `checkCookbookExecution`, který ji hlásí jako
|
|
199
|
+
neprošlou kontrolu. Vlastní pravidlo readiness cesta nemá žádné: zákaz klíče `id` u kroku odmítá
|
|
200
|
+
cookbook-core (d.983, `Forbidden field 'id' at /steps/<n>/id`) a kopie v `readCookbookSteps` zanikla
|
|
201
|
+
s d.985 (`### Removed` níže).
|
|
202
|
+
|
|
203
|
+
`createServiceReadinessTests` skládá syntetický recept v nové funkci `buildReadinessCookbook`
|
|
204
|
+
(export modulu `helpers/createServiceReadinessTests`, veřejný export balíčku se nemění). `step_id`
|
|
205
|
+
kroku je `test_<jméno operace>`, kde se každý znak mimo `[a-zA-Z0-9_]` nahradí `_` (dřív
|
|
206
|
+
`test-<jméno>`, což vzor `step_id` formátu porušovalo u každé operace). Když dvě operace dostanou
|
|
207
|
+
stejné `step_id`, pomocník to odmítne hláškou
|
|
208
|
+
`[createServiceReadinessTests] Operations "<a>" and "<b>" map to the same step_id "<id>" - …`. Pro biz
|
|
209
|
+
readiness sady (`tests/bootstrap/service-readiness.test.js`) se mění jen tvar syntetického `step_id`;
|
|
210
|
+
jejich tvrzení je průchod a ten platí (ověřeno nad kopiemi `operations.json` služeb hello, converter,
|
|
211
|
+
ingest, pdfgen).
|
|
212
|
+
|
|
213
|
+
`utils/cookbookFormat.checkCookbookFormatVersion` ztratil posledního čtenáře a zanikl i se svými
|
|
214
|
+
testy; `readCookbookSteps`, `stepIdentityOf` a `MIN_COOKBOOK_FORMAT_VERSION` zůstávají.
|
|
215
|
+
|
|
216
|
+
### Changed — Tier-1 `_failure.error_type` je string z klasifikátoru enginu, ne `null` (d.982)
|
|
217
|
+
|
|
218
|
+
`cookbook-core` `RunFailure.error_type` je povinný string; běžec psal `null`, takže recept, který
|
|
219
|
+
`_failure` předá dál (ingest `ack-source-delivery` čte `failure.error_type` jako string), by v Tier-1
|
|
220
|
+
padl na schématu. Běžec teď `error_type` získá týmž klasifikátorem jako engine:
|
|
221
|
+
`ErrorClassifier.classify` z `@onlineapps/error-handler-core` — jádro, na které deleguje
|
|
222
|
+
`classifyError` konektoru `@onlineapps/conn-infra-error-handler`, jehož instanci engine dostává.
|
|
223
|
+
Jedna instance na běžce.
|
|
224
|
+
|
|
225
|
+
- vyhozená chyba handleru → co klasifikátor vrátí pro ni (např. `ValidationError` z
|
|
226
|
+
`@onlineapps/handler-contract` → `VALIDATION`, obecný `Error` bez známého kódu a statusu → `UNKNOWN`);
|
|
227
|
+
- nesplněný `expect` bez vyhozené chyby → `classify(null)` = `UNKNOWN`; Tier-1 `expect` v enginu
|
|
228
|
+
protějšek nemá, `error_code` a `details` zůstávají `null`.
|
|
229
|
+
|
|
230
|
+
Nová závislost: `@onlineapps/error-handler-core` (exact pin na verzi, kterou pinuje
|
|
231
|
+
`@onlineapps/conn-infra-error-handler` orchestrátoru — táž třída `ErrorClassifier`).
|
|
232
|
+
Tvar `results.epilogue` a běh receptu bez deklarace epilogu se nemění.
|
|
233
|
+
|
|
234
|
+
### Changed — Tier-1 běžec nedrží druhou kopii kontrol receptu: `validateCookbook` z `@onlineapps/cookbook-core` běží PRVNÍ, jeho hlášky nahrazují hlášky běžce (d.980)
|
|
235
|
+
|
|
236
|
+
`CookbookTestRunner.validateCookbook()` (a tím `runCookbook`) volá nejdřív `validateCookbook`
|
|
237
|
+
z `@onlineapps/cookbook-core` — tutéž funkci, na které hází přijímající strana. Kopie jeho pravidel
|
|
238
|
+
v běžci jsou pryč (jedna kolej, `change-discipline.md` § One rail per concern). Co recept odmítne,
|
|
239
|
+
se nemění; mění se SLOVA, která biz vlákno čte ve výstupu Tier-1 (záznam `cookbook-load-failure`
|
|
240
|
+
v `results.steps[].error`, řádek chyb kroku 4 validace). Mizí tyto hlášky běžce a nahrazuje je
|
|
241
|
+
hláška cookbook-core (vpravo podřetězec, který se v ní objeví):
|
|
242
|
+
|
|
243
|
+
| Mizející hláška běžce | Nově (cookbook-core) |
|
|
244
|
+
|---|---|
|
|
245
|
+
| `[CookbookTestRunner] Cookbook is not a JSON object …` | `Invalid type for 'root' at /. Expected object, got <typ>.` |
|
|
246
|
+
| `[CookbookTestRunner] cookbook format version is missing …` | `Missing required field 'version' at /.` (prázdný řetězec: `Invalid format for 'version' at /version.`) |
|
|
247
|
+
| `[CookbookTestRunner] cookbook format version "<v>" is not a version string …` | `Invalid format for 'version' at /version. Must match pattern: ^2\.\d+\.\d+$` |
|
|
248
|
+
| `[CookbookTestRunner] cookbook format version "<v>" is below the required minimum 2.1.0 …` | `FAIL-FAST: V1 format (1.x.x) is BANNED` / `FAIL-FAST: V2.0 format (2.0.x) is BANNED` |
|
|
249
|
+
| `[CookbookTestRunner] Cookbook has no steps …` | `Missing required field 'steps' at /.` (`null`: `Invalid type for 'steps' at /steps. Expected array, got null.`) |
|
|
250
|
+
| `[CookbookFormat] cookbook "steps" is an object, not an array …` | `Invalid type for 'steps' at /steps. Expected array, got object.` |
|
|
251
|
+
| `[CookbookTestRunner] Cookbook must have at least one step …` | `Invalid value for 'steps' at /steps - must NOT have fewer than 1 items (got 0 items).` |
|
|
252
|
+
| `[CookbookTestRunner] Step #<n> has no step_id …` | `Missing required field 'step_id' at /steps/<n-1>.` |
|
|
253
|
+
| `[CookbookTestRunner] Step <id> must have service …` | `Missing required field 'service' at /steps/<i>.` (prázdný: `Invalid value for 'service' …`) |
|
|
254
|
+
| `[CookbookTestRunner] Step <id> must have operation …` | `Missing required field 'operation' at /steps/<i>.` |
|
|
255
|
+
| `[CookbookTestRunner] Step <id> references an undefined step …` | `Step references that cannot resolve at run time - <id>.input: {{steps.<x>…}} - unknown step '<x>'.` |
|
|
256
|
+
| `… references an undefined step - "{{steps.0…}}" names "0"` | `… - a step is addressed by its step_id, never by position` |
|
|
257
|
+
| `[CookbookTestRunner] Step <id> depends on an undefined step …` | `Step '<id>' depends on non-existent step_id '<x>'` |
|
|
258
|
+
|
|
259
|
+
Soubor receptu se dál připojuje na konec (`(cookbook file: <cesta>)`); tvar `results`, `epilogue`,
|
|
260
|
+
počty ani `kind` záznamu se nemění.
|
|
261
|
+
|
|
262
|
+
`version` jiného typu než řetězec (např. číslo `2.1`) cookbook-core vlny 3 odmítá pojmenovanou vadou
|
|
263
|
+
`Invalid type for 'version' at /version. Expected string, got number.` (d.983; do té doby padal
|
|
264
|
+
v `detectVersion` na `TypeError`, nahlášeno s d.980).
|
|
265
|
+
|
|
266
|
+
Běžci zůstává jen to, co cookbook-core nedělá: odmítnutí `test.mockInfrastructure` jménem; odmítnutí volání
|
|
267
|
+
helperu `{{name(…)}}` ve vstupu kroku (Tier-1 nemá registr helperů); hodnota `workspace_id`
|
|
268
|
+
(`assertWorkspaceId` při spuštění kroku). `CookbookTestRunner.validateCookbook()` nově odmítá
|
|
269
|
+
i to, co dřív odmítal až `runCookbook` (povinný `type`, vzor `step_id` …), protože cookbook-core
|
|
270
|
+
běží v něm.
|
|
271
|
+
|
|
272
|
+
### Changed — BREAKING: `parseHandlerRef` čte tvar handler ref z `@onlineapps/service-validator-core`; export `HANDLER_REF_PATTERN` zaniká (d.962, d.465d)
|
|
273
|
+
|
|
274
|
+
`src/utils/handlerRef.js` nedrží vlastní literál tvaru `handlers/<cesta>#<export>`: `parseHandlerRef` testuje
|
|
275
|
+
proti `HANDLER_REF_REGEX` z veřejného vstupu `@onlineapps/service-validator-core` (export z d.720), tedy proti
|
|
276
|
+
TÉMUŽ objektu, podle kterého registr odmítá `operations.json`. Dvě kopie jednoho pravidla se rozejdou v den,
|
|
277
|
+
kdy se jedna opraví (`change-discipline.md` § One rail per concern). Chování se nemění — oba výrazy změřeny nad
|
|
278
|
+
stejnou sadou vzorků (`handlers/a/b#fn`, `handlers/a.b#fn`, `handlers/a#1x`, `handlers//x#f` a dalších), 0 rozdílů.
|
|
279
|
+
|
|
280
|
+
BREAKING: vstup balíčku už nevyváží `HANDLER_REF_PATTERN`. Čtenáři mimo balíček: 0 (změřeno
|
|
281
|
+
`grep -rn --exclude-dir=node_modules` nad `api/shared`, `api/infra`, `api/scripts`, `api/templates`, `api_biz`,
|
|
282
|
+
`fe_adminui`). Kdo tvar potřebuje jako hodnotu, čte `require('@onlineapps/service-validator-core').HANDLER_REF_REGEX`.
|
|
283
|
+
|
|
284
|
+
Vyžaduje `@onlineapps/service-validator-core` s exportem `HANDLER_REF_REGEX` na vstupu balíčku (dnes v jeho
|
|
285
|
+
`[Unreleased]`; vydaná 2.1.0 ho nemá).
|
|
286
|
+
|
|
287
|
+
Stráž: `tests/unit/handlerRefSingleSource.test.js` — pod `src/` není literál `^handlers\/` ani hluboký import
|
|
288
|
+
`@onlineapps/<balíček>/src/…`; `tests/unit/handlerRef.test.js` měří identitu (`jest.spyOn` na exportovaném objektu).
|
|
289
|
+
|
|
290
|
+
### Fixed — unit sada nepřepisuje `manifests/biz-service.manifest.json` balíčku (d.965)
|
|
291
|
+
|
|
292
|
+
Dvě sondy v `tests/unit/sharedEnvCli.test.js` přepisovaly zabalený manifest a v `finally` ho vracely, takže paralelní
|
|
293
|
+
worker jestu, který ho v tu chvíli četl, dostal `[Manifest] Manifest is not valid JSON` (náhodně červený
|
|
294
|
+
`templateRunnerRuntime`); sondy teď běží nad kopií manifestu v dočasném adresáři a stráž `afterEach` shodí test, který
|
|
295
|
+
zabalený manifest změní (mtime nebo obsah).
|
|
296
|
+
|
|
297
|
+
### Changed — Tier-1 běžec předává handleru skutečný `OperationContext` (conf handler-contract 001)
|
|
298
|
+
|
|
299
|
+
`CookbookTestRunner._dispatchViaHandler` staví `ctx` jako `new OperationContext({...})` z
|
|
300
|
+
`@onlineapps/handler-contract` místo objektového literálu — tutéž třídu, kterou handler dostává
|
|
301
|
+
v produkci od `@onlineapps/service-wrapper`. Import jde z balíčku kontraktu (L1), ne z wrapperu (L4),
|
|
302
|
+
takže běžec (L3) nemá zpětnou hranu (architecture-principles §7).
|
|
303
|
+
|
|
304
|
+
Co to pro handler znamená pod běžcem:
|
|
305
|
+
|
|
306
|
+
- `ctx.requireActingPerson()` vrací `step.person_id`; krok bez něj skončí 400 `VALIDATION_FAILED`
|
|
307
|
+
(dosud `TypeError: ctx.requireActingPerson is not a function`, 500).
|
|
308
|
+
- `ctx.normalizeDateRange()` funguje jako v produkci (dosud `TypeError`, 500).
|
|
309
|
+
- `ctx` je zmrazený (`Object.isFrozen(ctx) === true`): zápis do slotu hodí v strict mode
|
|
310
|
+
`TypeError`, stejně jako v produkci. Dosud byl literál běžce zapisovatelný.
|
|
311
|
+
|
|
312
|
+
Sada slotů se NEmění (conf handler-contract 001, čtení 4): runner-only `headers` a `service_name`
|
|
313
|
+
zůstávají, `config` ani `scheduler` běžec nestaví. Nová závislost `@onlineapps/handler-contract`
|
|
314
|
+
`1.0.0` (exact).
|
|
315
|
+
|
|
316
|
+
### Fixed — šablona biz služby nese `src/config/index.js`, ze kterého wrapper čte konfiguraci (d.957)
|
|
317
|
+
|
|
318
|
+
`bootstrap(__dirname)` z `@onlineapps/service-wrapper` čte konfiguraci služby jen z `<serviceRoot>/src/config`
|
|
319
|
+
a `service.env` bere z toho, co tam vrátí `ConfigLoader.loadAll({ basePath, env: process.env })`. Všech osm biz služeb
|
|
320
|
+
ten soubor nese se stejným kódem; `templates/business-service` ho neměl, takže služba vytvořená `oa-sync-template --new`
|
|
321
|
+
(i `scripts/add-service.sh`, který jde touž cestou) by nenabootovala. Šablona teď nese `src/config/index.js` jako
|
|
322
|
+
bajtovou kopii souboru služeb converter, hello a ingest; zrcadlo `api/templates/business-service` ho nese také
|
|
323
|
+
(`tests/unit/templateMirror.test.js`) a README šablony ho uvádí v § Structure. Sada `tests/unit/templateServiceConfig.test.js`
|
|
324
|
+
měří, že vyrenderovaná služba soubor má a že předá loaderu kořen služby a `process.env` a vyveze, co loader vrátil
|
|
325
|
+
(wrapper v ní zastupuje zapsaný stub souseda). Stávající služby se nemění.
|
|
326
|
+
|
|
327
|
+
### Fixed — `oa-validate --library` nad balíčkem z jiného checkoutu skončí fail-fast, ne falešným nálezem (d.940)
|
|
328
|
+
|
|
329
|
+
Běh jednoho balíčku měří balíček proti api checkoutu, za který kopie validatoru mluví (`workspaceRoot.js`
|
|
330
|
+
§ apiCheckoutOf); balíček ze sourozeneckého checkoutu (typicky git worktree vedle `api/`) tak dostal `L-README-REGION`
|
|
331
|
+
s fixem `npx oa-sync-template readme-uniform --all`, který by README přepsal na odkaz do cizího checkoutu, a `where`
|
|
332
|
+
s jménem cizího adresáře. Nově `requirePackageInApiCheckout()` běh zastaví před prvním řádkem hláškou
|
|
333
|
+
`[ManifestWorkspace] <balíček> lies outside the checkout this validator speaks for (<checkout>) - Fix: run oa-validate
|
|
334
|
+
from the checkout that carries the package: node <jeho checkout>/…/oa-validate.js --library <balíček>` (exit 2); leží-li
|
|
335
|
+
balíček v adresáři, nad kterým žádný checkout není, hláška to říká a příkaz nevymýšlí. Balíček uvnitř checkoutu a běh bez
|
|
336
|
+
workspace (`NOT RESOLVED`) se nemění. Sada: `tests/unit/manifestWorkspaceRoot.test.js` § a package in a sibling checkout.
|
|
337
|
+
|
|
338
|
+
### Changed — `only_with` je vlastnost ŘÁDKU manifestu, ne jedné kontroly (d.838)
|
|
339
|
+
|
|
340
|
+
Podmíněný řádek `only_with: <cesta>` existuje od `S-INT-C`: skript, který ukazuje na sadu,
|
|
341
|
+
kterou repozitář nemá, je deklarace bez obsahu. Vyhodnocovala ho ale skriptová kontrola sama
|
|
342
|
+
(`checks/serviceScripts.js`), takže kterýkoli jiný druh řádku podmínku ignoroval — `only_with`
|
|
343
|
+
nad `config/service/*` by v manifestu stálo a v běhu nerozhodlo nic. Pravidlo viditelné
|
|
344
|
+
v deklaraci a nepřítomné v běhu je ta tichá neúčinnost, kterou `automation-gates.md` §5 počítá
|
|
345
|
+
za vadu.
|
|
346
|
+
|
|
347
|
+
Od téhle změny ho čte engine, který řádky rozděluje na kontroly (`manifest/runManifest.js`,
|
|
348
|
+
`rowApplies`), a čte ho pro VŠECHNY scope — `service`, `workspace` i `bearer` (u nosičů per
|
|
349
|
+
nosič, protože podmínka je o tom, co nese konkrétní repozitář).
|
|
350
|
+
|
|
351
|
+
Chování se nemění: řádek, jehož podmínka neplatí, neodpovídá nic — žádný nález a žádné NOT RUN,
|
|
352
|
+
přesně jako dosud u `S-INT-C`. NOT RUN by znamenalo „nemohl jsem posoudit"; tady není co
|
|
353
|
+
posuzovat, řádek pro takovou službu neplatí. Zachována je i ta část, na které `S-INT-C` stojí:
|
|
354
|
+
adresář, který existuje a je prázdný, podmínku NESPLŇUJE.
|
|
355
|
+
|
|
356
|
+
Žádný nový řádek uniformy tím nevzniká — mechanismus se zobecňuje dopředu, pro podmíněný řádek
|
|
357
|
+
nad `config/service/*`, který přijde s pinem po vlně, jež vydá jeho schéma.
|
|
358
|
+
|
|
359
|
+
### Changed — BREAKING: veřejnou plochou balíčku je mapa `exports`, ne strom souborů (d.812)
|
|
360
|
+
|
|
361
|
+
`package.json` nese mapu `exports` se čtyřmi klíči: `.` (→ `src/index.js`), `./manifests/*`, `./templates/*`
|
|
362
|
+
a `./package.json`. Každá jiná cesta do balíčku — typicky `require('@onlineapps/conn-orch-validator/src/utils/deployContract.js')`
|
|
363
|
+
— končí chybou `ERR_PACKAGE_PATH_NOT_EXPORTED`; interní moduly (`src/**`, včetně `src/cli/*`) přestávají být importovatelné.
|
|
364
|
+
Mapy `bin` se to netýká: `oa-validate`, `oa-biz-ci-gate`, `oa-lint-scripts` i `oa-sync-template` běží dál. Schopnost, kterou
|
|
365
|
+
jediný změřený konzument bral hlubokou cestou (`api/scripts/verify-biz-deploy-contract.sh`), dostala jméno na vstupním bodě:
|
|
366
|
+
`verifyDeployContract`, `DEPLOY_CONTRACT_REQUIREMENTS`, `DEPLOY_CONTRACT_SCOPE`. Konzument s hlubokým `require` přejde na tyto
|
|
367
|
+
exporty (nebo na `manifests/*` / `templates/*`). Mapu drží `tests/unit/packageExports.test.js`, seznam jmen vstupního bodu
|
|
368
|
+
`tests/unit/indexExports.test.js`.
|
|
369
|
+
|
|
370
|
+
### Fixed — varování kroku 1 (struktura) se dostanou do souhrnu validace (d.791c)
|
|
371
|
+
|
|
372
|
+
`ValidationOrchestrator` z kroku 1 sbíral jen `errors`; `warnings`, které `ServiceStructureValidator` plní (např.
|
|
373
|
+
`STANDARD_LEVEL_GAP`), tiše zahazoval, zatímco krok 4 je sbíral. Nově jsou v `results.warnings` se `step: structure`.
|
|
374
|
+
Verdikt se nemění — nikdo ho podle počtu varování nepočítá; služba může v souhrnu uvidět varování, které tam dřív nebylo
|
|
375
|
+
(změřeno nad `api_biz/*`: jedno, `STANDARD_LEVEL_GAP` u ingestu).
|
|
376
|
+
|
|
377
|
+
### Changed — BREAKING: R8 permit pro `require` modulu namespace žádá vykonávaný řádek, ne zmínku (d.782b)
|
|
378
|
+
|
|
379
|
+
`src/utils/deployContract.js`: permit R8 „soubor si vyžádá modul test-namespace“ se měřil nad celým textem souboru, takže
|
|
380
|
+
komentář `// TODO: require('./testNamespace')` soubor z bezpečnostní hranice R8 vyvázal. Nově platí `matchesOnExecutingLine()`
|
|
381
|
+
jako u ostatních permitů; regex má jméno `REQUIRE_NAMESPACE_MODULE`. Integrační test, který require nese jen v komentáři,
|
|
382
|
+
je teď nález R8. Změřeno nad `api_biz/*`: 0 takových souborů, verdikt R8 se u žádné služby nemění.
|
|
383
|
+
|
|
384
|
+
### Fixed — obě hlášky R8 jmenují obě cesty, které permit uznává (d.778, d.782)
|
|
385
|
+
|
|
386
|
+
Finální hláška R8 i hláška o souboru, který si staví vlastní databázi a nepřesměruje `DB_NAME`, radily jen
|
|
387
|
+
`require` modulu `tests/integration/testNamespace.js`. Nově jmenují obě uznávané cesty: volání `getTestNamespace()` /
|
|
388
|
+
`getForeignTestNamespace()` na vykonávaném řádku, nebo `require()` modulu repozitáře. Permit se nemění, jen text hlášek.
|
|
389
|
+
|
|
390
|
+
### Fixed — `createServiceReadinessTests`: deklarovaný `timeout` platí pro všechny tři registrované testy (d.764b)
|
|
391
|
+
|
|
392
|
+
Volba `options.timeout` (výchozí 15000) se předávala jen prvnímu ze tří testů; zbylé dva běžely s výchozím rozpočtem jestu
|
|
393
|
+
(5000). Nově ji nesou všechny tři. Neplatná hodnota (včetně `0`, které jest čte jako „bez rozpočtu“) končí fail-fast hláškou
|
|
394
|
+
`[Context] … Fix:`; vynechaná volba nebo `undefined` zůstává výchozí 15000. Volajícím bez voleb se dvěma testům rozpočet
|
|
395
|
+
rozšiřuje z 5000 na 15000.
|
|
396
|
+
|
|
397
|
+
### Changed — cesta k proofu má v balíčku jednoho vlastníka; proof na disku nepřeskočí nic (d.758)
|
|
398
|
+
|
|
399
|
+
`ValidationOrchestrator` bere cestu `conn-runtime/validation-proof.json` z `PROOF_RELATIVE_PATH` (`src/utils/preValidation.js`)
|
|
400
|
+
místo vlastního literálu. Chování se nemění: nová sada `tests/unit/proofFileIsOutputNotCache.test.js` dokládá hodnotou, že
|
|
401
|
+
starý proof položený na disk běh nepřeskočí a skončí přepsaný otiskem, který běh naměřil.
|
|
402
|
+
|
|
403
|
+
### Fixed — citace dokumentů v hláškách a komentářích nesou tvar `api/…`; sweep nedoporučuje `service-common` (d.753b, d.753c, d.756, d.756b)
|
|
404
|
+
|
|
405
|
+
Citace začínající `/` (`See: /docs/biz/…`, `@see /api/…`) a citace bez prefixu ve vytištěných `fix:` hláškách
|
|
406
|
+
(`ServiceStructureValidator`, `sharedEnv`) nesou `api/docs/…` — tvar, který se ze workspace otevře a který čte `L008`.
|
|
407
|
+
Sondy v `tests/unit/serviceStructureMessages.test.js` a `tests/unit/readmePointerCli.test.js` měří každou citaci v `src/**`
|
|
408
|
+
(a v komentářích `tests/**`) proti disku. `ServiceStructureValidator.validatePackageJson()` přestal doporučovat
|
|
409
|
+
`@onlineapps/service-common` — týž soubor import retired hierarchie chyb odmítá; odmítnutí zůstává beze změny. Konzument,
|
|
410
|
+
který porovnává text hlášek doslova, uvidí nový tvar cesty. Neexportovaná konstanta `MIGRATIONS_README` (`manifest/checks/serviceDb.js`)
|
|
411
|
+
bez čtenáře smazána — cestu nese řádek `D-DB-README`.
|
|
412
|
+
|
|
413
|
+
### Changed — jméno README má jednoho vlastníka, `src/sync/readmeFile.js` (d.739, d.739b, d.753)
|
|
414
|
+
|
|
415
|
+
`README_FILE` deklaruje jediný modul `src/sync/readmeFile.js`; `sync/readmePointer.js`, `sync/readmeLocation.js`,
|
|
416
|
+
`manifest/checks/libraryDocs.js` i nápověda a hlášky `oa-sync-template` ho importují. `src/cli/oa-sync-template.js` už
|
|
417
|
+
`README_FILE` nere-exportuje a `sync/readmeLocation.js` ho nevyváží (importéra mimo balíček neměl ani jeden). Vypsaný text
|
|
418
|
+
se nemění (`README_FILE === 'README.md'`).
|
|
419
|
+
|
|
420
|
+
### Added — `L-README` odmítá ručně psanou verzi balíčku (d.732)
|
|
421
|
+
|
|
422
|
+
Kontrola řádku `L-README` (`manifest/checks/libraryDocs.js`) hlásí v README zápis `Version: X.Y.Z` a samostatné `vX.Y.Z`
|
|
423
|
+
— verzi vlastní `package.json`. Holá trojice bez popisku, konfigurační příklad (`serviceVersion: '1.0.0'`) ani jméno
|
|
424
|
+
závislosti (`lib-v2`) nálezem nejsou. Knihovna s verzí v README dostane od `oa-validate --library` nález.
|
|
425
|
+
|
|
426
|
+
### Changed — `L-CHANGELOG` měří záznam vydávané verze, ne existenci souboru (d.731b)
|
|
427
|
+
|
|
428
|
+
Řádek běží jako kontrola `library-changelog-entry`: v `CHANGELOG.md` musí existovat sekce pro verzi z `package.json`
|
|
429
|
+
a nést aspoň jeden neprázdný řádek, který není podnadpis. Prerelease `X.Y.Z-rc.N` smí stát pod neprázdným `[Unreleased]`.
|
|
430
|
+
Tvar nadpisu se neřeší (`## [1.0.3] — …` i `## 1.0.0`). Knihovna s prázdnou sekcí vydávané verze je nově NOT PUBLISHABLE.
|
|
431
|
+
|
|
432
|
+
### Changed — BREAKING: klíče `config.json` vlastní jen řádek `C-SERVICE` (d.726)
|
|
433
|
+
|
|
434
|
+
Krok 1 (`ServiceStructureValidator`) přestal žádat `service.name` vlastním seznamem; drží jen strukturu (soubor existuje,
|
|
435
|
+
čte se, parsuje). Klíče žádá řádek `C-SERVICE` (`manifest/checks/serviceConfig.js`, `REQUIRED_SERVICE_KEYS`). Typ nálezu
|
|
436
|
+
`MISSING_CONFIG_FIELD` zaniká — kdo ho čte, přejde na nález `C-SERVICE`. Služba bez `service.name` už neselže v kroku 1,
|
|
437
|
+
takže běh nově promluví i o dalších chybějících klíčích (např. `workspaceScoped`).
|
|
438
|
+
|
|
439
|
+
### Changed — `oa-sync-template --target <služba>` uvede do souladu každý generovaný řádek, i `G-SHARED-ENV` (d.710, d.710c)
|
|
440
|
+
|
|
441
|
+
Holý běh psal jen řádky sekce `files`; `config/env-templates/shared.env` (řádek `G-SHARED-ENV` v sekci `config`) nezapsal,
|
|
442
|
+
takže služba po syncu mohla být NOT DEPLOYABLE. Nově běh bere každý řádek, který o sobě deklaruje `"class": "generated"`,
|
|
443
|
+
a bez workspace nad sebou hlásí `NOT RUN G-SHARED-ENV …`. Podpříkaz `shared-env` bere umístění SSOT i cíle z řádku
|
|
444
|
+
`G-SHARED-ENV` (`from`, `path`), ne z vlastních konstant; chybějící SSOT hlásí sdílenou větou `[ManifestDiscovery] Referenced
|
|
445
|
+
file not found …`. `fix` řádku `G-SHARED-ENV` je nově `npx oa-sync-template --target .`. Exporty CLI `MANIFEST_RELATIVE`
|
|
446
|
+
a `SHARED_ENV_RELATIVE` smazány (bez importéra).
|
|
447
|
+
|
|
448
|
+
### Fixed — R2 čte stráž předka po jobech a komentář symetricky; top-level klíč YAML má jednu definici (d.707, d.707b, d.707c, d.707d)
|
|
449
|
+
|
|
450
|
+
`src/utils/deployContract.js`: stráž `git merge-base --is-ancestor` kryje `git reset --hard <commit>` jen v TÉMŽE top-level
|
|
451
|
+
jobu a na dřívější pozici — stráž v sousedním jobu reset nekryje. Řádek, který začíná komentářem (`#`), neběží: zakomentovaná
|
|
452
|
+
stráž nekryje a zakomentovaný `git pull`, `git merge` či `git reset --hard` se nepočítá (predikát `isCommentLine()`
|
|
453
|
+
s `YAML_COMMENT_OPENERS`). Rozklad na klíče nese nový `src/utils/yamlTopLevel.js` (`topLevelKeys`, `rewritableTopLevelKeys`),
|
|
454
|
+
sdílený s `src/sync/serviceTemplate.js`. Repozitář se stráží jen v jiném jobu nebo v komentáři nově dostane nález R2;
|
|
455
|
+
změřeno nad `api_biz/*` a balenou šablonou: bez nálezu.
|
|
456
|
+
|
|
457
|
+
### Added — generovaný `shared.env` umí nést značku `# @per-machine` (d.666)
|
|
458
|
+
|
|
459
|
+
`src/sync/sharedEnv.js`: položka `config/shared-env.json` smí nést `perMachine: { reason: "<text>" }`; render pak nad `KEY=`
|
|
460
|
+
napíše `# @per-machine — <reason>`, tvar, který čte `scripts/lib/env-template-markers.sh`. Neplatný tvar (ne objekt, neznámé
|
|
461
|
+
pole, chybějící/prázdný/víceřádkový `reason`) končí hláškou `[SharedEnv] … Fix: …`. Zabalená kopie `shared.env` nese značku
|
|
462
|
+
u `NODE_ENV`.
|
|
463
|
+
|
|
464
|
+
### Fixed — hláška o chybějící proměnné v hlavičce kroku končí `Fix:` (d.657)
|
|
465
|
+
|
|
466
|
+
`src/utils/resolveHeaders.js`: k dosavadní větě se připojuje `Fix:` — hodnotu nastavit v `env-active/*.env`, nebo
|
|
467
|
+
dát do `headers` kroku kuchařky literál. Dosavadní text stojí před ní doslova; kdy a jakou třídou se hází, se nemění.
|
|
468
|
+
|
|
469
|
+
### Fixed — `oa-sync-template` čte platformní soubory přes konvenci `api/`, ne přes jméno adresáře (d.653, W653)
|
|
470
|
+
|
|
471
|
+
`shared-env` a `--new` skládaly cestu k `api/config/shared-env.json` (§ loadManifest) a
|
|
472
|
+
`api/config/libraries.json` (§ loadLibraries) prostým `path.join(workspaceRoot, …)`. `api/` v čele takové
|
|
473
|
+
cesty je konvence deklarujícího textu, nikdy jméno adresáře na disku (`src/manifest/workspaceRoot.js`
|
|
474
|
+
hlavička), a GitLab klonuje repozitář pod jménem projektu — oba podpříkazy tedy fungovaly na stroji vývojáře
|
|
475
|
+
a nikde jinde. Změřeno 2026-09-18 v obrazu jobu, jeden strom pod dvěma jmény:
|
|
476
|
+
|
|
477
|
+
infra-mono → [oa-sync-template] Missing platform env manifest - <workspace>/api/config/shared-env.json does not exist.
|
|
478
|
+
api → [oa-sync-template] shared-env is in sync - …/config/env-templates/shared.env
|
|
479
|
+
|
|
480
|
+
Cesta v té větě nepatří žádnému checkoutu toho workspace, takže podle ní nelze jednat
|
|
481
|
+
(`.claude/rules/automation-gates.md` §1 požadavek 4). V CI to shodilo `tests/scripts/shared-env-sync.bats:32,39`
|
|
482
|
+
a — přes `--new`, který čte oba soubory — `tests/scripts/readme-uniform-pointer.bats:248,260,302`. Obě místa
|
|
483
|
+
teď procházejí `resolveWorkspacePath()`, jediným vlastníkem té konvence.
|
|
484
|
+
|
|
485
|
+
### Fixed — `workspaceAbove()` pozná checkout pod jakýmkoli jménem (d.652, W652)
|
|
486
|
+
|
|
487
|
+
Otázka „ve kterém workspace ten strom leží" se ptala na doslovný `api/config/services.json` nad každým
|
|
488
|
+
předkem, zatímco checkout se jmenuje podle projektu GitLabu. Změřeno 2026-09-18 nad stromem `infra-mono`
|
|
489
|
+
(`tests/scripts/readme-uniform-pointer.bats:241`, job `test-scripts` pipeline 2860587739): `null` pro strom,
|
|
490
|
+
který ležel uvnitř téhož workspace, ze kterého běh vyšel — a `oa-sync-template readme-uniform` pak zapsaný
|
|
491
|
+
soubor označil absolutní cestou, jménem, které na každém stroji znamená něco jiného. Ptá se teď
|
|
492
|
+
`apiCheckoutOf()`, tedy touž jednou kolejí jako tři otázky pod ní; štítek `oa-sync-template` zůstává
|
|
493
|
+
`<jméno checkoutu>/…`, což je jeho vlastní věc a tato změna se jí nedotýká.
|
|
494
|
+
|
|
495
|
+
### Fixed — `where` nálezu nese konvenci `api/`, ne jméno adresáře checkoutu (d.652, W652)
|
|
496
|
+
|
|
497
|
+
`checks/libraryContext.js` § whereOf skládal `where` odečtením kořene workspace od kořene nesoucího, takže
|
|
498
|
+
hlavou cesty bylo **jméno adresáře** checkoutu. GitLab klonuje repozitář pod jménem projektu, a tentýž nález,
|
|
499
|
+
který lokálně ukazuje na `api/shared/connector/conn-orch-validator/…/deployment.md:3`, tak v CI ukázal na
|
|
500
|
+
`infra-mono/shared/connector/…` — cestu, která neexistuje pod žádným jménem, jež si čtenář může někam vložit
|
|
501
|
+
(`.claude/rules/automation-gates.md` §1 požadavek 4). Změřeno 2026-09-18 v obrazu CI nad `library-workspace`
|
|
502
|
+
přejmenovaným na `infra-mono`: tabulka nesla obě hlavy najednou —
|
|
503
|
+
`infra-mono/shared/lib-bad-core/package.json` vedle `api/shared/connector/conn-orch-validator/README.md`,
|
|
504
|
+
protože prefix už vzal `src/sync/readmeLocation.js` (d.625) a `whereOf` ne.
|
|
505
|
+
|
|
506
|
+
Konvence má teď jednoho vlastníka i pro zpětný směr: `manifest/workspaceRoot.js` § workspaceRelativeOf, inverze
|
|
507
|
+
k `resolveWorkspacePath` a totéž pravidlo, které `scripts/ci/lint-biz-docs.mjs` § workspaceRelativeOf aplikuje
|
|
508
|
+
na své vlastní nálezy. Čtenáři jsou dva a **musí** se shodnout: `whereOf` řetězec píše a `runManifest.js`
|
|
509
|
+
§ buildScopeFilter jím filtruje, které workspace-nálezy si běh v režimu služby nechá — dvě hláskování jedné
|
|
510
|
+
cesty by v CI zahodila všechny nálezy o službě, které se běh ptal (`.claude/rules/change-discipline.md`
|
|
511
|
+
§ One rail per concern).
|
|
512
|
+
|
|
513
|
+
### Added — řádek uniformy `C-CI-CONNECTOR-ENV`: job `test` nastavuje klíče deklarovaného konektoru (d.635b, W635b)
|
|
514
|
+
|
|
515
|
+
Nový řádek kategorie `config` (check `ci-connector-env`, severita `deploy`): pro každý
|
|
516
|
+
`requiredConnectors.<c>: true` musí `variables:` jobu `test` v `.gitlab-ci.yml` — **mimo** blok `oa-ci v1`,
|
|
517
|
+
který patří `G-CI` — nastavovat každý klíč z `CONNECTORS[c].env`. Změřeno 2026-09-18: tři testy emaileru padly
|
|
518
|
+
v CI na `[RuntimeConfig] Missing environment variable - MINIO_USE_SSL`, jméno, které nečte žádný řádek služby —
|
|
519
|
+
resolvuje ho `@onlineapps/conn-base-storage` (`required: true`, bez defaultu), takže `ci:gate:contract` ho
|
|
520
|
+
nevidí (`node_modules` je vědomě mimo jeho rozsah) a `ci:gate:env` jen emituje šest `OA_CI_*` a neměří nic.
|
|
521
|
+
Lokálně táž sada projde: běžec čte `config/env-templates/shared.env` přes `env_file`. Blok `variables:` je
|
|
522
|
+
druhé doručení téže množiny, ručně opsané v osmi repech, a nic ho neporovnávalo s prvním.
|
|
523
|
+
|
|
524
|
+
Řádek se klíčuje deklarací služby a množinou, kterou knihovna konektoru resolvuje bez defaultu — ne příznakem
|
|
525
|
+
`required: true` v schématu knihovny, který je podmíněný (priorita explicitní config → env → default) a platí
|
|
526
|
+
i pro čtyři rodiny klíčů, kde mezera není. Čte `variables:` jednoho jmenovaného jobu, ne `variables:` sidecaru
|
|
527
|
+
o dvě úrovně hlouběji, a neptá se, **zda** repozitář job má — to je jiná oprava, tedy jiný řádek.
|
|
528
|
+
Projektové proměnné GitLabu nevidí, proto míří jen na klíče s platformovou hodnotou v `api/config/shared-env.json`.
|
|
529
|
+
Rozhodnutí vlastníka `biz-service-manifest` 013.
|
|
530
|
+
|
|
531
|
+
### Changed — `CONNECTORS[minio].env` je pět klíčů, které `conn-base-storage` opravdu vyžaduje (d.635b, W635b)
|
|
532
|
+
|
|
533
|
+
Z `MINIO_ENDPOINT`, `MINIO_ACTUAL_HOST` na `MINIO_ENDPOINT`, `MINIO_PORT`, `MINIO_USE_SSL`, `MINIO_ACCESS_KEY`,
|
|
534
|
+
`MINIO_SECRET_KEY` — přesně ty, které `conn-base-storage/src/config.js` značí `required: true` bez defaultu.
|
|
535
|
+
`MINIO_ACTUAL_HOST` mezi nimi není: je to **volitelný** override hostitele proxy (`actualHost`, bez `required`),
|
|
536
|
+
takže by řádek vyžadoval klíč, který knihovna nepotřebuje; služby, které přes proxy jdou, ho deklarují tam, kde
|
|
537
|
+
ho čtou — placeholder `${MINIO_ACTUAL_HOST}` v `config/service/config.json`, což je pokrytí M1. Dopad na dva
|
|
538
|
+
další čtenáře téže množiny: M2 (`envContract.js`) pokrývá u služby s `minio: true` nově všech pět jmen, takže
|
|
539
|
+
`--env-reads` je vydá deploy bráně (všechny osmery `shared.env` je nesou); a krok bootu
|
|
540
|
+
`verifyConnectorContract` se dál ptá „aspoň jedno z nich", ale `MINIO_ACTUAL_HOST` sám o sobě už důkazem není.
|
|
541
|
+
|
|
542
|
+
### Removed — `checks/scriptHeaders.js` nevyváží ani `SCRIPT_SCOPE` (d.636d, W636)
|
|
543
|
+
|
|
544
|
+
Druhý re-export téhož druhu: vznikl s modulem v d.218 (`c2aa5367`) a čtenáře nikdy neměl — všichni tři
|
|
545
|
+
(`oa-lint-scripts.js`, `lintScripts.js`, `lintScripts.test.js`) ho od začátku berou od vlastníka
|
|
546
|
+
`src/lint/scripts/lintScripts.js`. Most řádku `S-SCRIPTS` teď vyváží jen `checks`.
|
|
547
|
+
|
|
548
|
+
### Removed — `checks/scriptHeaders.js` nevyváží `API_CHECKOUT` (d.636c, W636)
|
|
549
|
+
|
|
550
|
+
Jméno vzniklo s modulem v d.218 (`c2aa5367`) a čtenáře nikdy nemělo (`git grep -w` v každém commitu, který se
|
|
551
|
+
symbolu dotkl). Konvenci „hlava cesty je `api/`" vlastní od d.636b `workspaceRoot.API_PREFIX`; most řádku
|
|
552
|
+
`S-SCRIPTS` ji čte, ale nevydává pod druhým jménem. Věta NOT RUN se nemění a měří ji `manifestScriptHeaders`.
|
|
553
|
+
|
|
554
|
+
### Documentation — příklad běhu živých DB sad nevypisuje soubory (d.636c, W636)
|
|
555
|
+
|
|
556
|
+
Vývojářský příkaz v § Running the live-database suites bral dvě sady ze tří; výběr teď dělá požadavek na
|
|
557
|
+
`tests/helpers/liveDatabase.js` (`npx jest $(grep -rl …)`), takže nová sada se přidá bez editace README.
|
|
558
|
+
|
|
559
|
+
### Changed — prefix `api/` má jednoho vlastníka; čtenáři ho berou symbolem (d.636b, W636)
|
|
560
|
+
|
|
561
|
+
`workspaceRoot.js` vyváží `API_PREFIX`; `lintScripts.js` (dosud vlastní literál `'api/'`), řádek `scripts-lint`
|
|
562
|
+
a `readmeLocation.js` (dosud dvakrát hlava `WORKSPACE_MARKER`) čtou jeho hodnotu. Chování beze změny; sonda nad
|
|
563
|
+
`src/**` v `manifestWorkspaceRoot.test.js` hlídá, že druhé znění prefixu nepřibude.
|
|
564
|
+
|
|
565
|
+
### Documentation — § Running the live-database suites nedrží vlastní počet sad (d.636a, W636)
|
|
566
|
+
|
|
567
|
+
Věta o živých DB sadách už nejmenuje „dvě“ (od d.620b jsou tři) ani je nevypisuje — seznamem je `script` jobu
|
|
568
|
+
`test-validator-db` v `api/.gitlab-ci.yml` a požadavek na `tests/helpers/liveDatabase.js`.
|
|
569
|
+
|
|
570
|
+
### Fixed — řádek `oa-sync-template` jmenuje blok, když měřil jen blok (d.610)
|
|
571
|
+
|
|
572
|
+
U blokového řádku (`F-INIT`, `F-RUNNER`, `G-CI`) hlásí generátor `unchanged F-INIT init.sh (block "oa-deps-guard v1")` —
|
|
573
|
+
porovnal jen obsah uvnitř značek, zbytek souboru je vlastnictví služby. Řádek celého souboru závorku nemá. Kdo parsuje
|
|
574
|
+
výstup `oa-sync-template` doslova, uvidí u blokových řádků závorku navíc.
|
|
575
|
+
|
|
576
|
+
### Changed — BREAKING: pravidla `operations.json` mají jednoho vlastníka (d.465, d.465b, d.465c)
|
|
577
|
+
|
|
578
|
+
Pravidla o JEDNÉ operaci se všude (krok 1, krok 4, readiness skóre, sada `createServiceReadinessTests`, řádek `C-OPS`) ptají
|
|
579
|
+
zrcadla registru `validateOperationsSchema` z `@onlineapps/service-validator-core` přes `src/utils/operationsRules.js` —
|
|
580
|
+
lokální kontrola tedy nově odmítne i `mutates`, `resource_type` a klíč operace, které registr odmítá. Pravidla o DOKUMENTU
|
|
581
|
+
(`src/utils/operationsDocumentRules.js`): prázdná mapa operací je všude error a `schema_version` musí být deklarován a roven
|
|
582
|
+
`"3.0"`; typy nálezů kroku 1 `INVALID_OPERATIONS_STRUCTURE`, `INVALID_OPERATIONS_TYPE`, `NO_OPERATIONS` a
|
|
583
|
+
`SCHEMA_VERSION_MISMATCH` zanikají ve prospěch `INVALID_OPERATIONS_DOCUMENT`. Úplnost deklarace (`input`, `output`,
|
|
584
|
+
`description`) hlásí krok 4 i readiness touž větou (`operationsDeclarationFindings()`). Exportované API se nemění;
|
|
585
|
+
změřeno nad `api_biz/*`: verdikty `oa-validate` před a po shodné.
|
|
586
|
+
|
|
587
|
+
### Documentation — komentáře `src/**` bez čísel řádků; `setupDurationMs` rozlišuje jednorázovou a opakovanou cenu (d.795b, d.795c, d.981)
|
|
588
|
+
|
|
589
|
+
Jen komentáře a docblocky, chování beze změny. `CookbookTestRunner.js` (u `setupDurationMs`
|
|
590
|
+
na dvou místech) už netvrdí, že čtení `operations.json` i `require()` modulu jsou „a one-off
|
|
591
|
+
cost per process": `require()` Node po prvním kroku podá z registru modulů, ale
|
|
592
|
+
`resolveOperation()` čte `config/service/operations.json` z disku při každém kroku
|
|
593
|
+
(změřeno d.795b: pět volání → pět čtení) (d.795b, d.795c). Čísla řádků v komentářích
|
|
594
|
+
`src/**` (`createServiceReadinessTests.js`, `mocks/MockMQClient.js`, `utils/cookbookFormat.js`,
|
|
595
|
+
`utils/envContract.js`, `validators/ServiceStructureValidator.js`) nahradily symboly (d.981).
|
|
596
|
+
|
|
597
|
+
### Removed — `TESTING_STRATEGY.md` odstraněn (0 čtenářů) (d.1020)
|
|
598
|
+
|
|
599
|
+
- Dokument nečetl žádný soubor v balíčku ani v repozitáři, a tak zmizel z repozitáře i z tarballu;
|
|
600
|
+
`npm pack --dry-run` ubral právě tento soubor. `docs/DESIGN.md` se balí dál — odkazuje na něj
|
|
601
|
+
balený `src/helpers/README.md`.
|
|
602
|
+
|
|
603
|
+
## [12.2.0] — 2026-09-26
|
|
604
|
+
### Changed — šablona biz CI: obraz se staví jen na `main`, produkce nasazuje digest z registru (d.671, d.671b; conf image-promotion 001)
|
|
605
|
+
|
|
606
|
+
Job `build` v `templates/business-service/.gitlab-ci.yml` běží jen na `main` a před stavbou se ptá
|
|
607
|
+
registru, zda tag `:$CI_COMMIT_SHA` už existuje (existuje → nestaví a vypíše digest); tag se nikdy
|
|
608
|
+
nepřepíše. `deploy-production` nebere digest z dotenv artefaktu (`dependencies: []`), ale týmž
|
|
609
|
+
dotazem do registru (`.oa-registry-digest`); když obraz pro commit nenajde, zastaví nasazení
|
|
610
|
+
jmenovanou hláškou a nikdy nestaví náhradu. Fixtury manifestu nesou tentýž blok `oa-ci v1`;
|
|
611
|
+
tvar i tělo dotazu měří `tests/unit/templateImagePromotion.test.js`
|
|
612
|
+
a `tests/unit/templateImagePromotionShell.integration.test.js`.
|
|
613
|
+
|
|
7
614
|
## [12.1.1] — 2026-09-25
|
|
8
615
|
|
|
9
616
|
### Fixed — `verify-deploy-uniform.sh`: rada při checkoutu mimo `api_biz/` vede na cestu, kterou šablona skutečně deklaruje (d.899)
|