@noodleseed/one 0.38.1 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/billing-apply-ops.d.ts +2 -0
- package/dist/commands/billing-apply-ops.d.ts.map +1 -0
- package/dist/commands/billing-apply-ops.js +224 -0
- package/dist/commands/billing-apply-ops.js.map +1 -0
- package/dist/commands/billing-migration-files.d.ts +13 -0
- package/dist/commands/billing-migration-files.d.ts.map +1 -0
- package/dist/commands/billing-migration-files.js +84 -0
- package/dist/commands/billing-migration-files.js.map +1 -0
- package/dist/commands/billing-ops.d.ts +1 -1
- package/dist/commands/billing-ops.d.ts.map +1 -1
- package/dist/commands/billing-ops.js +13 -31
- package/dist/commands/billing-ops.js.map +1 -1
- package/dist/commands/billing-read-ops.d.ts +3 -0
- package/dist/commands/billing-read-ops.d.ts.map +1 -0
- package/dist/commands/billing-read-ops.js +289 -0
- package/dist/commands/billing-read-ops.js.map +1 -0
- package/dist/commands/catalog-data-resources.d.ts.map +1 -1
- package/dist/commands/catalog-data-resources.js +25 -2
- package/dist/commands/catalog-data-resources.js.map +1 -1
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +1 -0
- package/dist/commands/catalog.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/widget-scaffold-template.d.ts.map +1 -1
- package/dist/widget-scaffold-template.js +9 -0
- package/dist/widget-scaffold-template.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +3 -3
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.d.ts.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +28 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +44 -0
- package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts.map +1 -1
- package/node_modules/@noodle-borg/authoring/dist/assistant.js.map +1 -1
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -1
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/authoring/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/authoring/dist/server.js +6 -1
- package/node_modules/@noodle-borg/authoring/dist/server.js.map +1 -1
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +83 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts.map +1 -1
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +82 -14
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js.map +1 -1
- package/node_modules/@noodle-borg/module-audit/dist/index.d.ts +2 -1
- package/node_modules/@noodle-borg/module-audit/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/module-audit/dist/index.js +1 -1
- package/node_modules/@noodle-borg/module-audit/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/module-audit/dist/postgres-audit.d.ts +12 -3
- package/node_modules/@noodle-borg/module-audit/dist/postgres-audit.d.ts.map +1 -1
- package/node_modules/@noodle-borg/module-audit/dist/postgres-audit.js +30 -20
- package/node_modules/@noodle-borg/module-audit/dist/postgres-audit.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/in-memory.d.ts +4 -1
- package/node_modules/@noodle-borg/service/dist/billing/in-memory.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/in-memory.js +18 -0
- package/node_modules/@noodle-borg/service/dist/billing/in-memory.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/migration-apply.d.ts +98 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-apply.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-apply.js +194 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-apply.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-contract.d.ts +79 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-contract.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-contract.js +86 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration-contract.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/migration.d.ts +4 -75
- package/node_modules/@noodle-borg/service/dist/billing/migration.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/migration.js +19 -74
- package/node_modules/@noodle-borg/service/dist/billing/migration.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration-support.d.ts +36 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration-support.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration-support.js +122 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration-support.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration.d.ts +9 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration.js +265 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-migration.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-read.d.ts +7 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-read.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-read.js +55 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-read.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-schema.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/postgres-schema.js +71 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres-schema.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/postgres.d.ts +7 -0
- package/node_modules/@noodle-borg/service/dist/billing/postgres.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/postgres.js +21 -9
- package/node_modules/@noodle-borg/service/dist/billing/postgres.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/billing/read-contract.d.ts +268 -0
- package/node_modules/@noodle-borg/service/dist/billing/read-contract.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/read-contract.js +138 -0
- package/node_modules/@noodle-borg/service/dist/billing/read-contract.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/billing/store.d.ts +12 -0
- package/node_modules/@noodle-borg/service/dist/billing/store.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.d.ts +4 -2
- package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.js +3 -1
- package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/modules/host.js +3 -0
- package/node_modules/@noodle-borg/service/dist/modules/host.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/options.d.ts +13 -4
- package/node_modules/@noodle-borg/service/dist/options.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/billing-read.d.ts +12 -0
- package/node_modules/@noodle-borg/service/dist/routes/billing-read.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/billing-read.js +202 -0
- package/node_modules/@noodle-borg/service/dist/routes/billing-read.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/billing.d.ts +10 -1
- package/node_modules/@noodle-borg/service/dist/routes/billing.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/billing.js +89 -0
- package/node_modules/@noodle-borg/service/dist/routes/billing.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/commercial-dispatch.d.ts +4 -1
- package/node_modules/@noodle-borg/service/dist/routes/commercial-dispatch.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/commercial-dispatch.js +54 -2
- package/node_modules/@noodle-borg/service/dist/routes/commercial-dispatch.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts +8 -0
- package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/paths.js +25 -0
- package/node_modules/@noodle-borg/service/dist/routes/paths.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/serve.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/serve.js +20 -6
- package/node_modules/@noodle-borg/service/dist/serve.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/service.js +7 -4
- package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/audit.d.ts +8 -0
- package/node_modules/@noodle-borg/service/dist/store/audit.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/audit.js +15 -0
- package/node_modules/@noodle-borg/service/dist/store/audit.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-apps.d.ts +4 -2
- package/node_modules/@noodle-borg/service/dist/store/postgres-apps.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-apps.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-billing.d.ts +11 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-billing.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-billing.js +17 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-billing.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js +2 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-signup.d.ts +4 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-signup.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-signup.js +10 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-signup.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts +2 -2
- package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres.js +2 -2
- package/node_modules/@noodle-borg/service/dist/store/postgres.js.map +1 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts +3 -2
- package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts.map +1 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/assistant.js +3 -2
- package/node_modules/@noodle-borg/wire-contracts/dist/assistant.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { legacyBillingMigrationMappingChecksum, parseLegacyBillingMigrationRequest, } from './migration.js';
|
|
3
|
+
import { billingContentChecksum } from './model.js';
|
|
4
|
+
export class LegacyBillingMigrationConflictError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'LegacyBillingMigrationConflictError';
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const scalarSchema = (label, max) => z
|
|
13
|
+
.string()
|
|
14
|
+
.trim()
|
|
15
|
+
.min(1, `${label} is required`)
|
|
16
|
+
.max(max, `${label} must be ${max} characters or fewer`)
|
|
17
|
+
.refine((value) => !hasControlCharacters(value), `${label} cannot contain control characters`);
|
|
18
|
+
const serviceSchema = z
|
|
19
|
+
.string()
|
|
20
|
+
.url()
|
|
21
|
+
.max(2048)
|
|
22
|
+
.refine(isBillingServiceOrigin, 'service must be an HTTP(S) origin without credentials or a path')
|
|
23
|
+
.transform(normalizeBillingMigrationServiceUrl);
|
|
24
|
+
const planProjectionSchema = z.strictObject({
|
|
25
|
+
org: scalarSchema('organization', 128),
|
|
26
|
+
response: z.strictObject({
|
|
27
|
+
ok: z.literal(true),
|
|
28
|
+
service: serviceSchema,
|
|
29
|
+
plan: z.strictObject({
|
|
30
|
+
org: scalarSchema('plan organization', 128),
|
|
31
|
+
plan: z.literal('free'),
|
|
32
|
+
state: z.literal('active'),
|
|
33
|
+
source: z.literal('default'),
|
|
34
|
+
}),
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
const planEvidenceSchema = z.strictObject({
|
|
38
|
+
schemaVersion: z.literal(1),
|
|
39
|
+
service: serviceSchema,
|
|
40
|
+
capturedAt: z.iso.datetime({ offset: true }).transform((value) => new Date(value).toISOString()),
|
|
41
|
+
authoritativeOrganizationCount: z.number().int().nonnegative(),
|
|
42
|
+
projections: z.array(planProjectionSchema),
|
|
43
|
+
reconciliation: z.strictObject({
|
|
44
|
+
complete: z.literal(true),
|
|
45
|
+
treatment: z.literal('preserve_as_free'),
|
|
46
|
+
counts: z.strictObject({
|
|
47
|
+
freeActiveDefault: z.number().int().nonnegative(),
|
|
48
|
+
exceptions: z.literal(0),
|
|
49
|
+
}),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
const applyEnvelopeSchema = z.strictObject({
|
|
53
|
+
schemaVersion: z.literal(1),
|
|
54
|
+
mode: z.literal('shadow'),
|
|
55
|
+
mappings: z.array(z.unknown()),
|
|
56
|
+
expectedPreviewChecksum: z
|
|
57
|
+
.string()
|
|
58
|
+
.regex(/^[0-9a-f]{64}$/, 'expectedPreviewChecksum must be a lowercase SHA-256 checksum'),
|
|
59
|
+
legacyPlanEvidence: z.unknown(),
|
|
60
|
+
idempotencyKey: scalarSchema('idempotencyKey', 256),
|
|
61
|
+
reason: scalarSchema('reason', 512),
|
|
62
|
+
confirmed: z.literal(true),
|
|
63
|
+
});
|
|
64
|
+
export function parseLegacyBillingMigrationPlanEvidence(value) {
|
|
65
|
+
const result = planEvidenceSchema.safeParse(value);
|
|
66
|
+
if (!result.success) {
|
|
67
|
+
throw new Error(`invalid billing migration plan evidence: ${z.prettifyError(result.error)}`);
|
|
68
|
+
}
|
|
69
|
+
const evidence = result.data;
|
|
70
|
+
if (evidence.authoritativeOrganizationCount !== evidence.projections.length) {
|
|
71
|
+
throw new Error('invalid billing migration plan evidence: authoritativeOrganizationCount must equal projections length');
|
|
72
|
+
}
|
|
73
|
+
if (evidence.reconciliation.counts.freeActiveDefault !== evidence.projections.length ||
|
|
74
|
+
evidence.reconciliation.counts.exceptions !== 0) {
|
|
75
|
+
throw new Error('invalid billing migration plan evidence: reconciliation counts do not match projections');
|
|
76
|
+
}
|
|
77
|
+
const organizations = new Set();
|
|
78
|
+
for (const projection of evidence.projections) {
|
|
79
|
+
if (organizations.has(projection.org)) {
|
|
80
|
+
throw new Error(`invalid billing migration plan evidence: duplicate organization ${projection.org}`);
|
|
81
|
+
}
|
|
82
|
+
organizations.add(projection.org);
|
|
83
|
+
if (projection.response.plan.org !== projection.org) {
|
|
84
|
+
throw new Error(`invalid billing migration plan evidence: plan organization does not match ${projection.org}`);
|
|
85
|
+
}
|
|
86
|
+
if (projection.response.service !== evidence.service ||
|
|
87
|
+
projection.response.plan.source !== 'default' ||
|
|
88
|
+
projection.response.plan.plan !== 'free' ||
|
|
89
|
+
projection.response.plan.state !== 'active') {
|
|
90
|
+
throw new Error(`invalid billing migration plan evidence: ${projection.org} is not default Free and active`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return evidence;
|
|
94
|
+
}
|
|
95
|
+
export function parseLegacyBillingMigrationApplyRequest(value) {
|
|
96
|
+
const envelope = applyEnvelopeSchema.safeParse(value);
|
|
97
|
+
if (!envelope.success) {
|
|
98
|
+
throw new Error(`invalid billing migration apply: ${z.prettifyError(envelope.error)}`);
|
|
99
|
+
}
|
|
100
|
+
let mappingRequest;
|
|
101
|
+
let legacyPlanEvidence;
|
|
102
|
+
try {
|
|
103
|
+
mappingRequest = parseLegacyBillingMigrationRequest({
|
|
104
|
+
schemaVersion: envelope.data.schemaVersion,
|
|
105
|
+
mappings: envelope.data.mappings,
|
|
106
|
+
});
|
|
107
|
+
legacyPlanEvidence = parseLegacyBillingMigrationPlanEvidence(envelope.data.legacyPlanEvidence);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw new Error(`invalid billing migration apply: ${error instanceof Error ? error.message : String(error)}`);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
schemaVersion: 1,
|
|
114
|
+
mode: 'shadow',
|
|
115
|
+
mappings: mappingRequest.mappings ?? [],
|
|
116
|
+
expectedPreviewChecksum: envelope.data.expectedPreviewChecksum,
|
|
117
|
+
legacyPlanEvidence,
|
|
118
|
+
idempotencyKey: envelope.data.idempotencyKey,
|
|
119
|
+
reason: envelope.data.reason,
|
|
120
|
+
confirmed: true,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export function legacyBillingMigrationPlanEvidenceChecksum(evidence) {
|
|
124
|
+
return billingContentChecksum({
|
|
125
|
+
...evidence,
|
|
126
|
+
projections: [...evidence.projections].sort((a, b) => a.org.localeCompare(b.org)),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
export function legacyBillingMigrationRequestFingerprint(request, actor, service) {
|
|
130
|
+
return billingContentChecksum({
|
|
131
|
+
schemaVersion: request.schemaVersion,
|
|
132
|
+
mode: request.mode,
|
|
133
|
+
mappingChecksum: legacyBillingMigrationMappingChecksum(request.mappings),
|
|
134
|
+
expectedPreviewChecksum: request.expectedPreviewChecksum,
|
|
135
|
+
planEvidenceChecksum: legacyBillingMigrationPlanEvidenceChecksum(request.legacyPlanEvidence),
|
|
136
|
+
reason: request.reason,
|
|
137
|
+
confirmed: request.confirmed,
|
|
138
|
+
service: normalizeBillingMigrationServiceUrl(service),
|
|
139
|
+
actor: { subject: actor.subject, email: actor.email },
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
export function legacyBillingMigrationSuccessAudit(result, actor) {
|
|
143
|
+
return {
|
|
144
|
+
eventType: 'billing.migration.apply',
|
|
145
|
+
org: 'platform',
|
|
146
|
+
actorSubject: actor.subject,
|
|
147
|
+
actorEmail: actor.email,
|
|
148
|
+
decision: 'allow',
|
|
149
|
+
status: result.replayed ? 200 : 201,
|
|
150
|
+
details: {
|
|
151
|
+
replayed: result.replayed,
|
|
152
|
+
mode: result.mode,
|
|
153
|
+
state: result.state,
|
|
154
|
+
organizations: result.counts.organizations,
|
|
155
|
+
accountsCreated: result.counts.accountsCreated,
|
|
156
|
+
accountsReused: result.counts.accountsReused,
|
|
157
|
+
linksCreated: result.counts.linksCreated,
|
|
158
|
+
linksPreserved: result.counts.linksPreserved,
|
|
159
|
+
productionApps: result.counts.productionApps,
|
|
160
|
+
grantCandidateFundingSets: result.counts.grantCandidateFundingSets,
|
|
161
|
+
mappingChecksum: result.mappingChecksum,
|
|
162
|
+
previewChecksum: result.previewChecksum,
|
|
163
|
+
planEvidenceChecksum: result.planEvidenceChecksum,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export function normalizeBillingMigrationServiceUrl(value) {
|
|
168
|
+
const parsed = new URL(value);
|
|
169
|
+
if ((parsed.protocol !== 'https:' && parsed.protocol !== 'http:') ||
|
|
170
|
+
parsed.username !== '' ||
|
|
171
|
+
parsed.password !== '' ||
|
|
172
|
+
parsed.pathname !== '/' ||
|
|
173
|
+
parsed.search !== '' ||
|
|
174
|
+
parsed.hash !== '') {
|
|
175
|
+
throw new Error('billing migration service must be an HTTP(S) origin');
|
|
176
|
+
}
|
|
177
|
+
return parsed.origin;
|
|
178
|
+
}
|
|
179
|
+
function hasControlCharacters(value) {
|
|
180
|
+
return [...value].some((character) => {
|
|
181
|
+
const code = character.charCodeAt(0);
|
|
182
|
+
return code <= 0x1f || code === 0x7f;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function isBillingServiceOrigin(value) {
|
|
186
|
+
try {
|
|
187
|
+
normalizeBillingMigrationServiceUrl(value);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=migration-apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-apply.js","sourceRoot":"","sources":["../../src/billing/migration-apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type BillingIdentityRef, type GOOGLE_CONTROL_PLANE_ISSUER } from './model.js';
|
|
2
|
+
export interface LegacyProductionAppIdentity {
|
|
3
|
+
readonly app: string;
|
|
4
|
+
readonly createdAt: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LegacyUnlinkedOrganizationMapping {
|
|
7
|
+
readonly org: string;
|
|
8
|
+
readonly linkState: 'unlinked';
|
|
9
|
+
readonly defaultBillingOwnerSubject: string;
|
|
10
|
+
readonly productionApps: readonly LegacyProductionAppIdentity[];
|
|
11
|
+
}
|
|
12
|
+
export interface LegacyLinkedOrganizationMapping {
|
|
13
|
+
readonly org: string;
|
|
14
|
+
readonly linkState: 'linked';
|
|
15
|
+
readonly expectedBillingAccountId: string;
|
|
16
|
+
readonly expectedLinkVersion: number;
|
|
17
|
+
readonly productionApps: readonly LegacyProductionAppIdentity[];
|
|
18
|
+
}
|
|
19
|
+
export type LegacyBillingMigrationMapping = LegacyUnlinkedOrganizationMapping | LegacyLinkedOrganizationMapping;
|
|
20
|
+
export interface LegacyBillingMigrationRequest {
|
|
21
|
+
readonly schemaVersion: 1;
|
|
22
|
+
readonly mappings?: readonly LegacyBillingMigrationMapping[];
|
|
23
|
+
}
|
|
24
|
+
export type LegacyBillingMigrationBlockerCode = 'duplicate_org_mapping' | 'duplicate_production_app' | 'existing_link_conflict' | 'linked_organization_not_linked' | 'owner_mapping_required' | 'owner_billing_identity_invalid' | 'owner_billing_identity_conflict' | 'owner_not_org_owner' | 'owner_subject_unknown' | 'organization_not_found' | 'production_app_not_active' | 'production_app_not_found' | 'production_classification_required';
|
|
25
|
+
export interface LegacyBillingMigrationBlocker {
|
|
26
|
+
readonly code: LegacyBillingMigrationBlockerCode;
|
|
27
|
+
readonly org: string;
|
|
28
|
+
readonly message: string;
|
|
29
|
+
}
|
|
30
|
+
export interface LegacyBillingMigrationPreview {
|
|
31
|
+
readonly schemaVersion: 1;
|
|
32
|
+
readonly ready: boolean;
|
|
33
|
+
readonly organizations: readonly {
|
|
34
|
+
readonly org: string;
|
|
35
|
+
readonly ownerCandidates: readonly {
|
|
36
|
+
readonly subject: string;
|
|
37
|
+
readonly email: string;
|
|
38
|
+
}[];
|
|
39
|
+
readonly mappedOwnerSubject?: string;
|
|
40
|
+
readonly productionApps?: readonly LegacyProductionAppIdentity[];
|
|
41
|
+
}[];
|
|
42
|
+
readonly linkedOrganizations: readonly {
|
|
43
|
+
readonly org: string;
|
|
44
|
+
readonly billingAccountId: string;
|
|
45
|
+
readonly homeFreeBillingAccountId: string;
|
|
46
|
+
readonly homeOwner: BillingIdentityRef;
|
|
47
|
+
readonly fallbackBillingAccountId: string;
|
|
48
|
+
readonly version: number;
|
|
49
|
+
readonly productionApps?: readonly LegacyProductionAppIdentity[];
|
|
50
|
+
}[];
|
|
51
|
+
readonly fundingSets: readonly {
|
|
52
|
+
readonly destination: {
|
|
53
|
+
readonly kind: 'existing';
|
|
54
|
+
readonly billingAccountId: string;
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: 'proposed_default';
|
|
57
|
+
readonly identityIssuer: typeof GOOGLE_CONTROL_PLANE_ISSUER;
|
|
58
|
+
readonly subject: string;
|
|
59
|
+
};
|
|
60
|
+
readonly organizations: readonly string[];
|
|
61
|
+
readonly productionApps: readonly (LegacyProductionAppIdentity & {
|
|
62
|
+
readonly org: string;
|
|
63
|
+
})[];
|
|
64
|
+
readonly missingProductionClassifications: readonly string[];
|
|
65
|
+
}[];
|
|
66
|
+
readonly blockers: readonly LegacyBillingMigrationBlocker[];
|
|
67
|
+
readonly grantPolicy: {
|
|
68
|
+
readonly durationDays: 90;
|
|
69
|
+
readonly startsAt: 'billing_enforcement_cutover';
|
|
70
|
+
readonly expiresAt: null;
|
|
71
|
+
readonly eligibility: 'account_cohort_above_capacity';
|
|
72
|
+
};
|
|
73
|
+
/** Canonical SHA-256 over the complete preview except this self-referential field. */
|
|
74
|
+
readonly previewChecksum: string;
|
|
75
|
+
}
|
|
76
|
+
export declare function parseLegacyBillingMigrationRequest(value: unknown): LegacyBillingMigrationRequest;
|
|
77
|
+
export declare function legacyBillingMigrationPreviewChecksum(preview: Omit<LegacyBillingMigrationPreview, 'previewChecksum'> | LegacyBillingMigrationPreview): string;
|
|
78
|
+
export declare function legacyBillingMigrationMappingChecksum(mappings: readonly LegacyBillingMigrationMapping[]): string;
|
|
79
|
+
//# sourceMappingURL=migration-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-contract.d.ts","sourceRoot":"","sources":["../../src/billing/migration-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { validateSlug } from '../store/validate.js';
|
|
3
|
+
import { billingContentChecksum, validateBillingAccountId, } from './model.js';
|
|
4
|
+
const appSlugSchema = z
|
|
5
|
+
.string()
|
|
6
|
+
.trim()
|
|
7
|
+
.refine((value) => isValidSlug('app', value), 'invalid app slug');
|
|
8
|
+
const orgSlugSchema = z
|
|
9
|
+
.string()
|
|
10
|
+
.trim()
|
|
11
|
+
.refine((value) => isValidSlug('org', value), 'invalid organization slug');
|
|
12
|
+
const billingAccountIdSchema = z
|
|
13
|
+
.string()
|
|
14
|
+
.trim()
|
|
15
|
+
.refine(isValidBillingAccountId, 'invalid billing account ID');
|
|
16
|
+
const productionAppIdentitySchema = z.strictObject({
|
|
17
|
+
app: appSlugSchema,
|
|
18
|
+
createdAt: z.iso.datetime({ offset: true }).transform((value) => new Date(value).toISOString()),
|
|
19
|
+
});
|
|
20
|
+
const legacyBillingMigrationRequestSchema = z.strictObject({
|
|
21
|
+
schemaVersion: z.literal(1),
|
|
22
|
+
mappings: z
|
|
23
|
+
.array(z.discriminatedUnion('linkState', [
|
|
24
|
+
z.strictObject({
|
|
25
|
+
org: orgSlugSchema,
|
|
26
|
+
linkState: z.literal('unlinked'),
|
|
27
|
+
defaultBillingOwnerSubject: z.string().trim().min(1).max(512),
|
|
28
|
+
productionApps: z.array(productionAppIdentitySchema),
|
|
29
|
+
}),
|
|
30
|
+
z.strictObject({
|
|
31
|
+
org: orgSlugSchema,
|
|
32
|
+
linkState: z.literal('linked'),
|
|
33
|
+
expectedBillingAccountId: billingAccountIdSchema,
|
|
34
|
+
expectedLinkVersion: z.number().int().positive(),
|
|
35
|
+
productionApps: z.array(productionAppIdentitySchema),
|
|
36
|
+
}),
|
|
37
|
+
]))
|
|
38
|
+
.optional(),
|
|
39
|
+
});
|
|
40
|
+
export function parseLegacyBillingMigrationRequest(value) {
|
|
41
|
+
const result = legacyBillingMigrationRequestSchema.safeParse(value);
|
|
42
|
+
if (!result.success) {
|
|
43
|
+
throw new Error(`invalid billing migration preview: ${z.prettifyError(result.error)}`);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
schemaVersion: result.data.schemaVersion,
|
|
47
|
+
...(result.data.mappings !== undefined
|
|
48
|
+
? {
|
|
49
|
+
mappings: result.data.mappings.map((mapping) => ({
|
|
50
|
+
...mapping,
|
|
51
|
+
})),
|
|
52
|
+
}
|
|
53
|
+
: {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function legacyBillingMigrationPreviewChecksum(preview) {
|
|
57
|
+
const { previewChecksum: _checksum, ...content } = preview;
|
|
58
|
+
return billingContentChecksum(content);
|
|
59
|
+
}
|
|
60
|
+
export function legacyBillingMigrationMappingChecksum(mappings) {
|
|
61
|
+
return billingContentChecksum(mappings
|
|
62
|
+
.map((mapping) => ({
|
|
63
|
+
...mapping,
|
|
64
|
+
productionApps: [...mapping.productionApps].sort((a, b) => a.app.localeCompare(b.app) || a.createdAt.localeCompare(b.createdAt)),
|
|
65
|
+
}))
|
|
66
|
+
.sort((a, b) => a.org.localeCompare(b.org) || JSON.stringify(a).localeCompare(JSON.stringify(b))));
|
|
67
|
+
}
|
|
68
|
+
function isValidBillingAccountId(value) {
|
|
69
|
+
try {
|
|
70
|
+
validateBillingAccountId(value);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function isValidSlug(kind, value) {
|
|
78
|
+
try {
|
|
79
|
+
validateSlug(kind, value);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=migration-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-contract.js","sourceRoot":"","sources":["../../src/billing/migration-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +1,6 @@
|
|
|
1
1
|
import type { ControlPlaneStore } from '../store.js';
|
|
2
|
-
import { type
|
|
3
|
-
export
|
|
4
|
-
readonly app: string;
|
|
5
|
-
readonly createdAt: string;
|
|
6
|
-
}
|
|
7
|
-
export interface LegacyUnlinkedOrganizationMapping {
|
|
8
|
-
readonly org: string;
|
|
9
|
-
readonly linkState: 'unlinked';
|
|
10
|
-
readonly defaultBillingOwnerSubject: string;
|
|
11
|
-
readonly productionApps: readonly LegacyProductionAppIdentity[];
|
|
12
|
-
}
|
|
13
|
-
export interface LegacyLinkedOrganizationMapping {
|
|
14
|
-
readonly org: string;
|
|
15
|
-
readonly linkState: 'linked';
|
|
16
|
-
readonly expectedBillingAccountId: string;
|
|
17
|
-
readonly expectedLinkVersion: number;
|
|
18
|
-
readonly productionApps: readonly LegacyProductionAppIdentity[];
|
|
19
|
-
}
|
|
20
|
-
export type LegacyBillingMigrationMapping = LegacyUnlinkedOrganizationMapping | LegacyLinkedOrganizationMapping;
|
|
21
|
-
export interface LegacyBillingMigrationRequest {
|
|
22
|
-
readonly schemaVersion: 1;
|
|
23
|
-
readonly mappings?: readonly LegacyBillingMigrationMapping[];
|
|
24
|
-
}
|
|
25
|
-
export type LegacyBillingMigrationBlockerCode = 'duplicate_org_mapping' | 'duplicate_production_app' | 'existing_link_conflict' | 'linked_organization_not_linked' | 'owner_mapping_required' | 'owner_billing_identity_invalid' | 'owner_not_org_owner' | 'owner_subject_unknown' | 'organization_not_found' | 'production_app_not_active' | 'production_app_not_found' | 'production_classification_required';
|
|
26
|
-
export interface LegacyBillingMigrationBlocker {
|
|
27
|
-
readonly code: LegacyBillingMigrationBlockerCode;
|
|
28
|
-
readonly org: string;
|
|
29
|
-
readonly message: string;
|
|
30
|
-
}
|
|
2
|
+
import { type LegacyBillingMigrationPreview, type LegacyBillingMigrationRequest } from './migration-contract.js';
|
|
3
|
+
export { type LegacyBillingMigrationBlocker, type LegacyBillingMigrationBlockerCode, type LegacyBillingMigrationMapping, type LegacyBillingMigrationPreview, type LegacyBillingMigrationRequest, type LegacyLinkedOrganizationMapping, type LegacyProductionAppIdentity, type LegacyUnlinkedOrganizationMapping, legacyBillingMigrationMappingChecksum, legacyBillingMigrationPreviewChecksum, parseLegacyBillingMigrationRequest, } from './migration-contract.js';
|
|
31
4
|
export interface LegacyBillingMigrationInventory {
|
|
32
5
|
getAppIdentity(org: string, app: string): Promise<{
|
|
33
6
|
readonly createdAt: string;
|
|
@@ -35,50 +8,6 @@ export interface LegacyBillingMigrationInventory {
|
|
|
35
8
|
readonly archivedAt?: string;
|
|
36
9
|
} | undefined>;
|
|
37
10
|
}
|
|
38
|
-
export
|
|
39
|
-
export
|
|
40
|
-
readonly schemaVersion: 1;
|
|
41
|
-
readonly ready: boolean;
|
|
42
|
-
readonly organizations: readonly {
|
|
43
|
-
readonly org: string;
|
|
44
|
-
readonly ownerCandidates: readonly {
|
|
45
|
-
readonly subject: string;
|
|
46
|
-
readonly email: string;
|
|
47
|
-
}[];
|
|
48
|
-
readonly mappedOwnerSubject?: string;
|
|
49
|
-
readonly productionApps?: readonly LegacyProductionAppIdentity[];
|
|
50
|
-
}[];
|
|
51
|
-
readonly linkedOrganizations: readonly {
|
|
52
|
-
readonly org: string;
|
|
53
|
-
readonly billingAccountId: string;
|
|
54
|
-
readonly homeFreeBillingAccountId: string;
|
|
55
|
-
readonly homeOwner: BillingIdentityRef;
|
|
56
|
-
readonly fallbackBillingAccountId: string;
|
|
57
|
-
readonly version: number;
|
|
58
|
-
readonly productionApps?: readonly LegacyProductionAppIdentity[];
|
|
59
|
-
}[];
|
|
60
|
-
readonly fundingSets: readonly {
|
|
61
|
-
readonly destination: {
|
|
62
|
-
readonly kind: 'existing';
|
|
63
|
-
readonly billingAccountId: string;
|
|
64
|
-
} | {
|
|
65
|
-
readonly kind: 'proposed_default';
|
|
66
|
-
readonly identityIssuer: typeof GOOGLE_CONTROL_PLANE_ISSUER;
|
|
67
|
-
readonly subject: string;
|
|
68
|
-
};
|
|
69
|
-
readonly organizations: readonly string[];
|
|
70
|
-
readonly productionApps: readonly (LegacyProductionAppIdentity & {
|
|
71
|
-
readonly org: string;
|
|
72
|
-
})[];
|
|
73
|
-
readonly missingProductionClassifications: readonly string[];
|
|
74
|
-
}[];
|
|
75
|
-
readonly blockers: readonly LegacyBillingMigrationBlocker[];
|
|
76
|
-
readonly grantPolicy: {
|
|
77
|
-
readonly durationDays: 90;
|
|
78
|
-
readonly startsAt: 'billing_enforcement_cutover';
|
|
79
|
-
readonly expiresAt: null;
|
|
80
|
-
readonly eligibility: 'account_cohort_above_capacity';
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
export declare function previewLegacyBillingMigration(store: ControlPlaneStore, request: LegacyBillingMigrationRequest, inventory?: LegacyBillingMigrationInventory): Promise<LegacyBillingMigrationPreview>;
|
|
11
|
+
export type LegacyBillingMigrationControlPlane = Pick<ControlPlaneStore, 'listOrgs' | 'listOrgMembers' | 'getOrgBillingLink' | 'getDefaultBillingAccount'>;
|
|
12
|
+
export declare function previewLegacyBillingMigration(store: LegacyBillingMigrationControlPlane, request: LegacyBillingMigrationRequest, inventory?: LegacyBillingMigrationInventory): Promise<LegacyBillingMigrationPreview>;
|
|
84
13
|
//# sourceMappingURL=migration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/billing/migration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/billing/migration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAGL,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAGnC,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,iCAAiC,EACtC,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAClC,KAAK,+BAA+B,EACpC,KAAK,2BAA2B,EAChC,KAAK,iCAAiC,EACtC,qCAAqC,EACrC,qCAAqC,EACrC,kCAAkC,GACnC,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,+BAA+B;IAC9C,cAAc,CACZ,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,OAAO,CACN;QACE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;KAC9B,GACD,SAAS,CACZ,CAAC;CACH;AAED,MAAM,MAAM,kCAAkC,GAAG,IAAI,CACnD,iBAAiB,EACjB,UAAU,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,0BAA0B,CACjF,CAAC;AAWF,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,kCAAkC,EACzC,OAAO,EAAE,6BAA6B,EACtC,SAAS,CAAC,EAAE,+BAA+B,GAC1C,OAAO,CAAC,6BAA6B,CAAC,CAuNxC"}
|
|
@@ -1,58 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { GOOGLE_CONTROL_PLANE_ISSUER, normalizeBillingEmail, normalizeBillingIdentity,
|
|
4
|
-
|
|
5
|
-
.string()
|
|
6
|
-
.trim()
|
|
7
|
-
.refine((value) => isValidSlug('app', value), 'invalid app slug');
|
|
8
|
-
const orgSlugSchema = z
|
|
9
|
-
.string()
|
|
10
|
-
.trim()
|
|
11
|
-
.refine((value) => isValidSlug('org', value), 'invalid organization slug');
|
|
12
|
-
const billingAccountIdSchema = z
|
|
13
|
-
.string()
|
|
14
|
-
.trim()
|
|
15
|
-
.refine(isValidBillingAccountId, 'invalid billing account ID');
|
|
16
|
-
const productionAppIdentitySchema = z.strictObject({
|
|
17
|
-
app: appSlugSchema,
|
|
18
|
-
createdAt: z.iso.datetime({ offset: true }).transform((value) => new Date(value).toISOString()),
|
|
19
|
-
});
|
|
20
|
-
const legacyBillingMigrationRequestSchema = z.strictObject({
|
|
21
|
-
schemaVersion: z.literal(1),
|
|
22
|
-
mappings: z
|
|
23
|
-
.array(z.discriminatedUnion('linkState', [
|
|
24
|
-
z.strictObject({
|
|
25
|
-
org: orgSlugSchema,
|
|
26
|
-
linkState: z.literal('unlinked'),
|
|
27
|
-
defaultBillingOwnerSubject: z.string().trim().min(1).max(512),
|
|
28
|
-
productionApps: z.array(productionAppIdentitySchema),
|
|
29
|
-
}),
|
|
30
|
-
z.strictObject({
|
|
31
|
-
org: orgSlugSchema,
|
|
32
|
-
linkState: z.literal('linked'),
|
|
33
|
-
expectedBillingAccountId: billingAccountIdSchema,
|
|
34
|
-
expectedLinkVersion: z.number().int().positive(),
|
|
35
|
-
productionApps: z.array(productionAppIdentitySchema),
|
|
36
|
-
}),
|
|
37
|
-
]))
|
|
38
|
-
.optional(),
|
|
39
|
-
});
|
|
40
|
-
export function parseLegacyBillingMigrationRequest(value) {
|
|
41
|
-
const result = legacyBillingMigrationRequestSchema.safeParse(value);
|
|
42
|
-
if (!result.success) {
|
|
43
|
-
throw new Error(`invalid billing migration preview: ${z.prettifyError(result.error)}`);
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
schemaVersion: result.data.schemaVersion,
|
|
47
|
-
...(result.data.mappings !== undefined
|
|
48
|
-
? {
|
|
49
|
-
mappings: result.data.mappings.map((mapping) => ({
|
|
50
|
-
...mapping,
|
|
51
|
-
})),
|
|
52
|
-
}
|
|
53
|
-
: {}),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
1
|
+
import { isSystemOwnedOrgSlug } from '../store/validate.js';
|
|
2
|
+
import { legacyBillingMigrationPreviewChecksum, } from './migration-contract.js';
|
|
3
|
+
import { GOOGLE_CONTROL_PLANE_ISSUER, normalizeBillingEmail, normalizeBillingIdentity, } from './model.js';
|
|
4
|
+
export { legacyBillingMigrationMappingChecksum, legacyBillingMigrationPreviewChecksum, parseLegacyBillingMigrationRequest, } from './migration-contract.js';
|
|
56
5
|
export async function previewLegacyBillingMigration(store, request, inventory) {
|
|
57
6
|
if (request.schemaVersion !== 1)
|
|
58
7
|
throw new Error('unsupported billing migration schemaVersion');
|
|
@@ -73,6 +22,7 @@ export async function previewLegacyBillingMigration(store, request, inventory) {
|
|
|
73
22
|
const organizations = [];
|
|
74
23
|
const linkedOrganizations = [];
|
|
75
24
|
const fundingSets = new Map();
|
|
25
|
+
const selectedOwnerEmails = new Map();
|
|
76
26
|
const knownOrgs = new Set();
|
|
77
27
|
for (const org of await store.listOrgs()) {
|
|
78
28
|
if (isSystemOwnedOrgSlug(org.slug))
|
|
@@ -167,6 +117,18 @@ export async function previewLegacyBillingMigration(store, request, inventory) {
|
|
|
167
117
|
});
|
|
168
118
|
continue;
|
|
169
119
|
}
|
|
120
|
+
const ownerIdentityKey = `${GOOGLE_CONTROL_PLANE_ISSUER}\u0000${selectedSubject}`;
|
|
121
|
+
const normalizedOwnerEmail = normalizeBillingEmail(selectedOwner.email);
|
|
122
|
+
const priorOwnerEmail = selectedOwnerEmails.get(ownerIdentityKey);
|
|
123
|
+
if (priorOwnerEmail !== undefined && priorOwnerEmail !== normalizedOwnerEmail) {
|
|
124
|
+
blockers.push({
|
|
125
|
+
code: 'owner_billing_identity_conflict',
|
|
126
|
+
org: org.slug,
|
|
127
|
+
message: 'mapped billing owner has conflicting current emails across organizations',
|
|
128
|
+
});
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
selectedOwnerEmails.set(ownerIdentityKey, normalizedOwnerEmail);
|
|
170
132
|
const validProductionApps = await validateProductionApps(org.slug, mapping.productionApps, inventory, blockers);
|
|
171
133
|
if (!validProductionApps)
|
|
172
134
|
continue;
|
|
@@ -191,7 +153,7 @@ export async function previewLegacyBillingMigration(store, request, inventory) {
|
|
|
191
153
|
message: 'mapping references an unknown organization',
|
|
192
154
|
});
|
|
193
155
|
}
|
|
194
|
-
|
|
156
|
+
const preview = {
|
|
195
157
|
schemaVersion: 1,
|
|
196
158
|
ready: blockers.length === 0 &&
|
|
197
159
|
[...fundingSets.values()].every((set) => set.missingProductionClassifications.length === 0),
|
|
@@ -215,6 +177,7 @@ export async function previewLegacyBillingMigration(store, request, inventory) {
|
|
|
215
177
|
eligibility: 'account_cohort_above_capacity',
|
|
216
178
|
},
|
|
217
179
|
};
|
|
180
|
+
return { ...preview, previewChecksum: legacyBillingMigrationPreviewChecksum(preview) };
|
|
218
181
|
}
|
|
219
182
|
async function validateProductionApps(org, productionApps, inventory, blockers) {
|
|
220
183
|
let valid = true;
|
|
@@ -280,22 +243,4 @@ function fundingDestinationKey(destination) {
|
|
|
280
243
|
? `existing:${destination.billingAccountId}`
|
|
281
244
|
: `proposed:${destination.identityIssuer}:${destination.subject}`;
|
|
282
245
|
}
|
|
283
|
-
function isValidBillingAccountId(value) {
|
|
284
|
-
try {
|
|
285
|
-
validateBillingAccountId(value);
|
|
286
|
-
return true;
|
|
287
|
-
}
|
|
288
|
-
catch {
|
|
289
|
-
return false;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
function isValidSlug(kind, value) {
|
|
293
|
-
try {
|
|
294
|
-
validateSlug(kind, value);
|
|
295
|
-
return true;
|
|
296
|
-
}
|
|
297
|
-
catch {
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
246
|
//# sourceMappingURL=migration.js.map
|