@futdevpro/fsm-dynamo 1.20.6 → 1.20.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +28 -28
  2. package/__documentations/2026-08-23-atomic-rollback-manifest-contract.md +53 -53
  3. package/__documentations/2026-08-23-forms-v2-color-picker-settings.md +23 -0
  4. package/build/_modules/ngx-models/_enums/field-type.enum.d.ts +1 -0
  5. package/build/_modules/ngx-models/_enums/field-type.enum.d.ts.map +1 -1
  6. package/build/_modules/ngx-models/_enums/field-type.enum.js +1 -0
  7. package/build/_modules/ngx-models/_enums/field-type.enum.js.map +1 -1
  8. package/build/_modules/ngx-models/_models/control-models/forms-new/color-picker-field-new-settings.control-model.d.ts +14 -0
  9. package/build/_modules/ngx-models/_models/control-models/forms-new/color-picker-field-new-settings.control-model.d.ts.map +1 -0
  10. package/build/_modules/ngx-models/_models/control-models/forms-new/color-picker-field-new-settings.control-model.js +38 -0
  11. package/build/_modules/ngx-models/_models/control-models/forms-new/color-picker-field-new-settings.control-model.js.map +1 -0
  12. package/build/_modules/ngx-models/_models/control-models/forms-new/field-new-types.d.ts +2 -1
  13. package/build/_modules/ngx-models/_models/control-models/forms-new/field-new-types.d.ts.map +1 -1
  14. package/build/_modules/ngx-models/_models/control-models/forms-new/index.d.ts +1 -0
  15. package/build/_modules/ngx-models/_models/control-models/forms-new/index.d.ts.map +1 -1
  16. package/build/_modules/ngx-models/_models/control-models/forms-new/index.js +1 -0
  17. package/build/_modules/ngx-models/_models/control-models/forms-new/index.js.map +1 -1
  18. package/package.json +1 -1
  19. package/src/_modules/deployment/_collections/atomic-rollback-manifest.util.spec.ts +221 -221
  20. package/src/_modules/deployment/_collections/atomic-rollback-manifest.util.ts +455 -455
  21. package/src/_modules/deployment/_models/atomic-rollback-manifest.interface.ts +59 -59
  22. package/src/_modules/deployment/index.ts +2 -2
  23. package/src/_modules/ngx-models/_enums/field-type.enum.ts +5 -4
  24. package/src/_modules/ngx-models/_models/control-models/forms-new/color-picker-field-new-settings.control-model.ts +44 -0
  25. package/src/_modules/ngx-models/_models/control-models/forms-new/field-new-types.ts +5 -3
  26. package/src/_modules/ngx-models/_models/control-models/forms-new/forms-new.spec.ts +36 -5
  27. package/src/_modules/ngx-models/_models/control-models/forms-new/index.ts +3 -2
@@ -1,221 +1,221 @@
1
- import { DyFM_AtomicRollbackManifest_Util } from './atomic-rollback-manifest.util';
2
- import {
3
- DyFM_AtomicRollbackImage_Interface,
4
- DyFM_AtomicRollbackLocalValidation_Interface,
5
- DyFM_AtomicRollbackManifest_Interface,
6
- DyFM_AtomicRollbackPostCheck_Interface
7
- } from '../_models/atomic-rollback-manifest.interface';
8
-
9
- /** Builds one fully valid manifest for contract mutation tests. */
10
- const dyfm_createManifest: () => DyFM_AtomicRollbackManifest_Interface =
11
- (): DyFM_AtomicRollbackManifest_Interface => {
12
- const manifest: DyFM_AtomicRollbackManifest_Interface = {
13
- contractVersion: 'fdp-atomic-rollback-manifest/1',
14
- operationId: `rollback_${'1'.repeat(32)}`,
15
- environment: 'test',
16
- authority: {
17
- principalId: 'fdp-cdp',
18
- evidenceId: '2'.repeat(64),
19
- },
20
- sourceRevision: '3'.repeat(40),
21
- configuration: {
22
- revision: '4'.repeat(40),
23
- sha256: '5'.repeat(64),
24
- compatibilityVersion: 'ctm-db/1',
25
- policyChecksum: '6'.repeat(64),
26
- },
27
- images: [
28
- {
29
- service: 'company-toolmaker-server',
30
- version: '0.0.1',
31
- immutableReference: 'registry.example/company-toolmaker-server:release-0.0.1',
32
- mutableReference: 'registry.example/company-toolmaker-server:release',
33
- digest: `sha256:${'7'.repeat(64)}`,
34
- },
35
- {
36
- service: 'company-toolmaker-client',
37
- version: '0.0.1',
38
- immutableReference: 'registry.example/company-toolmaker-client:release-0.0.1',
39
- mutableReference: 'registry.example/company-toolmaker-client:release',
40
- digest: `sha256:${'8'.repeat(64)}`,
41
- },
42
- ],
43
- postChecks: [
44
- {
45
- checkId: 'server-readiness',
46
- service: 'company-toolmaker-server',
47
- endpoint: 'https://test-company-toolmaker.futdevpro.hu/readiness',
48
- expectedProbeContract: 'ctm-service-probe/4',
49
- },
50
- {
51
- checkId: 'client-smoke',
52
- service: 'company-toolmaker-client',
53
- endpoint: 'https://test-company-toolmaker.futdevpro.hu/',
54
- expectedProbeContract: 'ctm-client-smoke/1',
55
- },
56
- ],
57
- targetChecksum: '',
58
- };
59
-
60
- manifest.targetChecksum = DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(manifest);
61
-
62
- return manifest;
63
- };
64
-
65
- describe('| DyFM atomic rollback manifest', (): void => {
66
- it('| validates an exact manifest with order-independent service and post-check sets', (): void => {
67
- const manifest: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
68
- const checksum: string = manifest.targetChecksum;
69
-
70
- manifest.images.reverse();
71
- manifest.postChecks.reverse();
72
-
73
- expect(DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(manifest)).toBe(checksum);
74
- expect(checksum).toBe('2b416434a8d36c5b3305383eb1f2ecebae4057d30d2f46d986d04728225b58df');
75
- expect(DyFM_AtomicRollbackManifest_Util.validate(manifest)).toEqual(jasmine.objectContaining({
76
- valid: true,
77
- environment: 'test',
78
- operationId: manifest.operationId,
79
- targetChecksum: checksum,
80
- serviceCount: 2,
81
- postCheckCount: 2,
82
- gapCodes: [],
83
- }));
84
- });
85
-
86
- it('| ignores nested object insertion order when calculating the canonical checksum', (): void => {
87
- const manifest: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
88
- const reordered: DyFM_AtomicRollbackManifest_Interface = {
89
- ...manifest,
90
- authority: {
91
- evidenceId: manifest.authority.evidenceId,
92
- principalId: manifest.authority.principalId,
93
- },
94
- configuration: {
95
- policyChecksum: manifest.configuration.policyChecksum,
96
- compatibilityVersion: manifest.configuration.compatibilityVersion,
97
- sha256: manifest.configuration.sha256,
98
- revision: manifest.configuration.revision,
99
- },
100
- images: manifest.images.map((
101
- image: DyFM_AtomicRollbackImage_Interface,
102
- ): DyFM_AtomicRollbackImage_Interface => ({
103
- digest: image.digest,
104
- mutableReference: image.mutableReference,
105
- immutableReference: image.immutableReference,
106
- version: image.version,
107
- service: image.service,
108
- })),
109
- postChecks: manifest.postChecks.map((
110
- check: DyFM_AtomicRollbackPostCheck_Interface,
111
- ): DyFM_AtomicRollbackPostCheck_Interface => ({
112
- expectedProbeContract: check.expectedProbeContract,
113
- endpoint: check.endpoint,
114
- service: check.service,
115
- checkId: check.checkId,
116
- })),
117
- };
118
-
119
- expect(DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(reordered)).toBe(manifest.targetChecksum);
120
- expect(DyFM_AtomicRollbackManifest_Util.validate(reordered).valid).toBeTrue();
121
- });
122
-
123
- it('| rejects missing, duplicated and non-targeted service members', (): void => {
124
- const missing: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
125
-
126
- missing.images.pop();
127
- const duplicated: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
128
-
129
- duplicated.images[1] = { ...duplicated.images[0] };
130
-
131
- expect(DyFM_AtomicRollbackManifest_Util.validate(missing).gapCodes).toContain(
132
- 'FDP|ATOMIC_ROLLBACK|POST_CHECK_SERVICE_NOT_TARGETED',
133
- );
134
- expect(DyFM_AtomicRollbackManifest_Util.validate(duplicated).gapCodes).toContain(
135
- 'FDP|ATOMIC_ROLLBACK|IMAGE_SERVICE_DUPLICATED',
136
- );
137
- });
138
-
139
- it('| rejects tag, version, digest and repository substitution', (): void => {
140
- const mutable: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
141
-
142
- mutable.images[0].immutableReference = 'registry.example/company-toolmaker-server:release';
143
- const versionMismatch: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
144
-
145
- versionMismatch.images[0].version = '0.0.2';
146
- const digestInvalid: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
147
-
148
- digestInvalid.images[0].digest = 'sha256:not-a-digest';
149
- const repositoryMismatch: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
150
-
151
- repositoryMismatch.images[0].mutableReference = 'other.example/company-toolmaker-server:release';
152
-
153
- expect(DyFM_AtomicRollbackManifest_Util.validate(mutable).gapCodes).toContain(
154
- 'FDP|ATOMIC_ROLLBACK|IMAGE_IMMUTABLE_REFERENCE_INVALID|company-toolmaker-server',
155
- );
156
- expect(DyFM_AtomicRollbackManifest_Util.validate(versionMismatch).gapCodes).toContain(
157
- 'FDP|ATOMIC_ROLLBACK|IMAGE_IMMUTABLE_REFERENCE_INVALID|company-toolmaker-server',
158
- );
159
- expect(DyFM_AtomicRollbackManifest_Util.validate(digestInvalid).gapCodes).toContain(
160
- 'FDP|ATOMIC_ROLLBACK|IMAGE_DIGEST_INVALID|company-toolmaker-server',
161
- );
162
- expect(DyFM_AtomicRollbackManifest_Util.validate(repositoryMismatch).gapCodes).toContain(
163
- 'FDP|ATOMIC_ROLLBACK|IMAGE_REPOSITORY_MISMATCH|company-toolmaker-server',
164
- );
165
- });
166
-
167
- it('| rejects configuration, authority and target-checksum substitution', (): void => {
168
- const configuration: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
169
-
170
- configuration.configuration.sha256 = '9'.repeat(64);
171
- const authority: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
172
-
173
- authority.authority.evidenceId = 'not-evidence';
174
- const checksum: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
175
-
176
- checksum.targetChecksum = 'a'.repeat(64);
177
-
178
- expect(DyFM_AtomicRollbackManifest_Util.validate(configuration).gapCodes).toEqual([
179
- 'FDP|ATOMIC_ROLLBACK|TARGET_CHECKSUM_MISMATCH',
180
- ]);
181
- expect(DyFM_AtomicRollbackManifest_Util.validate(authority).gapCodes).toContain(
182
- 'FDP|ATOMIC_ROLLBACK|AUTHORITY_EVIDENCE_INVALID',
183
- );
184
- expect(DyFM_AtomicRollbackManifest_Util.validate(checksum).gapCodes).toEqual([
185
- 'FDP|ATOMIC_ROLLBACK|TARGET_CHECKSUM_MISMATCH',
186
- ]);
187
- });
188
-
189
- it('| rejects oversized operational references before they can expand evidence or work', (): void => {
190
- const imageReference: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
191
-
192
- imageReference.images[0].immutableReference =
193
- `registry.example/${'segment/'.repeat(70)}company-toolmaker-server:release-0.0.1`;
194
- imageReference.targetChecksum = DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(imageReference);
195
- const endpoint: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
196
-
197
- endpoint.postChecks[0].endpoint = `https://${'a'.repeat(2040)}.example/readiness`;
198
- endpoint.targetChecksum = DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(endpoint);
199
-
200
- expect(DyFM_AtomicRollbackManifest_Util.validate(imageReference).gapCodes).toContain(
201
- 'FDP|ATOMIC_ROLLBACK|IMAGE_IMMUTABLE_REFERENCE_INVALID|company-toolmaker-server',
202
- );
203
- expect(DyFM_AtomicRollbackManifest_Util.validate(endpoint).gapCodes).toContain(
204
- 'FDP|ATOMIC_ROLLBACK|POST_CHECK_ENDPOINT_INVALID|server-readiness',
205
- );
206
- });
207
-
208
- it('| never reflects unknown content in validation evidence', (): void => {
209
- const candidate: Record<string, unknown> = {
210
- ...dyfm_createManifest(),
211
- workbookName: 'sensitive-customer.xlsx',
212
- };
213
- const report: DyFM_AtomicRollbackLocalValidation_Interface = DyFM_AtomicRollbackManifest_Util.validate(candidate);
214
- const serialized: string = JSON.stringify(report);
215
-
216
- expect(report.gapCodes).toEqual([ 'FDP|ATOMIC_ROLLBACK|MANIFEST_SHAPE_INVALID' ]);
217
- expect(serialized).not.toContain('sensitive-customer');
218
- expect(serialized).not.toContain('registry.example');
219
- expect(serialized).not.toContain('workbookName');
220
- });
221
- });
1
+ import { DyFM_AtomicRollbackManifest_Util } from './atomic-rollback-manifest.util';
2
+ import {
3
+ DyFM_AtomicRollbackImage_Interface,
4
+ DyFM_AtomicRollbackLocalValidation_Interface,
5
+ DyFM_AtomicRollbackManifest_Interface,
6
+ DyFM_AtomicRollbackPostCheck_Interface
7
+ } from '../_models/atomic-rollback-manifest.interface';
8
+
9
+ /** Builds one fully valid manifest for contract mutation tests. */
10
+ const dyfm_createManifest: () => DyFM_AtomicRollbackManifest_Interface =
11
+ (): DyFM_AtomicRollbackManifest_Interface => {
12
+ const manifest: DyFM_AtomicRollbackManifest_Interface = {
13
+ contractVersion: 'fdp-atomic-rollback-manifest/1',
14
+ operationId: `rollback_${'1'.repeat(32)}`,
15
+ environment: 'test',
16
+ authority: {
17
+ principalId: 'fdp-cdp',
18
+ evidenceId: '2'.repeat(64),
19
+ },
20
+ sourceRevision: '3'.repeat(40),
21
+ configuration: {
22
+ revision: '4'.repeat(40),
23
+ sha256: '5'.repeat(64),
24
+ compatibilityVersion: 'ctm-db/1',
25
+ policyChecksum: '6'.repeat(64),
26
+ },
27
+ images: [
28
+ {
29
+ service: 'company-toolmaker-server',
30
+ version: '0.0.1',
31
+ immutableReference: 'registry.example/company-toolmaker-server:release-0.0.1',
32
+ mutableReference: 'registry.example/company-toolmaker-server:release',
33
+ digest: `sha256:${'7'.repeat(64)}`,
34
+ },
35
+ {
36
+ service: 'company-toolmaker-client',
37
+ version: '0.0.1',
38
+ immutableReference: 'registry.example/company-toolmaker-client:release-0.0.1',
39
+ mutableReference: 'registry.example/company-toolmaker-client:release',
40
+ digest: `sha256:${'8'.repeat(64)}`,
41
+ },
42
+ ],
43
+ postChecks: [
44
+ {
45
+ checkId: 'server-readiness',
46
+ service: 'company-toolmaker-server',
47
+ endpoint: 'https://test-company-toolmaker.futdevpro.hu/readiness',
48
+ expectedProbeContract: 'ctm-service-probe/4',
49
+ },
50
+ {
51
+ checkId: 'client-smoke',
52
+ service: 'company-toolmaker-client',
53
+ endpoint: 'https://test-company-toolmaker.futdevpro.hu/',
54
+ expectedProbeContract: 'ctm-client-smoke/1',
55
+ },
56
+ ],
57
+ targetChecksum: '',
58
+ };
59
+
60
+ manifest.targetChecksum = DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(manifest);
61
+
62
+ return manifest;
63
+ };
64
+
65
+ describe('| DyFM atomic rollback manifest', (): void => {
66
+ it('| validates an exact manifest with order-independent service and post-check sets', (): void => {
67
+ const manifest: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
68
+ const checksum: string = manifest.targetChecksum;
69
+
70
+ manifest.images.reverse();
71
+ manifest.postChecks.reverse();
72
+
73
+ expect(DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(manifest)).toBe(checksum);
74
+ expect(checksum).toBe('2b416434a8d36c5b3305383eb1f2ecebae4057d30d2f46d986d04728225b58df');
75
+ expect(DyFM_AtomicRollbackManifest_Util.validate(manifest)).toEqual(jasmine.objectContaining({
76
+ valid: true,
77
+ environment: 'test',
78
+ operationId: manifest.operationId,
79
+ targetChecksum: checksum,
80
+ serviceCount: 2,
81
+ postCheckCount: 2,
82
+ gapCodes: [],
83
+ }));
84
+ });
85
+
86
+ it('| ignores nested object insertion order when calculating the canonical checksum', (): void => {
87
+ const manifest: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
88
+ const reordered: DyFM_AtomicRollbackManifest_Interface = {
89
+ ...manifest,
90
+ authority: {
91
+ evidenceId: manifest.authority.evidenceId,
92
+ principalId: manifest.authority.principalId,
93
+ },
94
+ configuration: {
95
+ policyChecksum: manifest.configuration.policyChecksum,
96
+ compatibilityVersion: manifest.configuration.compatibilityVersion,
97
+ sha256: manifest.configuration.sha256,
98
+ revision: manifest.configuration.revision,
99
+ },
100
+ images: manifest.images.map((
101
+ image: DyFM_AtomicRollbackImage_Interface,
102
+ ): DyFM_AtomicRollbackImage_Interface => ({
103
+ digest: image.digest,
104
+ mutableReference: image.mutableReference,
105
+ immutableReference: image.immutableReference,
106
+ version: image.version,
107
+ service: image.service,
108
+ })),
109
+ postChecks: manifest.postChecks.map((
110
+ check: DyFM_AtomicRollbackPostCheck_Interface,
111
+ ): DyFM_AtomicRollbackPostCheck_Interface => ({
112
+ expectedProbeContract: check.expectedProbeContract,
113
+ endpoint: check.endpoint,
114
+ service: check.service,
115
+ checkId: check.checkId,
116
+ })),
117
+ };
118
+
119
+ expect(DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(reordered)).toBe(manifest.targetChecksum);
120
+ expect(DyFM_AtomicRollbackManifest_Util.validate(reordered).valid).toBeTrue();
121
+ });
122
+
123
+ it('| rejects missing, duplicated and non-targeted service members', (): void => {
124
+ const missing: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
125
+
126
+ missing.images.pop();
127
+ const duplicated: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
128
+
129
+ duplicated.images[1] = { ...duplicated.images[0] };
130
+
131
+ expect(DyFM_AtomicRollbackManifest_Util.validate(missing).gapCodes).toContain(
132
+ 'FDP|ATOMIC_ROLLBACK|POST_CHECK_SERVICE_NOT_TARGETED',
133
+ );
134
+ expect(DyFM_AtomicRollbackManifest_Util.validate(duplicated).gapCodes).toContain(
135
+ 'FDP|ATOMIC_ROLLBACK|IMAGE_SERVICE_DUPLICATED',
136
+ );
137
+ });
138
+
139
+ it('| rejects tag, version, digest and repository substitution', (): void => {
140
+ const mutable: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
141
+
142
+ mutable.images[0].immutableReference = 'registry.example/company-toolmaker-server:release';
143
+ const versionMismatch: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
144
+
145
+ versionMismatch.images[0].version = '0.0.2';
146
+ const digestInvalid: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
147
+
148
+ digestInvalid.images[0].digest = 'sha256:not-a-digest';
149
+ const repositoryMismatch: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
150
+
151
+ repositoryMismatch.images[0].mutableReference = 'other.example/company-toolmaker-server:release';
152
+
153
+ expect(DyFM_AtomicRollbackManifest_Util.validate(mutable).gapCodes).toContain(
154
+ 'FDP|ATOMIC_ROLLBACK|IMAGE_IMMUTABLE_REFERENCE_INVALID|company-toolmaker-server',
155
+ );
156
+ expect(DyFM_AtomicRollbackManifest_Util.validate(versionMismatch).gapCodes).toContain(
157
+ 'FDP|ATOMIC_ROLLBACK|IMAGE_IMMUTABLE_REFERENCE_INVALID|company-toolmaker-server',
158
+ );
159
+ expect(DyFM_AtomicRollbackManifest_Util.validate(digestInvalid).gapCodes).toContain(
160
+ 'FDP|ATOMIC_ROLLBACK|IMAGE_DIGEST_INVALID|company-toolmaker-server',
161
+ );
162
+ expect(DyFM_AtomicRollbackManifest_Util.validate(repositoryMismatch).gapCodes).toContain(
163
+ 'FDP|ATOMIC_ROLLBACK|IMAGE_REPOSITORY_MISMATCH|company-toolmaker-server',
164
+ );
165
+ });
166
+
167
+ it('| rejects configuration, authority and target-checksum substitution', (): void => {
168
+ const configuration: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
169
+
170
+ configuration.configuration.sha256 = '9'.repeat(64);
171
+ const authority: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
172
+
173
+ authority.authority.evidenceId = 'not-evidence';
174
+ const checksum: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
175
+
176
+ checksum.targetChecksum = 'a'.repeat(64);
177
+
178
+ expect(DyFM_AtomicRollbackManifest_Util.validate(configuration).gapCodes).toEqual([
179
+ 'FDP|ATOMIC_ROLLBACK|TARGET_CHECKSUM_MISMATCH',
180
+ ]);
181
+ expect(DyFM_AtomicRollbackManifest_Util.validate(authority).gapCodes).toContain(
182
+ 'FDP|ATOMIC_ROLLBACK|AUTHORITY_EVIDENCE_INVALID',
183
+ );
184
+ expect(DyFM_AtomicRollbackManifest_Util.validate(checksum).gapCodes).toEqual([
185
+ 'FDP|ATOMIC_ROLLBACK|TARGET_CHECKSUM_MISMATCH',
186
+ ]);
187
+ });
188
+
189
+ it('| rejects oversized operational references before they can expand evidence or work', (): void => {
190
+ const imageReference: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
191
+
192
+ imageReference.images[0].immutableReference =
193
+ `registry.example/${'segment/'.repeat(70)}company-toolmaker-server:release-0.0.1`;
194
+ imageReference.targetChecksum = DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(imageReference);
195
+ const endpoint: DyFM_AtomicRollbackManifest_Interface = dyfm_createManifest();
196
+
197
+ endpoint.postChecks[0].endpoint = `https://${'a'.repeat(2040)}.example/readiness`;
198
+ endpoint.targetChecksum = DyFM_AtomicRollbackManifest_Util.computeTargetChecksum(endpoint);
199
+
200
+ expect(DyFM_AtomicRollbackManifest_Util.validate(imageReference).gapCodes).toContain(
201
+ 'FDP|ATOMIC_ROLLBACK|IMAGE_IMMUTABLE_REFERENCE_INVALID|company-toolmaker-server',
202
+ );
203
+ expect(DyFM_AtomicRollbackManifest_Util.validate(endpoint).gapCodes).toContain(
204
+ 'FDP|ATOMIC_ROLLBACK|POST_CHECK_ENDPOINT_INVALID|server-readiness',
205
+ );
206
+ });
207
+
208
+ it('| never reflects unknown content in validation evidence', (): void => {
209
+ const candidate: Record<string, unknown> = {
210
+ ...dyfm_createManifest(),
211
+ workbookName: 'sensitive-customer.xlsx',
212
+ };
213
+ const report: DyFM_AtomicRollbackLocalValidation_Interface = DyFM_AtomicRollbackManifest_Util.validate(candidate);
214
+ const serialized: string = JSON.stringify(report);
215
+
216
+ expect(report.gapCodes).toEqual([ 'FDP|ATOMIC_ROLLBACK|MANIFEST_SHAPE_INVALID' ]);
217
+ expect(serialized).not.toContain('sensitive-customer');
218
+ expect(serialized).not.toContain('registry.example');
219
+ expect(serialized).not.toContain('workbookName');
220
+ });
221
+ });