@spottoai/types-package 1.0.2-beta.373 → 1.0.2-beta.375

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 (62) hide show
  1. package/README.md +9 -0
  2. package/dist/accounts/accounts.d.ts +4 -2
  3. package/dist/accounts/accounts.d.ts.map +1 -1
  4. package/dist/accounts/accounts.js.map +1 -1
  5. package/dist/accounts/azureSpSetup.d.ts +1 -1
  6. package/dist/accounts/azureSpSetup.d.ts.map +1 -1
  7. package/dist/aws/commitments-planning.d.ts +5 -0
  8. package/dist/aws/commitments-planning.d.ts.map +1 -1
  9. package/dist/aws/commitments-planning.js +19 -0
  10. package/dist/aws/commitments-planning.js.map +1 -1
  11. package/dist/aws/estates.d.ts +1 -1
  12. package/dist/aws/estates.d.ts.map +1 -1
  13. package/dist/aws/estates.js +7 -1
  14. package/dist/aws/estates.js.map +1 -1
  15. package/dist/aws/index.d.ts +5 -0
  16. package/dist/aws/index.d.ts.map +1 -1
  17. package/dist/aws/index.js +5 -0
  18. package/dist/aws/index.js.map +1 -1
  19. package/dist/aws/onboarding.d.ts +3 -0
  20. package/dist/aws/onboarding.d.ts.map +1 -1
  21. package/dist/aws/organizationCommitments.d.ts +260 -0
  22. package/dist/aws/organizationCommitments.d.ts.map +1 -0
  23. package/dist/aws/organizationCommitments.js +53 -0
  24. package/dist/aws/organizationCommitments.js.map +1 -0
  25. package/dist/aws/organizationCommitmentsApiValidation.d.ts +21 -0
  26. package/dist/aws/organizationCommitmentsApiValidation.d.ts.map +1 -0
  27. package/dist/aws/organizationCommitmentsApiValidation.js +226 -0
  28. package/dist/aws/organizationCommitmentsApiValidation.js.map +1 -0
  29. package/dist/aws/organizationCommitmentsValidation.d.ts +12 -0
  30. package/dist/aws/organizationCommitmentsValidation.d.ts.map +1 -0
  31. package/dist/aws/organizationCommitmentsValidation.js +228 -0
  32. package/dist/aws/organizationCommitmentsValidation.js.map +1 -0
  33. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifactValidation.d.ts +9 -0
  34. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifactValidation.d.ts.map +1 -0
  35. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifactValidation.js +407 -0
  36. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifactValidation.js.map +1 -0
  37. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifacts.d.ts +17 -0
  38. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifacts.d.ts.map +1 -0
  39. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifacts.js +6 -0
  40. package/dist/aws/portalOrganizationCommitmentsPlanningPublicArtifacts.js.map +1 -0
  41. package/dist/aws/requests.d.ts +13 -2
  42. package/dist/aws/requests.d.ts.map +1 -1
  43. package/dist/aws/requests.js +1 -1
  44. package/dist/aws/requests.js.map +1 -1
  45. package/dist/azure/commitmentsPlanning.d.ts +2 -2
  46. package/dist/azure/commitmentsPlanning.d.ts.map +1 -1
  47. package/dist/azure/governance.d.ts +4 -0
  48. package/dist/azure/governance.d.ts.map +1 -1
  49. package/dist/common/provider.d.ts +53 -0
  50. package/dist/common/provider.d.ts.map +1 -1
  51. package/dist/common/provider.js.map +1 -1
  52. package/dist/esm/aws/commitments-planning.js +5 -0
  53. package/dist/esm/aws/estates.js +7 -1
  54. package/dist/esm/aws/index.js +5 -0
  55. package/dist/esm/aws/organizationCommitments.js +48 -0
  56. package/dist/esm/aws/organizationCommitmentsApiValidation.js +220 -0
  57. package/dist/esm/aws/organizationCommitmentsValidation.js +224 -0
  58. package/dist/esm/aws/portalOrganizationCommitmentsPlanningPublicArtifactValidation.js +402 -0
  59. package/dist/esm/aws/portalOrganizationCommitmentsPlanningPublicArtifacts.js +2 -0
  60. package/dist/esm/aws/requests.js +1 -1
  61. package/dist/esm/entries/commitments-planning.js +2 -2
  62. package/package.json +4 -3
@@ -0,0 +1,402 @@
1
+ import { AWS_ORGANIZATION_COMMITMENTS_ATTRIBUTION_UNAVAILABLE_REASONS, } from './organizationCommitments.js';
2
+ import { validateAwsOrganizationCommitmentsPlanningViewIdentity, } from './organizationCommitmentsValidation.js';
3
+ import { AWS_ORGANIZATION_COMMITMENTS_PLANNING_LOGICAL_NAME, AWS_ORGANIZATION_COMMITMENTS_PUBLIC_ARTIFACT_SCHEMA_VERSION, } from './portalOrganizationCommitmentsPlanningPublicArtifacts.js';
4
+ import { AWS_PORTAL_PUBLIC_ARTIFACT_SCHEMA_VERSION } from './portalPublicArtifacts.js';
5
+ import { asRecord, assertExactKeys, assertPublicJson, assertValue, finiteNumber, isoTimestamp, requiredEnum, requiredString, validateGeneration, } from './portalPublicArtifactValidationCommon.js';
6
+ const TOP_LEVEL_KEYS = [
7
+ 'schemaVersion',
8
+ 'portalSchemaVersion',
9
+ 'provider',
10
+ 'artifactType',
11
+ 'artifactGeneration',
12
+ 'logicalName',
13
+ 'manifestRevision',
14
+ 'version',
15
+ 'generatedAt',
16
+ 'month',
17
+ 'providerScope',
18
+ 'accounts',
19
+ 'utilizationSummary',
20
+ 'expirySummary',
21
+ 'inventory',
22
+ 'payerAggregates',
23
+ 'sharingPosture',
24
+ 'pricingContext',
25
+ 'freshness',
26
+ 'purchaseRecommendations',
27
+ 'allocation',
28
+ 'resourceAttribution',
29
+ ];
30
+ /** Validates one untrusted organization Commitments Planning view without its Portal envelope. */
31
+ export function validateAwsOrganizationCommitmentsPlanningView(value, expected) {
32
+ validateAwsOrganizationCommitmentsPlanningViewIdentity(value, expected);
33
+ validateBody(value);
34
+ assertPublicJson(value, 'organizationCommitmentsPlanning');
35
+ return value;
36
+ }
37
+ /** Validates one untrusted immutable AWS organization Commitments Planning artifact. */
38
+ export function validateAwsPortalOrganizationCommitmentsPlanningArtifact(value, expected) {
39
+ const artifact = asRecord(value, 'artifact');
40
+ assertExactKeys(artifact, TOP_LEVEL_KEYS, 'artifact');
41
+ assertValue(artifact.schemaVersion, AWS_ORGANIZATION_COMMITMENTS_PUBLIC_ARTIFACT_SCHEMA_VERSION, 'artifact.schemaVersion');
42
+ assertValue(artifact.portalSchemaVersion, AWS_PORTAL_PUBLIC_ARTIFACT_SCHEMA_VERSION, 'artifact.portalSchemaVersion');
43
+ assertValue(artifact.provider, 'aws', 'artifact.provider');
44
+ assertValue(artifact.artifactType, 'organization-commitments-planning', 'artifact.artifactType');
45
+ assertValue(artifact.logicalName, AWS_ORGANIZATION_COMMITMENTS_PLANNING_LOGICAL_NAME, 'artifact.logicalName');
46
+ requiredString(artifact.manifestRevision, 'artifact.manifestRevision');
47
+ assertValue(artifact.version, '1.0', 'artifact.version');
48
+ const generation = validateGeneration(artifact.artifactGeneration, 'artifact.artifactGeneration');
49
+ const generatedAt = isoTimestamp(artifact.generatedAt, 'artifact.generatedAt');
50
+ if (Date.parse(generatedAt) > Date.parse(generation.generatedAt)) {
51
+ throw new Error('artifact.generatedAt must not be newer than the Portal generation.');
52
+ }
53
+ if (artifact.month !== undefined)
54
+ requiredString(artifact.month, 'artifact.month');
55
+ validateAwsOrganizationCommitmentsPlanningView(artifact, expected);
56
+ assertPublicJson(artifact, 'artifact');
57
+ return value;
58
+ }
59
+ function validateBody(view) {
60
+ records(view.accounts, 'artifact.accounts', validateAccount);
61
+ validateUtilizationSummary(view.utilizationSummary, 'artifact.utilizationSummary');
62
+ exact(view.expirySummary, ['expired', 'expiring30d', 'expiring60d', 'expiring90d', 'expiring180d'], 'artifact.expirySummary');
63
+ records(view.inventory, 'artifact.inventory', validateInventory);
64
+ records(view.payerAggregates, 'artifact.payerAggregates', validatePayerAggregate);
65
+ validateSharingPosture(view.sharingPosture, 'artifact.sharingPosture');
66
+ validatePricingContext(view.pricingContext, 'artifact.pricingContext');
67
+ optionalRecord(view.freshness, 'artifact.freshness', validateFreshness);
68
+ optionalRecords(view.purchaseRecommendations, 'artifact.purchaseRecommendations', validatePurchaseRecommendation);
69
+ validateAttribution(view.allocation, 'artifact.allocation', validateAllocationRecord);
70
+ validateAttribution(view.resourceAttribution, 'artifact.resourceAttribution', validateResourceAttributionRecord);
71
+ }
72
+ function validateSharingPosture(value, field) {
73
+ const posture = exact(value, ['status', 'reason'], field);
74
+ assertValue(posture.status, 'unknown', `${field}.status`);
75
+ assertValue(posture.reason, 'not-collected', `${field}.reason`);
76
+ }
77
+ function validateAccount(value, field) {
78
+ const account = exact(value, ['accountId', 'displayName', 'role', 'inventoryStatus', 'lastSuccessfulRefreshAt'], field);
79
+ requiredString(account.accountId, `${field}.accountId`);
80
+ optionalString(account.displayName, `${field}.displayName`);
81
+ requiredEnum(account.role, ['management', 'member'], `${field}.role`);
82
+ requiredEnum(account.inventoryStatus, ['current', 'stale', 'partial', 'unavailable'], `${field}.inventoryStatus`);
83
+ optionalTimestamp(account.lastSuccessfulRefreshAt, `${field}.lastSuccessfulRefreshAt`);
84
+ }
85
+ function validateUtilizationSummary(value, field) {
86
+ const summary = exact(value, ['total', 'withData', 'sevenDayAverage', 'thirtyDayAverage', 'sevenDayAggregates', 'thirtyDayAggregates', 'byBenefitType'], field);
87
+ nonNegative(summary.total, `${field}.total`);
88
+ nonNegative(summary.withData, `${field}.withData`);
89
+ optionalNumber(summary.sevenDayAverage, `${field}.sevenDayAverage`);
90
+ optionalNumber(summary.thirtyDayAverage, `${field}.thirtyDayAverage`);
91
+ optionalRecords(summary.sevenDayAggregates, `${field}.sevenDayAggregates`, validateWeightedAggregate);
92
+ optionalRecords(summary.thirtyDayAggregates, `${field}.thirtyDayAggregates`, validateWeightedAggregate);
93
+ records(summary.byBenefitType, `${field}.byBenefitType`, (entry, itemField) => {
94
+ const item = exact(entry, ['benefitType', 'total', 'withData', 'sevenDayAverage', 'thirtyDayAverage', 'sevenDayAggregates', 'thirtyDayAggregates'], itemField);
95
+ requiredEnum(item.benefitType, ['reservation', 'savings-plan'], `${itemField}.benefitType`);
96
+ nonNegative(item.total, `${itemField}.total`);
97
+ nonNegative(item.withData, `${itemField}.withData`);
98
+ optionalNumber(item.sevenDayAverage, `${itemField}.sevenDayAverage`);
99
+ optionalNumber(item.thirtyDayAverage, `${itemField}.thirtyDayAverage`);
100
+ optionalRecords(item.sevenDayAggregates, `${itemField}.sevenDayAggregates`, validateWeightedAggregate);
101
+ optionalRecords(item.thirtyDayAggregates, `${itemField}.thirtyDayAggregates`, validateWeightedAggregate);
102
+ });
103
+ }
104
+ function validateWeightedAggregate(value, field) {
105
+ const aggregate = exact(value, ['used', 'reserved', 'percentage', 'sampleCount', 'unit', 'currency'], field);
106
+ finiteNumber(aggregate.used, `${field}.used`);
107
+ finiteNumber(aggregate.reserved, `${field}.reserved`);
108
+ optionalNumber(aggregate.percentage, `${field}.percentage`);
109
+ if (aggregate.sampleCount !== undefined)
110
+ nonNegative(aggregate.sampleCount, `${field}.sampleCount`);
111
+ requiredEnum(aggregate.unit, ['hours', 'quantity', 'currency'], `${field}.unit`);
112
+ optionalString(aggregate.currency, `${field}.currency`);
113
+ }
114
+ function validateInventory(value, field) {
115
+ const item = exact(value, [
116
+ 'id',
117
+ 'benefitType',
118
+ 'commitmentFamily',
119
+ 'sourceKind',
120
+ 'sourceId',
121
+ 'provider',
122
+ 'ownerAccountId',
123
+ 'shape',
124
+ 'scope',
125
+ 'type',
126
+ 'displayName',
127
+ 'status',
128
+ 'purchaseDate',
129
+ 'expiryDate',
130
+ 'daysToExpiry',
131
+ 'commitmentAmount',
132
+ 'commitmentCurrencyCode',
133
+ 'commitmentGrain',
134
+ 'commitmentUnit',
135
+ 'skuName',
136
+ 'location',
137
+ 'term',
138
+ 'termMonths',
139
+ 'billingPlan',
140
+ 'utilization',
141
+ ], field);
142
+ requiredString(item.id, `${field}.id`);
143
+ requiredEnum(item.benefitType, ['reservation', 'savings-plan'], `${field}.benefitType`);
144
+ optionalString(item.commitmentFamily, `${field}.commitmentFamily`);
145
+ assertValue(item.sourceKind, 'aws-native', `${field}.sourceKind`);
146
+ optionalString(item.sourceId, `${field}.sourceId`);
147
+ assertValue(item.provider, 'aws', `${field}.provider`);
148
+ requiredString(item.ownerAccountId, `${field}.ownerAccountId`);
149
+ optionalRecord(item.shape, `${field}.shape`, validateShape);
150
+ requiredEnum(item.scope, ['Shared', 'Single', 'ManagementGroup', 'Unknown'], `${field}.scope`);
151
+ requiredString(item.type, `${field}.type`);
152
+ optionalString(item.displayName, `${field}.displayName`);
153
+ requiredString(item.status, `${field}.status`);
154
+ optionalString(item.purchaseDate, `${field}.purchaseDate`);
155
+ optionalString(item.expiryDate, `${field}.expiryDate`);
156
+ optionalNumber(item.daysToExpiry, `${field}.daysToExpiry`);
157
+ optionalNumber(item.commitmentAmount, `${field}.commitmentAmount`);
158
+ optionalString(item.commitmentCurrencyCode, `${field}.commitmentCurrencyCode`);
159
+ optionalString(item.commitmentGrain, `${field}.commitmentGrain`);
160
+ optionalString(item.commitmentUnit, `${field}.commitmentUnit`);
161
+ optionalString(item.skuName, `${field}.skuName`);
162
+ optionalString(item.location, `${field}.location`);
163
+ optionalString(item.term, `${field}.term`);
164
+ optionalNumber(item.termMonths, `${field}.termMonths`);
165
+ optionalString(item.billingPlan, `${field}.billingPlan`);
166
+ optionalRecord(item.utilization, `${field}.utilization`, validateUtilization);
167
+ }
168
+ function validatePayerAggregate(value, field) {
169
+ const aggregate = exact(value, [
170
+ 'benefitType',
171
+ 'commitmentFamily',
172
+ 'payerAccountId',
173
+ 'windowStart',
174
+ 'windowEnd',
175
+ 'eligibleCost',
176
+ 'coveredCost',
177
+ 'uncoveredCost',
178
+ 'coveragePercent',
179
+ 'utilization',
180
+ 'source',
181
+ ], field);
182
+ requiredEnum(aggregate.benefitType, ['reservation', 'savings-plan'], `${field}.benefitType`);
183
+ requiredString(aggregate.commitmentFamily, `${field}.commitmentFamily`);
184
+ requiredString(aggregate.payerAccountId, `${field}.payerAccountId`);
185
+ requiredString(aggregate.windowStart, `${field}.windowStart`);
186
+ requiredString(aggregate.windowEnd, `${field}.windowEnd`);
187
+ optionalRecord(aggregate.eligibleCost, `${field}.eligibleCost`, validateMoney);
188
+ optionalRecord(aggregate.coveredCost, `${field}.coveredCost`, validateMoney);
189
+ optionalRecord(aggregate.uncoveredCost, `${field}.uncoveredCost`, validateMoney);
190
+ optionalNumber(aggregate.coveragePercent, `${field}.coveragePercent`);
191
+ optionalRecord(aggregate.utilization, `${field}.utilization`, validateUtilization);
192
+ validateSource(aggregate.source, `${field}.source`, false);
193
+ }
194
+ function validatePurchaseRecommendation(value, field) {
195
+ const recommendation = exact(value, [
196
+ 'id',
197
+ 'groupKey',
198
+ 'commitmentFamily',
199
+ 'action',
200
+ 'purchaseScope',
201
+ 'payerAccountId',
202
+ 'recommendedAccountId',
203
+ 'source',
204
+ 'targetShape',
205
+ 'title',
206
+ 'description',
207
+ 'confidence',
208
+ 'riskLevel',
209
+ 'termMonths',
210
+ 'quantity',
211
+ 'estimatedAnnualSavings',
212
+ 'estimatedAnnualCost',
213
+ 'estimatedTermSavings',
214
+ 'estimatedTermCost',
215
+ 'notes',
216
+ ], field);
217
+ requiredString(recommendation.id, `${field}.id`);
218
+ requiredString(recommendation.groupKey, `${field}.groupKey`);
219
+ requiredString(recommendation.commitmentFamily, `${field}.commitmentFamily`);
220
+ requiredEnum(recommendation.action, ['buy', 'unlock', 'savings-plan', 'none'], `${field}.action`);
221
+ assertValue(recommendation.purchaseScope, 'payer', `${field}.purchaseScope`);
222
+ requiredString(recommendation.payerAccountId, `${field}.payerAccountId`);
223
+ optionalString(recommendation.recommendedAccountId, `${field}.recommendedAccountId`);
224
+ validateSource(recommendation.source, `${field}.source`, false);
225
+ validateShape(recommendation.targetShape, `${field}.targetShape`);
226
+ optionalString(recommendation.title, `${field}.title`);
227
+ optionalString(recommendation.description, `${field}.description`);
228
+ optionalString(recommendation.confidence, `${field}.confidence`);
229
+ optionalString(recommendation.riskLevel, `${field}.riskLevel`);
230
+ optionalNumber(recommendation.termMonths, `${field}.termMonths`);
231
+ optionalNumber(recommendation.quantity, `${field}.quantity`);
232
+ optionalRecord(recommendation.estimatedAnnualSavings, `${field}.estimatedAnnualSavings`, validateMoney);
233
+ optionalRecord(recommendation.estimatedAnnualCost, `${field}.estimatedAnnualCost`, validateMoney);
234
+ optionalRecord(recommendation.estimatedTermSavings, `${field}.estimatedTermSavings`, validateMoney);
235
+ optionalRecord(recommendation.estimatedTermCost, `${field}.estimatedTermCost`, validateMoney);
236
+ optionalStrings(recommendation.notes, `${field}.notes`);
237
+ }
238
+ function validateAttribution(value, field, validateRecord) {
239
+ const evidence = asRecord(value, field);
240
+ if (evidence.status === 'unavailable') {
241
+ assertExactKeys(evidence, ['status', 'reason'], field);
242
+ requiredEnum(evidence.reason, AWS_ORGANIZATION_COMMITMENTS_ATTRIBUTION_UNAVAILABLE_REASONS, `${field}.reason`);
243
+ return;
244
+ }
245
+ assertValue(evidence.status, 'available', `${field}.status`);
246
+ assertExactKeys(evidence, ['status', 'source', 'records'], field);
247
+ validateSource(evidence.source, `${field}.source`, true);
248
+ records(evidence.records, `${field}.records`, validateRecord, true);
249
+ }
250
+ function validateAllocationRecord(value, field) {
251
+ const record = exact(value, [
252
+ 'beneficiaryAccountId',
253
+ 'ownerAccountId',
254
+ 'commitmentId',
255
+ 'benefitType',
256
+ 'commitmentFamily',
257
+ 'windowStart',
258
+ 'windowEnd',
259
+ 'eligibleCost',
260
+ 'coveredCost',
261
+ 'uncoveredCost',
262
+ ], field);
263
+ requiredString(record.beneficiaryAccountId, `${field}.beneficiaryAccountId`);
264
+ optionalString(record.ownerAccountId, `${field}.ownerAccountId`);
265
+ optionalString(record.commitmentId, `${field}.commitmentId`);
266
+ requiredEnum(record.benefitType, ['reservation', 'savings-plan'], `${field}.benefitType`);
267
+ requiredString(record.commitmentFamily, `${field}.commitmentFamily`);
268
+ requiredString(record.windowStart, `${field}.windowStart`);
269
+ requiredString(record.windowEnd, `${field}.windowEnd`);
270
+ optionalRecord(record.eligibleCost, `${field}.eligibleCost`, validateMoney);
271
+ optionalRecord(record.coveredCost, `${field}.coveredCost`, validateMoney);
272
+ optionalRecord(record.uncoveredCost, `${field}.uncoveredCost`, validateMoney);
273
+ }
274
+ function validateResourceAttributionRecord(value, field) {
275
+ const record = exact(value, ['accountId', 'resourceId', 'resourceName', 'resourceType', 'benefitIds', 'windowStart', 'windowEnd', 'coveredCost'], field);
276
+ requiredString(record.accountId, `${field}.accountId`);
277
+ requiredString(record.resourceId, `${field}.resourceId`);
278
+ optionalString(record.resourceName, `${field}.resourceName`);
279
+ optionalString(record.resourceType, `${field}.resourceType`);
280
+ strings(record.benefitIds, `${field}.benefitIds`);
281
+ requiredString(record.windowStart, `${field}.windowStart`);
282
+ requiredString(record.windowEnd, `${field}.windowEnd`);
283
+ optionalRecord(record.coveredCost, `${field}.coveredCost`, validateMoney);
284
+ }
285
+ function validateShape(value, field) {
286
+ const shape = exact(value, [
287
+ 'provider',
288
+ 'resourceType',
289
+ 'commitmentFamily',
290
+ 'skuName',
291
+ 'normalizedSkuName',
292
+ 'location',
293
+ 'region',
294
+ 'availabilityZone',
295
+ 'platform',
296
+ 'reservationProductName',
297
+ 'reservedResourceType',
298
+ 'meterCategory',
299
+ 'meterSubCategory',
300
+ 'meterName',
301
+ 'unit',
302
+ 'attributes',
303
+ ], field);
304
+ assertValue(shape.provider, 'aws', `${field}.provider`);
305
+ if (shape.attributes !== undefined)
306
+ asRecord(shape.attributes, `${field}.attributes`);
307
+ }
308
+ function validateSource(value, field, allowDerived) {
309
+ const source = exact(value, ['sourceKind', 'sourceId', 'sourceName', 'generatedAt', 'observedAt', 'notes'], field);
310
+ requiredEnum(source.sourceKind, allowDerived ? ['aws-native', 'spotto-derived'] : ['aws-native'], `${field}.sourceKind`);
311
+ optionalString(source.sourceId, `${field}.sourceId`);
312
+ optionalString(source.sourceName, `${field}.sourceName`);
313
+ optionalTimestamp(source.generatedAt, `${field}.generatedAt`);
314
+ optionalTimestamp(source.observedAt, `${field}.observedAt`);
315
+ optionalStrings(source.notes, `${field}.notes`);
316
+ }
317
+ function validateMoney(value, field) {
318
+ const money = exact(value, ['amount', 'currency', 'source', 'windowStart', 'windowEnd', 'flags'], field);
319
+ finiteNumber(money.amount, `${field}.amount`);
320
+ requiredString(money.currency, `${field}.currency`);
321
+ optionalString(money.source, `${field}.source`);
322
+ optionalString(money.windowStart, `${field}.windowStart`);
323
+ optionalString(money.windowEnd, `${field}.windowEnd`);
324
+ optionalStrings(money.flags, `${field}.flags`);
325
+ }
326
+ function validateUtilization(value, field) {
327
+ const utilization = exact(value, ['trend', 'oneDay', 'sevenDay', 'thirtyDay', 'source'], field);
328
+ optionalString(utilization.trend, `${field}.trend`);
329
+ optionalNumber(utilization.oneDay, `${field}.oneDay`);
330
+ optionalNumber(utilization.sevenDay, `${field}.sevenDay`);
331
+ optionalNumber(utilization.thirtyDay, `${field}.thirtyDay`);
332
+ optionalString(utilization.source, `${field}.source`);
333
+ }
334
+ function validatePricingContext(value, field) {
335
+ const pricing = exact(value, ['source', 'currency', 'assumptions', 'confidenceNotes', 'calculatorDeepLink'], field);
336
+ requiredEnum(pricing.source, ['retail', 'negotiated', 'unknown', 'recommendation-apis'], `${field}.source`);
337
+ optionalString(pricing.currency, `${field}.currency`);
338
+ optionalStrings(pricing.assumptions, `${field}.assumptions`);
339
+ optionalString(pricing.confidenceNotes, `${field}.confidenceNotes`);
340
+ optionalString(pricing.calculatorDeepLink, `${field}.calculatorDeepLink`);
341
+ }
342
+ function validateFreshness(value, field) {
343
+ const freshness = exact(value, ['status', 'generatedAt', 'entries', 'warnings'], field);
344
+ requiredEnum(freshness.status, ['current', 'stale', 'partial', 'unavailable'], `${field}.status`);
345
+ isoTimestamp(freshness.generatedAt, `${field}.generatedAt`);
346
+ records(freshness.entries, `${field}.entries`, (entry, itemField) => {
347
+ const item = exact(entry, ['section', 'status', 'generatedAt', 'observedAt', 'lastSuccessfulSyncAt', 'reason', 'sourceKind'], itemField);
348
+ requiredString(item.section, `${itemField}.section`);
349
+ requiredEnum(item.status, ['current', 'stale', 'partial', 'unavailable'], `${itemField}.status`);
350
+ optionalTimestamp(item.generatedAt, `${itemField}.generatedAt`);
351
+ optionalTimestamp(item.observedAt, `${itemField}.observedAt`);
352
+ optionalTimestamp(item.lastSuccessfulSyncAt, `${itemField}.lastSuccessfulSyncAt`);
353
+ optionalString(item.reason, `${itemField}.reason`);
354
+ optionalString(item.sourceKind, `${itemField}.sourceKind`);
355
+ });
356
+ optionalStrings(freshness.warnings, `${field}.warnings`);
357
+ }
358
+ function exact(value, allowed, field) {
359
+ const record = asRecord(value, field);
360
+ assertExactKeys(record, allowed, field);
361
+ return record;
362
+ }
363
+ function records(value, field, validate, nonEmpty = false) {
364
+ if (!Array.isArray(value) || (nonEmpty && value.length === 0)) {
365
+ throw new Error(`${field} must be ${nonEmpty ? 'a non-empty' : 'an'} array.`);
366
+ }
367
+ value.forEach((entry, index) => validate(entry, `${field}[${index}]`));
368
+ }
369
+ function optionalRecords(value, field, validate) {
370
+ if (value !== undefined)
371
+ records(value, field, validate);
372
+ }
373
+ function optionalRecord(value, field, validate) {
374
+ if (value !== undefined)
375
+ validate(value, field);
376
+ }
377
+ function strings(value, field) {
378
+ if (!Array.isArray(value))
379
+ throw new Error(`${field} must be an array.`);
380
+ value.forEach((entry, index) => requiredString(entry, `${field}[${index}]`));
381
+ }
382
+ function optionalStrings(value, field) {
383
+ if (value !== undefined)
384
+ strings(value, field);
385
+ }
386
+ function optionalString(value, field) {
387
+ if (value !== undefined)
388
+ requiredString(value, field);
389
+ }
390
+ function optionalTimestamp(value, field) {
391
+ if (value !== undefined)
392
+ isoTimestamp(value, field);
393
+ }
394
+ function optionalNumber(value, field) {
395
+ if (value !== undefined)
396
+ finiteNumber(value, field);
397
+ }
398
+ function nonNegative(value, field) {
399
+ const number = finiteNumber(value, field);
400
+ if (number < 0)
401
+ throw new Error(`${field} must not be negative.`);
402
+ }
@@ -0,0 +1,2 @@
1
+ export const AWS_ORGANIZATION_COMMITMENTS_PUBLIC_ARTIFACT_SCHEMA_VERSION = 1;
2
+ export const AWS_ORGANIZATION_COMMITMENTS_PLANNING_LOGICAL_NAME = 'organization-commitments-planning.json.gz';
@@ -3,7 +3,7 @@ export const AWS_COMMAND_SCHEMA_VERSION = 1;
3
3
  /** Canonical provider wire value for AWS commands. */
4
4
  export const AWS_COMMAND_PROVIDER = 'aws';
5
5
  /** Entities handled by AWS estate orchestration. */
6
- export const AWS_COMMAND_ENTITIES = ['estate', 'account', 'billing-source'];
6
+ export const AWS_COMMAND_ENTITIES = ['estate', 'account', 'billing-source', 'organization-commitments'];
7
7
  /** Actions supported across AWS estate orchestration commands. */
8
8
  export const AWS_COMMAND_ACTIONS = ['reconcile', 'refresh', 'delete'];
9
9
  /** Credential-shaped keys forbidden from shared AWS configuration and commands. */
@@ -1,3 +1,3 @@
1
- export * from '../aws/commitmentsPlanningValidation.js';
2
- import * as namespace from '../aws/commitmentsPlanningValidation.js';
1
+ export * from '../aws/commitments-planning.js';
2
+ import * as namespace from '../aws/commitments-planning.js';
3
3
  export default namespace;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spottoai/types-package",
3
- "version": "1.0.2-beta.373",
3
+ "version": "1.0.2-beta.375",
4
4
  "description": "Shared TypeScript interfaces for SpottoAI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -43,7 +43,7 @@
43
43
  "./aws/commitments-planning": {
44
44
  "types": "./dist/aws/commitments-planning.d.ts",
45
45
  "import": "./dist/esm/entries/commitments-planning.js",
46
- "require": "./dist/aws/commitmentsPlanningValidation.js"
46
+ "require": "./dist/aws/commitments-planning.js"
47
47
  },
48
48
  "./azure/recommendations": {
49
49
  "types": "./dist/azure/recommendations.d.ts",
@@ -76,8 +76,9 @@
76
76
  "check:dev-1135-latest-contracts": "node scripts/check-dev-1135-latest-contracts.mjs",
77
77
  "check:capability-passport-contracts": "node scripts/check-capability-passport-contracts.mjs",
78
78
  "check:commitments-planning": "node scripts/check-commitments-planning.mjs",
79
+ "check:organization-commitments-planning": "node scripts/check-organization-commitments-planning.mjs",
79
80
  "prepublishOnly": "npm run clean && npm run build && npm test",
80
- "test": "npm run build && npm run check:artifact-evidence-contracts && npm run check:billing-artifact-object-boundaries && npm run check:billing-cost-analysis-read-responses && npm run check:aws-examples && npm run check:plugin-public-artifacts && npm run check:portal-public-artifacts && npm run check:relationship-public-artifacts && npm run check:azure-view-set-contracts && npm run check:dev-1135-latest-contracts && npm run check:capability-passport-contracts && npm run check:commitments-planning && npm run check:packed-exports",
81
+ "test": "npm run build && npm run check:artifact-evidence-contracts && npm run check:billing-artifact-object-boundaries && npm run check:billing-cost-analysis-read-responses && npm run check:aws-examples && npm run check:plugin-public-artifacts && npm run check:portal-public-artifacts && npm run check:relationship-public-artifacts && npm run check:azure-view-set-contracts && npm run check:dev-1135-latest-contracts && npm run check:capability-passport-contracts && npm run check:commitments-planning && npm run check:organization-commitments-planning && npm run check:packed-exports",
81
82
  "lint": "eslint src --ext .ts",
82
83
  "lint:fix": "eslint src --ext .ts --fix",
83
84
  "format": "prettier --write \"src/**/*.{ts,js,json}\"",