@spottoai/types-package 1.0.2-beta.360 → 1.0.2-beta.364

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 (37) hide show
  1. package/README.md +38 -0
  2. package/dist/azure/billingArtifactCanonicalization.d.ts +3 -1
  3. package/dist/azure/billingArtifactCanonicalization.d.ts.map +1 -1
  4. package/dist/azure/billingArtifactCanonicalization.js +123 -43
  5. package/dist/azure/billingArtifactCanonicalization.js.map +1 -1
  6. package/dist/azure/billingArtifactGeneration.d.ts +53 -1
  7. package/dist/azure/billingArtifactGeneration.d.ts.map +1 -1
  8. package/dist/azure/billingArtifactGeneration.js +190 -25
  9. package/dist/azure/billingArtifactGeneration.js.map +1 -1
  10. package/dist/azure/billingArtifactLimits.d.ts +19 -0
  11. package/dist/azure/billingArtifactLimits.d.ts.map +1 -0
  12. package/dist/azure/billingArtifactLimits.js +22 -0
  13. package/dist/azure/billingArtifactLimits.js.map +1 -0
  14. package/dist/azure/billingPlots.d.ts +26 -3
  15. package/dist/azure/billingPlots.d.ts.map +1 -1
  16. package/dist/azure/billingPlots.js +257 -10
  17. package/dist/azure/billingPlots.js.map +1 -1
  18. package/dist/azure/views.d.ts +60 -0
  19. package/dist/azure/views.d.ts.map +1 -1
  20. package/dist/azure/views.js +280 -4
  21. package/dist/azure/views.js.map +1 -1
  22. package/dist/common/artifactControlData.d.ts +16 -2
  23. package/dist/common/artifactControlData.d.ts.map +1 -1
  24. package/dist/common/artifactControlData.js +129 -23
  25. package/dist/common/artifactControlData.js.map +1 -1
  26. package/dist/esm/azure/billingArtifactCanonicalization.js +121 -42
  27. package/dist/esm/azure/billingArtifactGeneration.js +186 -25
  28. package/dist/esm/azure/billingArtifactLimits.js +18 -0
  29. package/dist/esm/azure/billingPlots.js +253 -10
  30. package/dist/esm/azure/views.js +278 -4
  31. package/dist/esm/common/artifactControlData.js +127 -22
  32. package/dist/esm/index.js +1 -0
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/package.json +4 -2
@@ -1 +1 @@
1
- {"version":3,"file":"artifactControlData.js","sourceRoot":"","sources":["../../src/common/artifactControlData.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"artifactControlData.js","sourceRoot":"","sources":["../../src/common/artifactControlData.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { ARTIFACT_CONTROL_DATA_MAX_VISITED_NODES, allowedArtifactReferenceField, containsForbiddenArtifactControlData, } from '../common/artifactControlData.js';
1
2
  const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
2
3
  const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
3
4
  const requirePlainRecord = (value, name) => {
@@ -158,6 +159,47 @@ const projectPublicationDecision = (value) => {
158
159
  issues: issues.map(projectIssue),
159
160
  };
160
161
  };
162
+ const projectPromotionEvaluation = (value) => {
163
+ const source = requirePlainRecord(value, 'Billing promotion observation evaluation');
164
+ const projected = {
165
+ comparison: readDataProperty(source, 'comparison'),
166
+ projectedOutcome: readDataProperty(source, 'projectedOutcome'),
167
+ };
168
+ selectOptional(source, projected, 'outputDigestRelation');
169
+ return projected;
170
+ };
171
+ const projectPromotionObservation = (value) => {
172
+ const source = requirePlainRecord(value, 'Billing promotion observation');
173
+ const observationDigest = readDataProperty(source, 'observationDigest');
174
+ if (typeof observationDigest !== 'string')
175
+ throw new TypeError('Billing promotion observation requires an observationDigest string.');
176
+ const projected = {
177
+ schemaVersion: readDataProperty(source, 'schemaVersion'),
178
+ documentType: readDataProperty(source, 'documentType'),
179
+ authority: readDataProperty(source, 'authority'),
180
+ publicationMode: readDataProperty(source, 'publicationMode'),
181
+ processingState: readDataProperty(source, 'processingState'),
182
+ subscriptionId: readDataProperty(source, 'subscriptionId'),
183
+ generationId: readDataProperty(source, 'generationId'),
184
+ ownership: projectOwnership(readDataProperty(source, 'ownership')),
185
+ revision: projectRevision(readDataProperty(source, 'revision')),
186
+ messageId: readDataProperty(source, 'messageId'),
187
+ correlationId: readDataProperty(source, 'correlationId'),
188
+ inputManifestPath: readDataProperty(source, 'inputManifestPath'),
189
+ inputManifestDigest: readDataProperty(source, 'inputManifestDigest'),
190
+ outputManifestPath: readDataProperty(source, 'outputManifestPath'),
191
+ outputManifestDigest: readDataProperty(source, 'outputManifestDigest'),
192
+ evaluation: projectPromotionEvaluation(readDataProperty(source, 'evaluation')),
193
+ observedAt: readDataProperty(source, 'observedAt'),
194
+ };
195
+ if (containsForbiddenArtifactControlData(projected, [
196
+ ...allowedArtifactReferenceField(projected, 'inputManifestPath'),
197
+ ...allowedArtifactReferenceField(projected, 'outputManifestPath'),
198
+ ])) {
199
+ throw new TypeError('Billing promotion observation contains forbidden control data.');
200
+ }
201
+ return projected;
202
+ };
161
203
  const projectBinding = (subscriptionId, generationId, ownership, revision, inputManifestDigest, publicationDecision) => ({
162
204
  kind: 'billing-analysis-output',
163
205
  schemaVersion: 1,
@@ -180,68 +222,103 @@ export const projectBillingOutputBindingV1FromMetadata = (metadata) => {
180
222
  };
181
223
  const canonicalizeJson = (value) => {
182
224
  const active = new Set();
183
- const serialize = (candidate) => {
184
- if (candidate === null || typeof candidate === 'boolean')
185
- return JSON.stringify(candidate);
225
+ const fragments = [];
226
+ const pending = [{ kind: 'value', value }];
227
+ let visitedContainerCount = 0;
228
+ while (pending.length > 0) {
229
+ const frame = pending.pop();
230
+ if (frame === undefined)
231
+ break;
232
+ if (frame.kind === 'fragment') {
233
+ fragments.push(frame.value);
234
+ continue;
235
+ }
236
+ if (frame.kind === 'leave') {
237
+ active.delete(frame.value);
238
+ continue;
239
+ }
240
+ const candidate = frame.value;
241
+ if (candidate === null || typeof candidate === 'boolean') {
242
+ fragments.push(JSON.stringify(candidate));
243
+ continue;
244
+ }
186
245
  if (typeof candidate === 'string') {
187
246
  if (hasUnpairedSurrogate(candidate))
188
247
  throw new TypeError('Canonical JSON rejects invalid Unicode surrogate data.');
189
- return JSON.stringify(candidate);
248
+ fragments.push(JSON.stringify(candidate));
249
+ continue;
190
250
  }
191
251
  if (typeof candidate === 'number') {
192
252
  if (!Number.isFinite(candidate) || Object.is(candidate, -0) || (Number.isInteger(candidate) && !Number.isSafeInteger(candidate))) {
193
253
  throw new TypeError('Canonical JSON requires finite, safe, non-negative-zero numbers.');
194
254
  }
195
- return JSON.stringify(candidate);
255
+ fragments.push(JSON.stringify(candidate));
256
+ continue;
196
257
  }
197
258
  if (typeof candidate !== 'object' || candidate === undefined)
198
259
  throw new TypeError('Canonical JSON rejects non-JSON values.');
260
+ visitedContainerCount += 1;
261
+ if (visitedContainerCount > ARTIFACT_CONTROL_DATA_MAX_VISITED_NODES) {
262
+ throw new TypeError('Canonical JSON exceeds its 100000-container limit.');
263
+ }
199
264
  if (active.has(candidate))
200
265
  throw new TypeError('Canonical JSON rejects cyclic values.');
201
266
  active.add(candidate);
202
- try {
203
- if (Array.isArray(candidate)) {
204
- if (Object.getPrototypeOf(candidate) !== Array.prototype)
205
- throw new TypeError('Canonical JSON requires plain arrays.');
206
- const ownKeys = Reflect.ownKeys(candidate);
207
- if (ownKeys.some(key => typeof key === 'symbol') ||
208
- ownKeys.some(key => typeof key === 'string' && key !== 'length' && !/^(0|[1-9]\d*)$/.test(key))) {
209
- throw new TypeError('Canonical JSON arrays cannot contain custom properties.');
210
- }
211
- const values = [];
212
- for (let index = 0; index < candidate.length; index += 1) {
213
- if (!hasOwn(candidate, index))
214
- throw new TypeError('Canonical JSON rejects sparse arrays.');
215
- const descriptor = Object.getOwnPropertyDescriptor(candidate, String(index));
216
- if (descriptor === undefined || !('value' in descriptor) || !descriptor.enumerable || descriptor.value === undefined) {
217
- throw new TypeError('Canonical JSON array entries must be enumerable JSON values.');
218
- }
219
- values.push(serialize(descriptor.value));
220
- }
221
- return `[${values.join(',')}]`;
267
+ pending.push({ kind: 'leave', value: candidate });
268
+ if (Array.isArray(candidate)) {
269
+ if (Object.getPrototypeOf(candidate) !== Array.prototype)
270
+ throw new TypeError('Canonical JSON requires plain arrays.');
271
+ const ownKeys = Reflect.ownKeys(candidate);
272
+ if (ownKeys.some(key => typeof key === 'symbol') ||
273
+ ownKeys.some(key => typeof key === 'string' && key !== 'length' && !/^(0|[1-9]\d*)$/.test(key))) {
274
+ throw new TypeError('Canonical JSON arrays cannot contain custom properties.');
222
275
  }
223
- const prototype = Object.getPrototypeOf(candidate);
224
- if (prototype !== Object.prototype && prototype !== null)
225
- throw new TypeError('Canonical JSON requires plain objects.');
226
- if (Object.getOwnPropertySymbols(candidate).length > 0)
227
- throw new TypeError('Canonical JSON rejects symbol properties.');
228
- const entries = [];
229
- for (const key of Object.getOwnPropertyNames(candidate).sort()) {
230
- if (hasUnpairedSurrogate(key))
231
- throw new TypeError('Canonical JSON rejects invalid Unicode property names.');
232
- const descriptor = Object.getOwnPropertyDescriptor(candidate, key);
276
+ const values = [];
277
+ for (let index = 0; index < candidate.length; index += 1) {
278
+ if (!hasOwn(candidate, index))
279
+ throw new TypeError('Canonical JSON rejects sparse arrays.');
280
+ const descriptor = Object.getOwnPropertyDescriptor(candidate, String(index));
233
281
  if (descriptor === undefined || !('value' in descriptor) || !descriptor.enumerable || descriptor.value === undefined) {
234
- throw new TypeError('Canonical JSON object fields must be enumerable JSON values.');
282
+ throw new TypeError('Canonical JSON array entries must be enumerable JSON values.');
235
283
  }
236
- entries.push(`${JSON.stringify(key)}:${serialize(descriptor.value)}`);
284
+ values.push(descriptor.value);
237
285
  }
238
- return `{${entries.join(',')}}`;
286
+ fragments.push('[');
287
+ pending.push({ kind: 'fragment', value: ']' });
288
+ for (let index = values.length - 1; index >= 0; index -= 1) {
289
+ pending.push({ kind: 'value', value: values[index] });
290
+ if (index > 0)
291
+ pending.push({ kind: 'fragment', value: ',' });
292
+ }
293
+ continue;
294
+ }
295
+ const prototype = Object.getPrototypeOf(candidate);
296
+ if (prototype !== Object.prototype && prototype !== null)
297
+ throw new TypeError('Canonical JSON requires plain objects.');
298
+ if (Object.getOwnPropertySymbols(candidate).length > 0)
299
+ throw new TypeError('Canonical JSON rejects symbol properties.');
300
+ const entries = [];
301
+ for (const key of Object.getOwnPropertyNames(candidate).sort()) {
302
+ if (hasUnpairedSurrogate(key))
303
+ throw new TypeError('Canonical JSON rejects invalid Unicode property names.');
304
+ const descriptor = Object.getOwnPropertyDescriptor(candidate, key);
305
+ if (descriptor === undefined || !('value' in descriptor) || !descriptor.enumerable || descriptor.value === undefined) {
306
+ throw new TypeError('Canonical JSON object fields must be enumerable JSON values.');
307
+ }
308
+ entries.push({ key, value: descriptor.value });
239
309
  }
240
- finally {
241
- active.delete(candidate);
310
+ fragments.push('{');
311
+ pending.push({ kind: 'fragment', value: '}' });
312
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
313
+ const entry = entries[index];
314
+ pending.push({ kind: 'value', value: entry.value });
315
+ pending.push({
316
+ kind: 'fragment',
317
+ value: `${index > 0 ? ',' : ''}${JSON.stringify(entry.key)}:`,
318
+ });
242
319
  }
243
- };
244
- return serialize(value);
320
+ }
321
+ return fragments.join('');
245
322
  };
246
323
  const withoutManifestDigest = (manifest) => {
247
324
  const prototype = Object.getPrototypeOf(manifest);
@@ -277,5 +354,7 @@ export const canonicalizeBillingOutputBindingV1 = (binding) => {
277
354
  export const canonicalizeBillingAnalyzerInputManifestV2ForDigest = (manifest) => canonicalizeJson(withoutManifestDigest(manifest));
278
355
  /** Returns the canonical output-manifest digest preimage, excluding only top-level manifestDigest. */
279
356
  export const canonicalizeBillingAnalyzerOutputManifestV2ForDigest = (manifest) => canonicalizeJson(withoutManifestDigest(manifest));
357
+ /** Returns the exact promotion-observation digest preimage, excluding observationDigest and additive fields. */
358
+ export const canonicalizeBillingAnalysisPromotionObservationV1ForDigest = (observation) => canonicalizeJson(projectPromotionObservation(observation));
280
359
  /** Returns the RFC 8785/JCS-compatible canonical JSON string for a validated JSON value. */
281
360
  export const canonicalizeBillingArtifactJson = (value) => canonicalizeJson(value);
@@ -1,11 +1,34 @@
1
1
  import { isArtifactOwnershipBinding, isEnforceableArtifactOwnershipBinding, } from '../common/artifactEvidence.js';
2
2
  import { isArtifactRevisionVector, isStrictLogicalArtifactReference } from '../common/artifactEvidenceValidation.js';
3
- import { allowedArtifactIdentityField, allowedArtifactReferenceField, containsForbiddenArtifactControlData, } from '../common/artifactControlData.js';
3
+ import { ARTIFACT_CONTROL_DATA_MAX_VISITED_NODES, allowedArtifactIdentityField, allowedArtifactReferenceField, allowedArtifactTraversalField, containsForbiddenArtifactControlData, } from '../common/artifactControlData.js';
4
4
  import { isBillingCompletedArtifactPublicationDecision } from './billingArtifactEvidence.js';
5
+ import { BILLING_ARTIFACT_OBJECT_LIMITS_V1 } from './billingArtifactLimits.js';
6
+ /** Stable diagnostic-only suffix for the latest successfully enqueued observe input. */
7
+ export const BILLING_ANALYZER_INPUT_OBSERVATION_POINTER_RELATIVE_PATH = 'history/billing/analyzer-inputs/latest-enqueued.json';
5
8
  const BILLING_BASES = new Set(['actual', 'amortized']);
6
9
  const COVERAGE_VERDICTS = new Set(['complete', 'partial', 'none', 'unknown']);
7
10
  const DATE_BASES = new Set(['utc', 'billing-calendar', 'company-local']);
8
11
  const CONTENT_ENCODINGS = new Set(['identity', 'gzip']);
12
+ const OBSERVATION_COMPARISONS = new Set([
13
+ 'authority-absent',
14
+ 'newer',
15
+ 'equal',
16
+ 'older',
17
+ 'incomparable',
18
+ 'newer-ownership',
19
+ 'older-ownership',
20
+ 'unenforceable',
21
+ ]);
22
+ const OBSERVATION_PROJECTED_OUTCOMES = new Map([
23
+ ['authority-absent', 'would-promote'],
24
+ ['newer', 'would-promote'],
25
+ ['newer-ownership', 'would-promote'],
26
+ ['equal', 'would-be-idempotent'],
27
+ ['older', 'would-be-superseded'],
28
+ ['older-ownership', 'would-be-superseded'],
29
+ ['incomparable', 'would-quarantine'],
30
+ ['unenforceable', 'not-enforceable'],
31
+ ]);
9
32
  const SHA256_PATTERN = /^[a-f0-9]{64}$/;
10
33
  const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
11
34
  const isNonEmptyString = (value) => typeof value === 'string' && value.trim() === value && value.length > 0;
@@ -25,7 +48,23 @@ const isCanonicalIsoTimestamp = (value) => {
25
48
  };
26
49
  const hasControlCharacters = (value) => Array.from(value).some(character => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127);
27
50
  const allowedDescriptorPaths = (descriptors) => Array.isArray(descriptors) ? descriptors.flatMap(descriptor => allowedArtifactReferenceField(descriptor, 'path')) : [];
51
+ const containsForbiddenBillingArtifactControlData = (value, allowedReferenceFields = []) => containsForbiddenArtifactControlData(value, allowedReferenceFields, {
52
+ requireAllowedFieldTraversalContext: true,
53
+ });
28
54
  const isPathSegment = (value) => isNonEmptyString(value) && !/[\\/?#%]/.test(value) && !hasControlCharacters(value) && value !== '.' && value !== '..';
55
+ /** Builds the diagnostic-only latest-enqueued observation path for one safe subscription segment. */
56
+ export const buildBillingAnalyzerInputObservationPointerPath = (subscriptionId) => {
57
+ if (!isPathSegment(subscriptionId))
58
+ throw new TypeError('subscriptionId must be a safe path segment');
59
+ return `subscriptions/${subscriptionId}/${BILLING_ANALYZER_INPUT_OBSERVATION_POINTER_RELATIVE_PATH}`;
60
+ };
61
+ /** Validates the exact diagnostic-only latest-enqueued observation logical path. */
62
+ export const isBillingAnalyzerInputObservationPointerPath = (value) => {
63
+ if (!isStrictLogicalArtifactReference(value))
64
+ return false;
65
+ const match = /^subscriptions\/([^/]+)\/history\/billing\/analyzer-inputs\/latest-enqueued\.json$/.exec(value);
66
+ return match !== null && isPathSegment(match[1]);
67
+ };
29
68
  const inputGenerationPrefix = (subscriptionId, generationId) => `subscriptions/${subscriptionId}/history/billing/analyzer-inputs/generations/${generationId}/`;
30
69
  const inputManifestPath = (subscriptionId, generationId) => `${inputGenerationPrefix(subscriptionId, generationId)}manifest.json`;
31
70
  const outputGenerationPrefix = (subscriptionId, generationId) => `subscriptions/${subscriptionId}/billing/generations/${generationId}/`;
@@ -45,6 +84,9 @@ const hasMatchingIdentity = (subscriptionId, generationId, ownership, revision,
45
84
  return !enforceable || isEnforceableArtifactOwnershipBinding(ownership);
46
85
  };
47
86
  const isSha256 = (value) => typeof value === 'string' && SHA256_PATTERN.test(value);
87
+ const hasDiagnosticObservationDiscriminant = (value) => value.authority === 'diagnostic-only' ||
88
+ (value.publicationMode === 'observe' &&
89
+ (value.documentType === 'billing-analyzer-input-observation-pointer' || value.documentType === 'billing-analysis-promotion-observation'));
48
90
  const isRequestedPeriod = (value) => {
49
91
  if (!isRecord(value) ||
50
92
  !isCanonicalIsoTimestamp(value.fromInclusive) ||
@@ -65,6 +107,7 @@ const isInputObjectDescriptor = (value, subscriptionId, generationId) => {
65
107
  isNonEmptyString(value.etag) &&
66
108
  isSha256(value.sha256) &&
67
109
  isPositiveInteger(value.byteCount) &&
110
+ value.byteCount <= BILLING_ARTIFACT_OBJECT_LIMITS_V1.inputObjectStoredBytes &&
68
111
  isNonNegativeInteger(value.rowCount) &&
69
112
  isStringIn(value.basis, BILLING_BASES) &&
70
113
  (value.currencyCode === undefined || isNonEmptyString(value.currencyCode)) &&
@@ -74,31 +117,76 @@ const isOutputArtifactDescriptor = (value, subscriptionId, generationId) => {
74
117
  if (!isRecord(value))
75
118
  return false;
76
119
  const prefix = outputGenerationPrefix(subscriptionId, generationId);
77
- return (isGenerationPath(value.path, prefix, outputManifestPath(subscriptionId, generationId)) &&
78
- isNonEmptyString(value.name) &&
79
- value.mediaType === 'application/json' &&
80
- isStringIn(value.contentEncoding, CONTENT_ENCODINGS) &&
81
- isNonNegativeInteger(value.byteLength) &&
82
- isSha256(value.sha256));
120
+ if (!isGenerationPath(value.path, prefix, outputManifestPath(subscriptionId, generationId)) ||
121
+ !isPathSegment(value.name) ||
122
+ !((value.name === 'metadata.json' &&
123
+ value.path === `${prefix}metadata.json` &&
124
+ isNonNegativeInteger(value.byteLength) &&
125
+ value.byteLength <= BILLING_ARTIFACT_OBJECT_LIMITS_V1.metadataStoredBytes) ||
126
+ (value.name !== 'metadata.json' &&
127
+ value.path === `${prefix}plots/${value.name}` &&
128
+ isNonNegativeInteger(value.byteLength) &&
129
+ value.byteLength <= BILLING_ARTIFACT_OBJECT_LIMITS_V1.plotStoredBytes))) {
130
+ return false;
131
+ }
132
+ return value.mediaType === 'application/json' && isStringIn(value.contentEncoding, CONTENT_ENCODINGS) && isSha256(value.sha256);
83
133
  };
84
134
  const isJsonMetadata = (value) => {
85
135
  if (!isRecord(value))
86
136
  return false;
87
- const visit = (candidate) => {
88
- if (candidate === null || typeof candidate === 'string' || typeof candidate === 'boolean')
89
- return true;
90
- if (isFiniteNumber(candidate))
91
- return true;
92
- if (Array.isArray(candidate))
93
- return candidate.every(visit);
94
- return isRecord(candidate) && Object.getPrototypeOf(candidate) === Object.prototype && Object.values(candidate).every(visit);
95
- };
96
- return visit(value);
137
+ const pending = [{ kind: 'visit', value }];
138
+ const activeContainers = new WeakSet();
139
+ const completedContainers = new WeakSet();
140
+ let visitedNodeCount = 0;
141
+ while (pending.length > 0) {
142
+ const candidate = pending.pop();
143
+ if (candidate.kind === 'leave') {
144
+ activeContainers.delete(candidate.container);
145
+ completedContainers.add(candidate.container);
146
+ continue;
147
+ }
148
+ if (candidate.value === null || typeof candidate.value === 'string' || typeof candidate.value === 'boolean' || isFiniteNumber(candidate.value)) {
149
+ continue;
150
+ }
151
+ if (Array.isArray(candidate.value)) {
152
+ visitedNodeCount += 1;
153
+ if (visitedNodeCount > ARTIFACT_CONTROL_DATA_MAX_VISITED_NODES)
154
+ return false;
155
+ if (activeContainers.has(candidate.value))
156
+ return false;
157
+ if (completedContainers.has(candidate.value))
158
+ continue;
159
+ activeContainers.add(candidate.value);
160
+ pending.push({ kind: 'leave', container: candidate.value });
161
+ for (let index = candidate.value.length - 1; index >= 0; index -= 1) {
162
+ pending.push({ kind: 'visit', value: candidate.value[index] });
163
+ }
164
+ continue;
165
+ }
166
+ if (!isRecord(candidate.value) || Object.getPrototypeOf(candidate.value) !== Object.prototype)
167
+ return false;
168
+ visitedNodeCount += 1;
169
+ if (visitedNodeCount > ARTIFACT_CONTROL_DATA_MAX_VISITED_NODES)
170
+ return false;
171
+ if (activeContainers.has(candidate.value))
172
+ return false;
173
+ if (completedContainers.has(candidate.value))
174
+ continue;
175
+ activeContainers.add(candidate.value);
176
+ pending.push({ kind: 'leave', container: candidate.value });
177
+ for (const child of Object.values(candidate.value))
178
+ pending.push({ kind: 'visit', value: child });
179
+ }
180
+ return true;
97
181
  };
98
182
  /** Validates one immutable billing analyzer input manifest without performing I/O. */
99
183
  export const isBillingAnalyzerInputManifestV2 = (value) => {
100
184
  if (!isRecord(value) ||
101
- containsForbiddenArtifactControlData(value, [...allowedArtifactIdentityField(value, 'publicationKey'), ...allowedDescriptorPaths(value.inputs)])) {
185
+ containsForbiddenBillingArtifactControlData(value, [
186
+ ...allowedArtifactIdentityField(value, 'publicationKey'),
187
+ ...allowedArtifactTraversalField(value, 'inputs'),
188
+ ...allowedDescriptorPaths(value.inputs),
189
+ ])) {
102
190
  return false;
103
191
  }
104
192
  if (value.schemaVersion !== 2 || value.status !== 'completed')
@@ -117,7 +205,7 @@ export const isBillingAnalyzerInputManifestV2 = (value) => {
117
205
  const periodKeys = value.requestedPeriods.map(period => `${period.fromInclusive}\n${period.throughExclusive}\n${period.dateBasis}\n${period.timeZone ?? ''}\n${period.basis}`);
118
206
  if (!hasUniqueValues(periodKeys))
119
207
  return false;
120
- if (!Array.isArray(value.inputs) || value.inputs.length === 0)
208
+ if (!Array.isArray(value.inputs) || value.inputs.length === 0 || value.inputs.length > BILLING_ARTIFACT_OBJECT_LIMITS_V1.maxInputObjects)
121
209
  return false;
122
210
  if (!value.inputs.every(input => isInputObjectDescriptor(input, value.subscriptionId, value.generationId)))
123
211
  return false;
@@ -125,7 +213,9 @@ export const isBillingAnalyzerInputManifestV2 = (value) => {
125
213
  };
126
214
  /** Validates the enforceable current pointer for one published analyzer input generation. */
127
215
  export const isBillingAnalyzerInputCurrentPointerV1 = (value) => {
128
- if (!isRecord(value) || containsForbiddenArtifactControlData(value, allowedArtifactReferenceField(value, 'manifestPath')))
216
+ if (!isRecord(value) ||
217
+ hasDiagnosticObservationDiscriminant(value) ||
218
+ containsForbiddenBillingArtifactControlData(value, allowedArtifactReferenceField(value, 'manifestPath')))
129
219
  return false;
130
220
  if (value.schemaVersion !== 1 || value.status !== 'completed')
131
221
  return false;
@@ -138,7 +228,7 @@ export const isBillingAnalyzerInputCurrentPointerV1 = (value) => {
138
228
  };
139
229
  /** Validates the V2 queue envelope and its immutable input-manifest binding. */
140
230
  export const isBillingAnalyzerRequestV2 = (value) => {
141
- if (!isRecord(value) || containsForbiddenArtifactControlData(value, allowedArtifactReferenceField(value, 'inputManifestPath')))
231
+ if (!isRecord(value) || containsForbiddenBillingArtifactControlData(value, allowedArtifactReferenceField(value, 'inputManifestPath')))
142
232
  return false;
143
233
  if (value.schemaVersion !== 2 || (value.publicationMode !== 'observe' && value.publicationMode !== 'enforce'))
144
234
  return false;
@@ -157,11 +247,32 @@ export const isBillingAnalyzerRequestV2 = (value) => {
157
247
  return false;
158
248
  return value.displayMetadata === undefined || isJsonMetadata(value.displayMetadata);
159
249
  };
250
+ /** Validates a diagnostic-only latest-enqueued pointer; it is never customer authority. */
251
+ export const isBillingAnalyzerInputObservationPointerV1 = (value) => {
252
+ if (!isRecord(value) || containsForbiddenBillingArtifactControlData(value, allowedArtifactReferenceField(value, 'inputManifestPath')))
253
+ return false;
254
+ if (value.schemaVersion !== 1 ||
255
+ value.documentType !== 'billing-analyzer-input-observation-pointer' ||
256
+ value.authority !== 'diagnostic-only' ||
257
+ value.publicationMode !== 'observe' ||
258
+ value.inputState !== 'enqueued') {
259
+ return false;
260
+ }
261
+ if (!hasMatchingIdentity(value.subscriptionId, value.generationId, value.ownership, value.revision, false))
262
+ return false;
263
+ return (isStrictLogicalArtifactReference(value.inputManifestPath) &&
264
+ value.inputManifestPath === inputManifestPath(value.subscriptionId, value.generationId) &&
265
+ isSha256(value.inputManifestDigest) &&
266
+ isSha256(value.messageId) &&
267
+ isNonEmptyString(value.correlationId) &&
268
+ isCanonicalIsoTimestamp(value.enqueuedAt));
269
+ };
160
270
  /** Validates an immutable analyzer output manifest and its exact input binding. */
161
271
  export const isBillingAnalyzerOutputManifestV2 = (value) => {
162
272
  if (!isRecord(value) ||
163
- containsForbiddenArtifactControlData(value, [
273
+ containsForbiddenBillingArtifactControlData(value, [
164
274
  ...allowedArtifactReferenceField(value, 'inputManifestPath'),
275
+ ...allowedArtifactTraversalField(value, 'artifacts'),
165
276
  ...allowedDescriptorPaths(value.artifacts),
166
277
  ])) {
167
278
  return false;
@@ -195,16 +306,16 @@ export const isBillingAnalyzerOutputManifestV2 = (value) => {
195
306
  publicationDecisionReferencesDigest(value.publicationDecision, new Set([...outputDerivedDigests].filter(digest => digest !== value.inputManifestDigest)))) {
196
307
  return false;
197
308
  }
198
- if (!value.artifacts.some(artifact => artifact.path === `${outputGenerationPrefix(value.subscriptionId, value.generationId)}metadata.json`)) {
309
+ if (value.artifacts.filter(artifact => artifact.name === 'metadata.json').length !== 1)
199
310
  return false;
200
- }
201
311
  return (isBillingCompletedArtifactPublicationDecision(value.publicationDecision, value.generationId, value.inputManifestDigest) &&
202
312
  isCanonicalIsoTimestamp(value.completedAt));
203
313
  };
204
314
  /** Validates the sole promoted authority pointer for completed billing analysis. */
205
315
  export const isBillingAnalysisCurrentPointerV1 = (value) => {
206
316
  if (!isRecord(value) ||
207
- containsForbiddenArtifactControlData(value, [
317
+ hasDiagnosticObservationDiscriminant(value) ||
318
+ containsForbiddenBillingArtifactControlData(value, [
208
319
  ...allowedArtifactReferenceField(value, 'inputManifestPath'),
209
320
  ...allowedArtifactReferenceField(value, 'outputManifestPath'),
210
321
  ])) {
@@ -227,3 +338,53 @@ export const isBillingAnalysisCurrentPointerV1 = (value) => {
227
338
  return (isBillingCompletedArtifactPublicationDecision(value.publicationDecision, value.generationId, value.inputManifestDigest) &&
228
339
  isCanonicalIsoTimestamp(value.completedAt));
229
340
  };
341
+ /** Validates an immutable diagnostic-only promotion evaluation. */
342
+ export const isBillingAnalysisPromotionObservationV1 = (value) => {
343
+ if (!isRecord(value) ||
344
+ containsForbiddenBillingArtifactControlData(value, [
345
+ ...allowedArtifactReferenceField(value, 'inputManifestPath'),
346
+ ...allowedArtifactReferenceField(value, 'outputManifestPath'),
347
+ ])) {
348
+ return false;
349
+ }
350
+ if (value.schemaVersion !== 1 ||
351
+ value.documentType !== 'billing-analysis-promotion-observation' ||
352
+ value.authority !== 'diagnostic-only' ||
353
+ value.publicationMode !== 'observe' ||
354
+ value.processingState !== 'succeeded') {
355
+ return false;
356
+ }
357
+ if (!hasMatchingIdentity(value.subscriptionId, value.generationId, value.ownership, value.revision, false))
358
+ return false;
359
+ if (!isStrictLogicalArtifactReference(value.inputManifestPath) ||
360
+ value.inputManifestPath !== inputManifestPath(value.subscriptionId, value.generationId) ||
361
+ !isStrictLogicalArtifactReference(value.outputManifestPath) ||
362
+ value.outputManifestPath !== outputManifestPath(value.subscriptionId, value.generationId)) {
363
+ return false;
364
+ }
365
+ if (!isSha256(value.inputManifestDigest) ||
366
+ !isSha256(value.outputManifestDigest) ||
367
+ !isSha256(value.observationDigest) ||
368
+ !isSha256(value.messageId) ||
369
+ !isNonEmptyString(value.correlationId) ||
370
+ !isCanonicalIsoTimestamp(value.observedAt) ||
371
+ !isRecord(value.evaluation) ||
372
+ !isStringIn(value.evaluation.comparison, OBSERVATION_COMPARISONS)) {
373
+ return false;
374
+ }
375
+ const hasOwnershipEpoch = value.ownership.ownershipEpochRevision !== undefined;
376
+ const outputDigestRelation = value.evaluation.outputDigestRelation;
377
+ if (outputDigestRelation !== undefined && outputDigestRelation !== 'same' && outputDigestRelation !== 'different')
378
+ return false;
379
+ if (!hasOwnershipEpoch) {
380
+ return (outputDigestRelation === undefined && value.evaluation.comparison === 'unenforceable' && value.evaluation.projectedOutcome === 'not-enforceable');
381
+ }
382
+ if (value.evaluation.comparison === 'equal') {
383
+ return outputDigestRelation === 'different'
384
+ ? value.evaluation.projectedOutcome === 'would-quarantine'
385
+ : value.evaluation.projectedOutcome === 'would-be-idempotent';
386
+ }
387
+ return (outputDigestRelation === undefined &&
388
+ value.evaluation.comparison !== 'unenforceable' &&
389
+ OBSERVATION_PROJECTED_OUTCOMES.get(value.evaluation.comparison) === value.evaluation.projectedOutcome);
390
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * V1 billing artifact object limits in bytes.
3
+ *
4
+ * `StoredBytes` limits apply to the exact persisted object before content
5
+ * decoding. `DecodedBytes` limits apply after decoding or decompression.
6
+ */
7
+ export const BILLING_ARTIFACT_OBJECT_LIMITS_V1 = Object.freeze({
8
+ pointerStoredBytes: 64 * 1024,
9
+ observationStoredBytes: 64 * 1024,
10
+ manifestStoredBytes: 1024 * 1024,
11
+ metadataStoredBytes: 4 * 1024 * 1024,
12
+ metadataDecodedBytes: 16 * 1024 * 1024,
13
+ plotStoredBytes: 32 * 1024 * 1024,
14
+ plotDecodedBytes: 128 * 1024 * 1024,
15
+ inputObjectStoredBytes: 32 * 1024 * 1024,
16
+ inputObjectDecodedBytes: 128 * 1024 * 1024,
17
+ maxInputObjects: 12,
18
+ });