@spottoai/types-package 1.0.2-beta.361 → 1.0.2-beta.365
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/README.md +10 -0
- package/dist/azure/billingPlots.d.ts +19 -0
- package/dist/azure/billingPlots.d.ts.map +1 -1
- package/dist/azure/billingPlots.js +42 -1
- package/dist/azure/billingPlots.js.map +1 -1
- package/dist/azure/costComposition.d.ts +35 -0
- package/dist/azure/costComposition.d.ts.map +1 -1
- package/dist/azure/costComposition.js +49 -0
- package/dist/azure/costComposition.js.map +1 -1
- package/dist/azure/views.d.ts +60 -0
- package/dist/azure/views.d.ts.map +1 -1
- package/dist/azure/views.js +265 -1
- package/dist/azure/views.js.map +1 -1
- package/dist/esm/azure/billingPlots.js +40 -0
- package/dist/esm/azure/costComposition.js +47 -1
- package/dist/esm/azure/views.js +262 -0
- package/package.json +1 -1
package/dist/esm/azure/views.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { allowedArtifactReferenceField, allowedArtifactTraversalField, containsForbiddenArtifactControlData, } from '../common/artifactControlData.js';
|
|
2
2
|
import { isArtifactOwnershipBinding, isArtifactPublicationDecision, isEnforceableArtifactOwnershipBinding, } from '../common/artifactEvidence.js';
|
|
3
3
|
import { isArtifactRevisionVector, isStrictLogicalArtifactReference } from '../common/artifactEvidenceValidation.js';
|
|
4
|
+
export const PUBLISHED_VIEW_OBJECT_LIMITS_V1 = {
|
|
5
|
+
maxArtifacts: 512,
|
|
6
|
+
maxClaims: 128,
|
|
7
|
+
maxDependencies: 256,
|
|
8
|
+
maxIssues: 512,
|
|
9
|
+
maxClaimBindings: 512,
|
|
10
|
+
maxSectionPaths: 512,
|
|
11
|
+
};
|
|
4
12
|
const isNonEmptyString = (value) => typeof value === 'string' && value.trim().length > 0;
|
|
5
13
|
const isCanonicalIsoTimestamp = (value) => {
|
|
6
14
|
if (!isNonEmptyString(value))
|
|
@@ -73,6 +81,120 @@ const isViewArtifactDescriptor = (value, runId) => isRecord(value) &&
|
|
|
73
81
|
VIEW_CONTENT_ENCODINGS.has(value.contentEncoding) &&
|
|
74
82
|
isNonNegativeSafeInteger(value.byteLength) &&
|
|
75
83
|
isSha256(value.sha256);
|
|
84
|
+
const isPublishedViewCoverage = (value) => value === 'complete' || value === 'partial';
|
|
85
|
+
const isProjectedSectionPathForArtifact = (value, artifactPath) => {
|
|
86
|
+
if (!isStrictNonEmptyString(value))
|
|
87
|
+
return false;
|
|
88
|
+
if (value === artifactPath)
|
|
89
|
+
return true;
|
|
90
|
+
if (!value.startsWith(`${artifactPath}#/`))
|
|
91
|
+
return false;
|
|
92
|
+
const pointer = value.slice(artifactPath.length + 1);
|
|
93
|
+
return !pointer.includes('\\') && !pointer.includes('?') && !/%(?:2f|2F|5c|5C)/.test(pointer);
|
|
94
|
+
};
|
|
95
|
+
const parseProjectedSectionPath = (value) => {
|
|
96
|
+
const fragmentIndex = value.indexOf('#');
|
|
97
|
+
const artifactPath = fragmentIndex < 0 ? value : value.slice(0, fragmentIndex);
|
|
98
|
+
if (!isStrictLogicalArtifactReference(artifactPath) || !isProjectedSectionPathForArtifact(value, artifactPath))
|
|
99
|
+
return undefined;
|
|
100
|
+
return {
|
|
101
|
+
artifactPath,
|
|
102
|
+
pointerSegments: fragmentIndex < 0 ? [] : value.slice(fragmentIndex + 2).split('/'),
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
const doProjectedSectionsOverlap = (left, right) => {
|
|
106
|
+
const parsedLeft = parseProjectedSectionPath(left);
|
|
107
|
+
const parsedRight = parseProjectedSectionPath(right);
|
|
108
|
+
if (!parsedLeft || !parsedRight || parsedLeft.artifactPath !== parsedRight.artifactPath)
|
|
109
|
+
return false;
|
|
110
|
+
if (parsedLeft.pointerSegments.length === 0 || parsedRight.pointerSegments.length === 0)
|
|
111
|
+
return true;
|
|
112
|
+
const sharedLength = Math.min(parsedLeft.pointerSegments.length, parsedRight.pointerSegments.length);
|
|
113
|
+
for (let index = 0; index < sharedLength; index += 1) {
|
|
114
|
+
const leftSegment = parsedLeft.pointerSegments[index];
|
|
115
|
+
const rightSegment = parsedRight.pointerSegments[index];
|
|
116
|
+
if (leftSegment === rightSegment)
|
|
117
|
+
continue;
|
|
118
|
+
if (leftSegment === '*' || leftSegment === '**' || rightSegment === '*' || rightSegment === '**')
|
|
119
|
+
return true;
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
};
|
|
124
|
+
const hasUnambiguousPublishedClaimSections = (decision) => {
|
|
125
|
+
const declaredSections = [];
|
|
126
|
+
for (const claim of decision.claims) {
|
|
127
|
+
if (new Set(claim.sectionPaths).size !== claim.sectionPaths.length)
|
|
128
|
+
return false;
|
|
129
|
+
for (const sectionPath of claim.sectionPaths) {
|
|
130
|
+
if (!parseProjectedSectionPath(sectionPath))
|
|
131
|
+
return false;
|
|
132
|
+
if (declaredSections.some(declaredSection => doProjectedSectionsOverlap(declaredSection, sectionPath)))
|
|
133
|
+
return false;
|
|
134
|
+
declaredSections.push(sectionPath);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
};
|
|
139
|
+
const isPublishedViewArtifactDescriptor = (value, runId) => {
|
|
140
|
+
if (!isViewArtifactDescriptor(value, runId) || !isRecord(value))
|
|
141
|
+
return false;
|
|
142
|
+
const runPrefix = `runs/${runId}/`;
|
|
143
|
+
if (value.name !== value.path.slice(runPrefix.length))
|
|
144
|
+
return false;
|
|
145
|
+
if (!Array.isArray(value.claimBindings) ||
|
|
146
|
+
value.claimBindings.length === 0 ||
|
|
147
|
+
value.claimBindings.length > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxClaimBindings) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
const claimIds = new Set();
|
|
151
|
+
for (const binding of value.claimBindings) {
|
|
152
|
+
if (!isRecord(binding) || !isStrictNonEmptyString(binding.claimId) || claimIds.has(binding.claimId))
|
|
153
|
+
return false;
|
|
154
|
+
claimIds.add(binding.claimId);
|
|
155
|
+
if (!Array.isArray(binding.sectionPaths) ||
|
|
156
|
+
binding.sectionPaths.length === 0 ||
|
|
157
|
+
binding.sectionPaths.length > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxSectionPaths) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
if (new Set(binding.sectionPaths).size !== binding.sectionPaths.length)
|
|
161
|
+
return false;
|
|
162
|
+
if (!binding.sectionPaths.every(sectionPath => isProjectedSectionPathForArtifact(sectionPath, value.path)))
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
};
|
|
167
|
+
const hasPublishedViewDecisionBounds = (decision) => {
|
|
168
|
+
if (decision.claims.length === 0 ||
|
|
169
|
+
decision.claims.length > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxClaims ||
|
|
170
|
+
decision.dependencies.length > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxDependencies ||
|
|
171
|
+
decision.issues.length > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxIssues) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
let sectionPathCount = 0;
|
|
175
|
+
let issueCount = decision.issues.length;
|
|
176
|
+
for (const claim of decision.claims) {
|
|
177
|
+
sectionPathCount += claim.sectionPaths.length;
|
|
178
|
+
issueCount += claim.issues.length;
|
|
179
|
+
if (sectionPathCount > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxSectionPaths || issueCount > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxIssues) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
};
|
|
185
|
+
const hasPublishedViewArtifactBounds = (artifacts) => {
|
|
186
|
+
let claimBindingCount = 0;
|
|
187
|
+
let sectionPathCount = 0;
|
|
188
|
+
for (const artifact of artifacts) {
|
|
189
|
+
claimBindingCount += artifact.claimBindings.length;
|
|
190
|
+
for (const binding of artifact.claimBindings)
|
|
191
|
+
sectionPathCount += binding.sectionPaths.length;
|
|
192
|
+
if (claimBindingCount > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxClaimBindings || sectionPathCount > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxSectionPaths) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
};
|
|
76
198
|
const hasRequiredViewDependencies = (decision) => {
|
|
77
199
|
const dependencies = new Map(decision.dependencies.map(dependency => [dependency.name, dependency]));
|
|
78
200
|
const billing = dependencies.get('billing');
|
|
@@ -123,6 +245,90 @@ export const isCompletedViewManifestV3 = (value) => {
|
|
|
123
245
|
}
|
|
124
246
|
return isArtifactPublicationDecision(value.publicationDecision) && hasRequiredViewDependencies(value.publicationDecision);
|
|
125
247
|
};
|
|
248
|
+
const hasExactPublishedClaimProjection = (artifacts, decision) => {
|
|
249
|
+
if (!hasUnambiguousPublishedClaimSections(decision))
|
|
250
|
+
return false;
|
|
251
|
+
const claimById = new Map(decision.claims.map(claim => [claim.claimId, claim]));
|
|
252
|
+
const completedClaims = decision.claims.filter(claim => claim.publication === 'completed');
|
|
253
|
+
if (completedClaims.length === 0)
|
|
254
|
+
return false;
|
|
255
|
+
const expectedBindings = new Set();
|
|
256
|
+
for (const claim of completedClaims) {
|
|
257
|
+
if (claim.sectionPaths.length === 0 || new Set(claim.sectionPaths).size !== claim.sectionPaths.length)
|
|
258
|
+
return false;
|
|
259
|
+
for (const sectionPath of claim.sectionPaths)
|
|
260
|
+
expectedBindings.add(`${claim.claimId}\0${sectionPath}`);
|
|
261
|
+
}
|
|
262
|
+
const actualBindings = new Set();
|
|
263
|
+
for (const artifact of artifacts) {
|
|
264
|
+
for (const binding of artifact.claimBindings) {
|
|
265
|
+
const claim = claimById.get(binding.claimId);
|
|
266
|
+
if (!claim || claim.publication !== 'completed')
|
|
267
|
+
return false;
|
|
268
|
+
for (const sectionPath of binding.sectionPaths) {
|
|
269
|
+
if (!claim.sectionPaths.includes(sectionPath))
|
|
270
|
+
return false;
|
|
271
|
+
const key = `${binding.claimId}\0${sectionPath}`;
|
|
272
|
+
if (actualBindings.has(key))
|
|
273
|
+
return false;
|
|
274
|
+
actualBindings.add(key);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return expectedBindings.size === actualBindings.size && Array.from(expectedBindings).every(binding => actualBindings.has(binding));
|
|
279
|
+
};
|
|
280
|
+
const isPublishedDecisionForCoverage = (decision, coverage) => {
|
|
281
|
+
if (!hasRequiredViewDependencies(decision) || decision.processing !== 'succeeded')
|
|
282
|
+
return false;
|
|
283
|
+
const completedClaimCount = decision.claims.filter(claim => claim.publication === 'completed').length;
|
|
284
|
+
if (coverage === 'complete') {
|
|
285
|
+
return decision.publication === 'completed' && decision.evidence === 'complete' && completedClaimCount === decision.claims.length;
|
|
286
|
+
}
|
|
287
|
+
return (decision.publication === 'partial' && decision.evidence === 'partial' && completedClaimCount > 0 && completedClaimCount < decision.claims.length);
|
|
288
|
+
};
|
|
289
|
+
/** Validates a claim-projected portal or plugin generation, including observe-mode epoch-free manifests. */
|
|
290
|
+
export const isPublishedViewManifestV4 = (value) => {
|
|
291
|
+
if (!isRecord(value) ||
|
|
292
|
+
containsForbiddenViewArtifactControlData(value, [
|
|
293
|
+
...allowedArtifactTraversalField(value, 'artifacts'),
|
|
294
|
+
...allowedViewArtifactPaths(value.artifacts),
|
|
295
|
+
])) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
if (value.schemaVersion !== 4 || value.status !== 'published' || !isPublishedViewCoverage(value.coverage))
|
|
299
|
+
return false;
|
|
300
|
+
if (!isSafePathSegment(value.runId) || !hasMatchingViewOwnership(value.subscriptionId, value.ownership, value.revision, false))
|
|
301
|
+
return false;
|
|
302
|
+
if (!isRecord(value.artifactGeneration) ||
|
|
303
|
+
value.artifactGeneration.runId !== value.runId ||
|
|
304
|
+
!isStrictCanonicalIsoTimestamp(value.artifactGeneration.generatedAt)) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
if (!Array.isArray(value.artifacts) || value.artifacts.length === 0 || value.artifacts.length > PUBLISHED_VIEW_OBJECT_LIMITS_V1.maxArtifacts) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
if (!value.artifacts.every(artifact => isPublishedViewArtifactDescriptor(artifact, value.runId)))
|
|
311
|
+
return false;
|
|
312
|
+
if (!hasPublishedViewArtifactBounds(value.artifacts))
|
|
313
|
+
return false;
|
|
314
|
+
if (new Set(value.artifacts.map(artifact => artifact.path)).size !== value.artifacts.length ||
|
|
315
|
+
new Set(value.artifacts.map(artifact => artifact.name)).size !== value.artifacts.length) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
if (!isPositiveSafeInteger(value.requestedArtifactCount) ||
|
|
319
|
+
value.requestedArtifactCount !== value.artifacts.length ||
|
|
320
|
+
!isNonNegativeSafeInteger(value.requestedResourceCount) ||
|
|
321
|
+
value.failedArtifactCount !== 0 ||
|
|
322
|
+
value.failedResourceCount !== 0 ||
|
|
323
|
+
!isSha256(value.compositeDependencyDigest) ||
|
|
324
|
+
!isStrictCanonicalIsoTimestamp(value.completedAt) ||
|
|
325
|
+
!isArtifactPublicationDecision(value.publicationDecision) ||
|
|
326
|
+
!hasPublishedViewDecisionBounds(value.publicationDecision)) {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
return (isPublishedDecisionForCoverage(value.publicationDecision, value.coverage) &&
|
|
330
|
+
hasExactPublishedClaimProjection(value.artifacts, value.publicationDecision));
|
|
331
|
+
};
|
|
126
332
|
const hasSameOwnership = (left, right) => left.provider === right.provider &&
|
|
127
333
|
left.tenantId === right.tenantId &&
|
|
128
334
|
left.companyId === right.companyId &&
|
|
@@ -148,6 +354,22 @@ const isViewSetV2SurfaceReference = (value, surface, subscriptionId, ownership,
|
|
|
148
354
|
value.compositeDependencyDigest === compositeDependencyDigest &&
|
|
149
355
|
isStrictCanonicalIsoTimestamp(value.completedAt));
|
|
150
356
|
};
|
|
357
|
+
const isPublishedViewSetV3SurfaceReference = (value, surface, subscriptionId, ownership, revision, compositeDependencyDigest) => {
|
|
358
|
+
if (!isRecord(value) || !isSafePathSegment(value.runId) || !isPublishedViewCoverage(value.coverage))
|
|
359
|
+
return false;
|
|
360
|
+
const expectedManifestName = surface === 'portal' ? 'published-view-manifest.json' : 'published-plugin-generation.json';
|
|
361
|
+
if (value.manifestPath !== `runs/${value.runId}/${expectedManifestName}` || !isStrictLogicalArtifactReference(value.manifestPath))
|
|
362
|
+
return false;
|
|
363
|
+
if (!isEnforceableAzureOwnershipBinding(value.ownership) || !isArtifactRevisionVector(value.revision))
|
|
364
|
+
return false;
|
|
365
|
+
if (!hasMatchingViewOwnership(subscriptionId, value.ownership, value.revision, true))
|
|
366
|
+
return false;
|
|
367
|
+
if (!hasSameOwnership(ownership, value.ownership) || !hasSameRevision(revision, value.revision))
|
|
368
|
+
return false;
|
|
369
|
+
return (isSha256(value.manifestDigest) &&
|
|
370
|
+
value.compositeDependencyDigest === compositeDependencyDigest &&
|
|
371
|
+
isStrictCanonicalIsoTimestamp(value.completedAt));
|
|
372
|
+
};
|
|
151
373
|
const hasMatchingSurfaceDependency = (decision, name, surface) => {
|
|
152
374
|
const dependency = decision.dependencies.find(candidate => candidate.name === name);
|
|
153
375
|
return (dependency !== undefined &&
|
|
@@ -191,3 +413,43 @@ export const isCompletedAzureViewSetV2 = (value) => {
|
|
|
191
413
|
hasMatchingSurfaceDependency(value.publicationDecision, 'portal', value.portal) &&
|
|
192
414
|
hasMatchingSurfaceDependency(value.publicationDecision, 'plugin', value.plugin));
|
|
193
415
|
};
|
|
416
|
+
/** Validates the promoted pointer for one claim-projected portal/plugin generation pair. */
|
|
417
|
+
export const isPublishedAzureViewSetV3 = (value) => {
|
|
418
|
+
const allowedReferences = isRecord(value)
|
|
419
|
+
? [
|
|
420
|
+
...allowedArtifactTraversalField(value, 'portal'),
|
|
421
|
+
...allowedArtifactTraversalField(value, 'plugin'),
|
|
422
|
+
...allowedArtifactReferenceField(value.portal, 'manifestPath'),
|
|
423
|
+
...allowedArtifactReferenceField(value.plugin, 'manifestPath'),
|
|
424
|
+
]
|
|
425
|
+
: [];
|
|
426
|
+
if (!isRecord(value) || containsForbiddenViewArtifactControlData(value, allowedReferences))
|
|
427
|
+
return false;
|
|
428
|
+
if (value.schemaVersion !== 3 || value.status !== 'published' || !isPublishedViewCoverage(value.coverage))
|
|
429
|
+
return false;
|
|
430
|
+
if (!isSafePathSegment(value.subscriptionId) ||
|
|
431
|
+
!isStrictNonEmptyString(value.publicationId) ||
|
|
432
|
+
!isEnforceableAzureOwnershipBinding(value.ownership) ||
|
|
433
|
+
!isArtifactRevisionVector(value.revision) ||
|
|
434
|
+
!hasMatchingViewOwnership(value.subscriptionId, value.ownership, value.revision, true)) {
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
if (!isSha256(value.compositeDependencyDigest) || !isStrictCanonicalIsoTimestamp(value.completedAt))
|
|
438
|
+
return false;
|
|
439
|
+
if (!isPublishedViewSetV3SurfaceReference(value.portal, 'portal', value.subscriptionId, value.ownership, value.revision, value.compositeDependencyDigest) ||
|
|
440
|
+
!isPublishedViewSetV3SurfaceReference(value.plugin, 'plugin', value.subscriptionId, value.ownership, value.revision, value.compositeDependencyDigest)) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
const expectedCoverage = value.portal.coverage === 'complete' && value.plugin.coverage === 'complete' ? 'complete' : 'partial';
|
|
444
|
+
if (value.coverage !== expectedCoverage)
|
|
445
|
+
return false;
|
|
446
|
+
const laterSurfaceCompletedAt = Date.parse(value.portal.completedAt) >= Date.parse(value.plugin.completedAt) ? value.portal.completedAt : value.plugin.completedAt;
|
|
447
|
+
if (value.completedAt !== laterSurfaceCompletedAt)
|
|
448
|
+
return false;
|
|
449
|
+
return (isArtifactPublicationDecision(value.publicationDecision) &&
|
|
450
|
+
hasPublishedViewDecisionBounds(value.publicationDecision) &&
|
|
451
|
+
value.publicationDecision.publication === 'completed' &&
|
|
452
|
+
value.publicationDecision.evidence === value.coverage &&
|
|
453
|
+
hasMatchingSurfaceDependency(value.publicationDecision, 'portal', value.portal) &&
|
|
454
|
+
hasMatchingSurfaceDependency(value.publicationDecision, 'plugin', value.plugin));
|
|
455
|
+
};
|