Skip to content

Commit d7cf53c

Browse files
authored
migration dashboard (#5495)
* migration dashboard * remove customer facing code * fix build * clean up * build
1 parent 4efa7aa commit d7cf53c

File tree

16 files changed

+92127
-579
lines changed

16 files changed

+92127
-579
lines changed

.claude/settings.local.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,14 @@
101101
"WebFetch(domain:streamdown.ai)",
102102
"mcp__ide__getDiagnostics",
103103
"Bash(yarn cf-typegen:*)",
104-
"WebFetch(domain:docs.stripe.com)"
104+
"WebFetch(domain:docs.stripe.com)",
105+
"Bash(npx tsoa:*)",
106+
"Bash(python3:*)"
105107
],
106108
"deny": []
107109
},
108110
"enableAllProjectMcpServers": true,
109-
"enabledMcpjsonServers": ["playwright"]
111+
"enabledMcpjsonServers": [
112+
"playwright"
113+
]
110114
}

bifrost/lib/clients/jawnTypes/private.ts

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,54 @@ export interface paths {
649649
/** @description Update a saved query for admin (stored under admin org ID) */
650650
patch: operations["UpdateAdminSavedQuery"];
651651
};
652+
"/v1/admin/pricing-migration/pending": {
653+
/**
654+
* @description Get all organizations that need to be migrated to new pricing
655+
* Supports pagination, search, and tier filtering
656+
*/
657+
post: operations["GetPendingMigrations"];
658+
};
659+
"/v1/admin/pricing-migration/migrate/{orgId}": {
660+
/** @description Migrate a single organization to new pricing (legacy - use migrate-instant or migrate-scheduled instead) */
661+
post: operations["MigrateOrganization"];
662+
};
663+
"/v1/admin/pricing-migration/migrate-instant/{orgId}": {
664+
/**
665+
* @description Migrate instantly with usage backfill
666+
* Updates subscription immediately and backfills metered usage events for current billing period
667+
*/
668+
post: operations["MigrateInstant"];
669+
};
670+
"/v1/admin/pricing-migration/migrate-scheduled/{orgId}": {
671+
/**
672+
* @description Schedule migration for next billing period
673+
* Uses Stripe subscription schedules to defer the pricing change
674+
*/
675+
post: operations["MigrateScheduled"];
676+
};
677+
"/v1/admin/pricing-migration/completed": {
678+
/** @description Get migration history/status */
679+
get: operations["GetCompletedMigrations"];
680+
};
681+
"/v1/admin/pricing-migration/reapply/{orgId}": {
682+
/** @description Reapply migration for an already migrated organization (for fixing issues) */
683+
post: operations["ReapplyMigration"];
684+
};
685+
"/v1/admin/pricing-migration/org/{orgId}": {
686+
/** @description Get organization details for admin view */
687+
get: operations["GetOrgDetails"];
688+
};
689+
"/v1/admin/pricing-migration/add-usage/{orgId}": {
690+
/**
691+
* @description Add metered usage for an organization (for testing/fixing billing)
692+
* Uses Stripe Billing Meter events
693+
*/
694+
post: operations["AddMeteredUsage"];
695+
};
696+
"/v1/admin/pricing-migration/switch-to-free/{orgId}": {
697+
/** @description Switch an organization to free tier (for cancelled subscriptions) */
698+
post: operations["SwitchToFree"];
699+
};
652700
"/v1/credits/balance": {
653701
get: operations["GetCreditsBalance"];
654702
};
@@ -16371,6 +16419,84 @@ Json: JsonObject;
1637116419
error: null;
1637216420
};
1637316421
"Result__rows-Record_string.any_-Array--elapsedMilliseconds-number--size-number--rowCount-number_.string_": components["schemas"]["ResultSuccess__rows-Record_string.any_-Array--elapsedMilliseconds-number--size-number--rowCount-number__"] | components["schemas"]["ResultError_string_"];
16422+
"ResultSuccess__previousTier-string--newTier-string--subscriptionId-string__": {
16423+
data: {
16424+
subscriptionId: string;
16425+
newTier: string;
16426+
previousTier: string;
16427+
};
16428+
/** @enum {number|null} */
16429+
error: null;
16430+
};
16431+
"Result__previousTier-string--newTier-string--subscriptionId-string_.string_": components["schemas"]["ResultSuccess__previousTier-string--newTier-string--subscriptionId-string__"] | components["schemas"]["ResultError_string_"];
16432+
"ResultSuccess__previousTier-string--newTier-string--subscriptionId-string--usage_58__requests-number--storageBytes-number--storageMb-number--source-clickhouse-or-override_--backfillResult_58__requestsEvent-string--storageEvent-string___": {
16433+
data: {
16434+
backfillResult: {
16435+
storageEvent: string;
16436+
requestsEvent: string;
16437+
};
16438+
usage: {
16439+
/** @enum {string} */
16440+
source: "clickhouse" | "override";
16441+
/** Format: double */
16442+
storageMb: number;
16443+
/** Format: double */
16444+
storageBytes: number;
16445+
/** Format: double */
16446+
requests: number;
16447+
};
16448+
subscriptionId: string;
16449+
newTier: string;
16450+
previousTier: string;
16451+
};
16452+
/** @enum {number|null} */
16453+
error: null;
16454+
};
16455+
"Result__previousTier-string--newTier-string--subscriptionId-string--usage_58__requests-number--storageBytes-number--storageMb-number--source-clickhouse-or-override_--backfillResult_58__requestsEvent-string--storageEvent-string__.string_": components["schemas"]["ResultSuccess__previousTier-string--newTier-string--subscriptionId-string--usage_58__requests-number--storageBytes-number--storageMb-number--source-clickhouse-or-override_--backfillResult_58__requestsEvent-string--storageEvent-string___"] | components["schemas"]["ResultError_string_"];
16456+
"ResultSuccess__previousTier-string--newTier-string--subscriptionId-string--scheduleId-string--scheduledFor-string__": {
16457+
data: {
16458+
scheduledFor: string;
16459+
scheduleId: string;
16460+
subscriptionId: string;
16461+
newTier: string;
16462+
previousTier: string;
16463+
};
16464+
/** @enum {number|null} */
16465+
error: null;
16466+
};
16467+
"Result__previousTier-string--newTier-string--subscriptionId-string--scheduleId-string--scheduledFor-string_.string_": components["schemas"]["ResultSuccess__previousTier-string--newTier-string--subscriptionId-string--scheduleId-string--scheduledFor-string__"] | components["schemas"]["ResultError_string_"];
16468+
"ResultSuccess__id-string--name-string--tier-string--stripe_customer_id-string-or-null--stripe_subscription_id-string-or-null--subscription_status-string-or-null--owner_email-string-or-null--created_at-string__": {
16469+
data: {
16470+
created_at: string;
16471+
owner_email: string | null;
16472+
subscription_status: string | null;
16473+
stripe_subscription_id: string | null;
16474+
stripe_customer_id: string | null;
16475+
tier: string;
16476+
name: string;
16477+
id: string;
16478+
};
16479+
/** @enum {number|null} */
16480+
error: null;
16481+
};
16482+
"Result__id-string--name-string--tier-string--stripe_customer_id-string-or-null--stripe_subscription_id-string-or-null--subscription_status-string-or-null--owner_email-string-or-null--created_at-string_.string_": components["schemas"]["ResultSuccess__id-string--name-string--tier-string--stripe_customer_id-string-or-null--stripe_subscription_id-string-or-null--subscription_status-string-or-null--owner_email-string-or-null--created_at-string__"] | components["schemas"]["ResultError_string_"];
16483+
"ResultSuccess__message-string__": {
16484+
data: {
16485+
message: string;
16486+
};
16487+
/** @enum {number|null} */
16488+
error: null;
16489+
};
16490+
"Result__message-string_.string_": components["schemas"]["ResultSuccess__message-string__"] | components["schemas"]["ResultError_string_"];
16491+
"ResultSuccess__message-string--previousTier-string__": {
16492+
data: {
16493+
previousTier: string;
16494+
message: string;
16495+
};
16496+
/** @enum {number|null} */
16497+
error: null;
16498+
};
16499+
"Result__message-string--previousTier-string_.string_": components["schemas"]["ResultSuccess__message-string--previousTier-string__"] | components["schemas"]["ResultError_string_"];
1637416500
CreditBalanceResponse: {
1637516501
/** Format: double */
1637616502
totalCreditsPurchased: number;
@@ -20570,6 +20696,220 @@ export interface operations {
2057020696
};
2057120697
};
2057220698
};
20699+
/**
20700+
* @description Get all organizations that need to be migrated to new pricing
20701+
* Supports pagination, search, and tier filtering
20702+
*/
20703+
GetPendingMigrations: {
20704+
requestBody: {
20705+
content: {
20706+
"application/json": {
20707+
tierFilter?: string[];
20708+
search?: string;
20709+
/** Format: double */
20710+
offset?: number;
20711+
/** Format: double */
20712+
limit?: number;
20713+
};
20714+
};
20715+
};
20716+
responses: {
20717+
/** @description Ok */
20718+
200: {
20719+
content: {
20720+
"application/json": {
20721+
hasMore: boolean;
20722+
summary: {
20723+
byTier: components["schemas"]["Record_string.number_"];
20724+
/** Format: double */
20725+
total: number;
20726+
};
20727+
organizations: ({
20728+
/** Format: double */
20729+
member_count: number;
20730+
created_at: string;
20731+
stripe_status: string | null;
20732+
subscription_status: string | null;
20733+
stripe_subscription_id: string | null;
20734+
stripe_customer_id: string | null;
20735+
owner_email: string | null;
20736+
tier: string;
20737+
name: string;
20738+
id: string;
20739+
})[];
20740+
};
20741+
};
20742+
};
20743+
};
20744+
};
20745+
/** @description Migrate a single organization to new pricing (legacy - use migrate-instant or migrate-scheduled instead) */
20746+
MigrateOrganization: {
20747+
parameters: {
20748+
path: {
20749+
orgId: string;
20750+
};
20751+
};
20752+
responses: {
20753+
/** @description Ok */
20754+
200: {
20755+
content: {
20756+
"application/json": components["schemas"]["Result__previousTier-string--newTier-string--subscriptionId-string_.string_"];
20757+
};
20758+
};
20759+
};
20760+
};
20761+
/**
20762+
* @description Migrate instantly with usage backfill
20763+
* Updates subscription immediately and backfills metered usage events for current billing period
20764+
*/
20765+
MigrateInstant: {
20766+
parameters: {
20767+
path: {
20768+
orgId: string;
20769+
};
20770+
};
20771+
requestBody: {
20772+
content: {
20773+
"application/json": {
20774+
/** Format: double */
20775+
storageBytesOverride?: number;
20776+
/** Format: double */
20777+
requestsOverride?: number;
20778+
};
20779+
};
20780+
};
20781+
responses: {
20782+
/** @description Ok */
20783+
200: {
20784+
content: {
20785+
"application/json": components["schemas"]["Result__previousTier-string--newTier-string--subscriptionId-string--usage_58__requests-number--storageBytes-number--storageMb-number--source-clickhouse-or-override_--backfillResult_58__requestsEvent-string--storageEvent-string__.string_"];
20786+
};
20787+
};
20788+
};
20789+
};
20790+
/**
20791+
* @description Schedule migration for next billing period
20792+
* Uses Stripe subscription schedules to defer the pricing change
20793+
*/
20794+
MigrateScheduled: {
20795+
parameters: {
20796+
path: {
20797+
orgId: string;
20798+
};
20799+
};
20800+
responses: {
20801+
/** @description Ok */
20802+
200: {
20803+
content: {
20804+
"application/json": components["schemas"]["Result__previousTier-string--newTier-string--subscriptionId-string--scheduleId-string--scheduledFor-string_.string_"];
20805+
};
20806+
};
20807+
};
20808+
};
20809+
/** @description Get migration history/status */
20810+
GetCompletedMigrations: {
20811+
responses: {
20812+
/** @description Ok */
20813+
200: {
20814+
content: {
20815+
"application/json": {
20816+
summary: {
20817+
byTier: components["schemas"]["Record_string.number_"];
20818+
/** Format: double */
20819+
total: number;
20820+
};
20821+
organizations: ({
20822+
subscription_status: string | null;
20823+
stripe_subscription_id: string | null;
20824+
stripe_customer_id: string | null;
20825+
owner_email: string | null;
20826+
tier: string;
20827+
name: string;
20828+
id: string;
20829+
})[];
20830+
};
20831+
};
20832+
};
20833+
};
20834+
};
20835+
/** @description Reapply migration for an already migrated organization (for fixing issues) */
20836+
ReapplyMigration: {
20837+
parameters: {
20838+
path: {
20839+
orgId: string;
20840+
};
20841+
};
20842+
responses: {
20843+
/** @description Ok */
20844+
200: {
20845+
content: {
20846+
"application/json": components["schemas"]["Result__previousTier-string--newTier-string--subscriptionId-string_.string_"];
20847+
};
20848+
};
20849+
};
20850+
};
20851+
/** @description Get organization details for admin view */
20852+
GetOrgDetails: {
20853+
parameters: {
20854+
path: {
20855+
orgId: string;
20856+
};
20857+
};
20858+
responses: {
20859+
/** @description Ok */
20860+
200: {
20861+
content: {
20862+
"application/json": components["schemas"]["Result__id-string--name-string--tier-string--stripe_customer_id-string-or-null--stripe_subscription_id-string-or-null--subscription_status-string-or-null--owner_email-string-or-null--created_at-string_.string_"];
20863+
};
20864+
};
20865+
};
20866+
};
20867+
/**
20868+
* @description Add metered usage for an organization (for testing/fixing billing)
20869+
* Uses Stripe Billing Meter events
20870+
*/
20871+
AddMeteredUsage: {
20872+
parameters: {
20873+
path: {
20874+
orgId: string;
20875+
};
20876+
};
20877+
requestBody: {
20878+
content: {
20879+
"application/json": {
20880+
timestamp?: string;
20881+
/** Format: double */
20882+
quantity: number;
20883+
/** @enum {string} */
20884+
usageType: "requests" | "storage_gb";
20885+
};
20886+
};
20887+
};
20888+
responses: {
20889+
/** @description Ok */
20890+
200: {
20891+
content: {
20892+
"application/json": components["schemas"]["Result__message-string_.string_"];
20893+
};
20894+
};
20895+
};
20896+
};
20897+
/** @description Switch an organization to free tier (for cancelled subscriptions) */
20898+
SwitchToFree: {
20899+
parameters: {
20900+
path: {
20901+
orgId: string;
20902+
};
20903+
};
20904+
responses: {
20905+
/** @description Ok */
20906+
200: {
20907+
content: {
20908+
"application/json": components["schemas"]["Result__message-string--previousTier-string_.string_"];
20909+
};
20910+
};
20911+
};
20912+
};
2057320913
GetCreditsBalance: {
2057420914
responses: {
2057520915
/** @description Ok */

0 commit comments

Comments
 (0)