diff --git a/.specs/coding-plans.md b/.specs/coding-plans.md index 40bcfb817f..1cc6402006 100644 --- a/.specs/coding-plans.md +++ b/.specs/coding-plans.md @@ -16,7 +16,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S **Managed Plan Credential** - An upstream API key acquired or provisioned by Kilo for a Coding Plan. Kilo manages its assignment and revocation. It is paired with an Upstream Plan ID and is not exposed to the subscriber after it is installed in BYOK. -**Installed BYOK Configuration** - A normal personal BYOK entry that Kilo initially populates with a Managed Plan Credential. While unchanged, it identifies Token Plan Plus as its origin and Kilo may delete it at Effective Cancellation. A subscriber may test, enable, disable, update, or delete it using normal BYOK operations. Replacing its credential transfers cleanup ownership to the subscriber. +**Installed BYOK Configuration** - A normal personal BYOK entry that Kilo initially populates with a Managed Plan Credential. While unchanged, it identifies the MiniMax Coding Plan as its origin and Kilo may delete it at Effective Cancellation. A subscriber may test, enable, disable, update, or delete it using normal BYOK operations. Replacing its credential transfers cleanup ownership to the subscriber. **Availability Notification Intent** - A user's plan-scoped request to be notified when a sold-out Coding Plan has capacity again. It is not a reservation, purchase, subscription, or entitlement. @@ -42,7 +42,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S 1.4. A Plan ID **MUST NOT** be treated as the upstream provider identity. Multiple future plans from one upstream provider **MAY** coexist without extending or replacing one another unless their product rules explicitly state otherwise. -1.5. The initial implementation is intended to configure one offering: MiniMax Token Plan Plus. This initial offering does not impose a requirement that future catalogs contain MiniMax or any minimum number of offerings. +1.5. The MiniMax token catalog **MUST** contain Token Plan Plus, Token Plan Max, and Token Plan Ultra. All MiniMax token offerings **MUST** share the ordinary MiniMax BYOK provider ID, `minimax`. 1.6. When no assignable Managed Plan Credential exists for an offering, customer-facing catalog responses **MUST** identify the offering as sold out without exposing credential counts or credential metadata. @@ -50,11 +50,11 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S 2.1. Users **MUST** be able to purchase a Coding Plan using Kilo Credits through Kilo. The system **MUST NOT** redirect a user to an upstream provider to subscribe. -2.2. The system **MUST** allow at most one non-terminal subscription for a given user and Plan ID. A terminal subscription **MUST NOT** prevent a later new subscription to the same Plan ID. +2.2. The system **MUST** allow at most one live Coding Plan subscription for a given user and provider ID. A subscription with `active` or `past_due` status, including an active subscription pending cancellation at period end, is live. A terminal subscription **MUST NOT** prevent a later new subscription to the same provider ID. 2.3. Each purchase request **MUST** include an idempotency key scoped to the user and Plan ID. Retrying a successfully processed request with the same idempotency key **MUST** return the original outcome and **MUST NOT** create an additional billing period, charge, or credential assignment. -2.4. The initial release **MUST NOT** sell an additional prepaid period for a non-terminal subscription. A successful idempotent retry **MUST** return the existing purchase result; all other purchase attempts while a subscription is `active` or `past_due` **MUST** be rejected. Later-period billing occurs only through recurring renewal in the initial release. +2.4. The initial release **MUST NOT** sell an additional prepaid period for a live subscription. A successful idempotent retry **MUST** return the existing purchase result; all other purchase attempts for the same provider ID while a subscription is `active` or `past_due` **MUST** be rejected. Later-period billing occurs only through recurring renewal in the initial release. 2.5. The system **MUST** atomically perform initial activation: verify that the user's personal provider slot is unoccupied, debit sufficient Kilo Credits using a guarded balance operation, claim an available Managed Plan Credential, create the Installed BYOK Configuration, record the charged term, and create the active subscription. If any step fails, none of those effects **MUST** commit. @@ -94,7 +94,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S 4.9. Administrative upload tooling **MUST** prevent accidental duplicate credential assignment without exposing raw credential values in list responses, for example through a secure, non-reversible fingerprint comparison. -4.10. Before a MiniMax credential becomes `available` inventory, administrative upload tooling **MUST** validate that it can use the approved ordinary MiniMax routing and model behavior for Token Plan Plus. An invalid or incompatible credential **MUST NOT** become assignable inventory. +4.10. Before a MiniMax credential becomes `available` inventory, administrative upload tooling **MUST** validate that it can use the approved ordinary MiniMax routing and model behavior for the selected MiniMax token plan. An invalid or incompatible credential **MUST NOT** become assignable inventory. ## 5. Subscription lifecycle @@ -120,9 +120,9 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S ## 6. Traffic routing -6.1. Initial Token Plan Plus setup **MUST** route through the Kilo Gateway using the existing ordinary personal MiniMax BYOK provider identity. The initial release **MUST NOT** expose saved raw credential values through Kilo UI or API responses. +6.1. Initial MiniMax Coding Plan setup **MUST** route through the Kilo Gateway using the existing ordinary personal MiniMax BYOK provider identity. The initial release **MUST NOT** expose saved raw credential values through Kilo UI or API responses. -6.2. The system **MUST NOT** add a Token Plan Plus-specific provider or model-routing namespace. The Kilo-installed MiniMax key and any later subscriber replacement **MUST** use ordinary MiniMax BYOK routing and model availability. +6.2. The system **MUST NOT** add a MiniMax Coding Plan-specific provider or model-routing namespace. The Kilo-installed MiniMax key and any later subscriber replacement **MUST** use ordinary MiniMax BYOK routing and model availability. 6.3. Purchase **MUST** reject an occupied personal MiniMax BYOK slot before a charge or issued credential assignment commits. Once subscribed, a user's ordinary MiniMax BYOK actions affect routing configuration only; Coding Plan billing and revocation of Kilo's originally issued credential remain independent. @@ -132,7 +132,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S 7.2. Coding Plan surfaces **MUST** display recurring prices and charged-term amounts in USD regardless of payment source. Kilo Credits are valued one-to-one with USD for display. Surfaces **MUST** identify `Credits` as the payment source for credit-funded subscriptions and **MUST NOT** expose internal microdollars. -7.3. While an Installed BYOK Configuration is unchanged, the BYOK surface **MUST** identify it as configured by Token Plan Plus. Before updating, disabling, or deleting it, the surface **MUST** warn that routing changes do not cancel subscription billing and direct the user to Subscription Center to cancel. Saved raw-key view or copy controls **MUST NOT** be added for customer BYOK surfaces. +7.3. While an Installed BYOK Configuration is unchanged, the BYOK surface **MUST** identify it as configured by the MiniMax Coding Plan. Before updating, disabling, or deleting it, the surface **MUST** warn that routing changes do not cancel subscription billing and direct the user to Subscription Center to cancel. Saved raw-key view or copy controls **MUST NOT** be added for customer BYOK surfaces. 7.4. Purchase messaging **MUST** state that Kilo configures MiniMax in BYOK and **MUST** tell users with an existing MiniMax key to delete it before subscribing. Cancellation messaging **MUST** state when billing ends, that Kilo deletes only its unchanged installed configuration, and that Kilo revokes its issued credential when plan access ends. diff --git a/.specs/subscription-center.md b/.specs/subscription-center.md index 29ab69f9e8..be59a77bf7 100644 --- a/.specs/subscription-center.md +++ b/.specs/subscription-center.md @@ -25,6 +25,7 @@ Updated 2026-05-28 -- Credit-funded payment source label. Updated 2026-05-28 -- Coding Plans API key configuration summary. Updated 2026-05-28 -- Coding Plans billing history USD amount display. Updated 2026-06-05 -- KiloClaw final Commit term continuation behavior. +Updated 2026-06-26 -- MiniMax token plan tiers and provider-level Coding Plan exclusivity. ## Conventions @@ -270,10 +271,10 @@ historical Commit names, prices, invoices, and credit deductions. ### Coding Plans Subscriptions (Personal Route) -27. A user MAY have multiple Coding Plans subscriptions — one per - configured Plan ID. The Coding Plans group MUST display one - Subscription Card for each non-terminal coding plan subscription, - including a `past_due` subscription in its warning state. +27. A user MAY have multiple Coding Plans subscriptions -- one live + subscription per configured provider ID. The Coding Plans group MUST + display one Subscription Card for each non-terminal coding plan + subscription, including a `past_due` subscription in its warning state. 28. The Coding Plans detail page MUST be served at `/subscriptions/coding-plans/[subscriptionId]`. @@ -298,9 +299,9 @@ historical Commit names, prices, invoices, and credit deductions. (see Billing History rules) Before update, disable, or delete, `/byok` MUST warn that routing changes - do not cancel or pause Token Plan Plus billing and cancellation is managed - in Subscription Center; customer surfaces MUST NOT include saved raw-key - view or copy controls. + do not cancel or pause MiniMax Coding Plan billing and cancellation is + managed in Subscription Center; customer surfaces MUST NOT include saved + raw-key view or copy controls. 31. Coding Plan cancellation, installed MiniMax configuration cleanup, and issued-credential revocation MUST follow `.specs/coding-plans.md`. @@ -308,19 +309,24 @@ historical Commit names, prices, invoices, and credit deductions. only Kilo's unchanged installed configuration is removed, and that Kilo revokes its issued credential when plan access ends. -32. When the user views Coding Plans with no non-terminal subscription, - the system MUST show each configured offering with provider name, - plan name, recurring USD price, billing period, and payment source. - An offering with assignable credential capacity MUST show a subscribe - action. For MiniMax Token Plan Plus, purchase messaging MUST explain - automatic MiniMax BYOK setup and purchase MUST be blocked when any - personal MiniMax BYOK key exists, including a disabled key. In that - state, the system MUST direct the user to delete the existing key in - `/byok` first. An offering without assignable credential capacity MUST - display a sold-out state and a `Notify me when available` action. The - action MUST persist one notification intent per user and Plan ID without - charging credits or reserving inventory, and the surface MUST indicate - once that intent has been saved. +32. When the user views Coding Plans, the system MUST show each configured + offering with provider name, plan name, recurring USD price, billing + period, payment source, and catalog feature copy. MiniMax token offerings + MUST include Token Plan Plus, Token Plan Max, and Token Plan Ultra. An + offering with assignable credential capacity MUST show a subscribe action. + Purchase messaging for MiniMax token plans MUST explain automatic MiniMax + BYOK setup and purchase MUST be blocked when any personal MiniMax BYOK key + exists, including a disabled key. In that state, the system MUST direct + the user to delete the existing key in `/byok` first. Purchase MUST also + be blocked when the user already has any non-terminal MiniMax Coding Plan, + including a subscription pending cancellation. In that state, the system + MUST explain that the user must cancel the current plan and wait until + access ends before subscribing to another MiniMax Coding Plan. An offering + without assignable credential capacity MUST display a sold-out state and a + `Notify me when available` action. The action MUST persist one + notification intent per user and Plan ID without charging credits or + reserving inventory, and the surface MUST indicate once that intent has + been saved. ### Teams/Enterprise Seats Subscriptions (Org Route) diff --git a/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx b/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx index 87867a54c5..d1baeb41ad 100644 --- a/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx +++ b/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx @@ -27,13 +27,22 @@ import { TableHeader, TableRow, } from '@/components/ui/table'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Textarea } from '@/components/ui/textarea'; +import type { UserByokProviderId } from '@/lib/ai-gateway/providers/openrouter/inference-provider-id'; +import type { CodingPlanId } from '@/lib/coding-plans/pricing'; import { useTRPC } from '@/lib/trpc/utils'; -const PLAN_ID = 'minimax-token-plan-plus'; - type OperationsState = { + providerId: UserByokProviderId; + planId: CodingPlanId; entriesText: string; completeInventoryId: string | null; failureInventoryId: string | null; @@ -41,6 +50,8 @@ type OperationsState = { }; const INITIAL_OPERATIONS_STATE: OperationsState = { + providerId: 'minimax', + planId: 'minimax-token-plan-plus', entriesText: '', completeInventoryId: null, failureInventoryId: null, @@ -54,7 +65,16 @@ function updateOperationsState(state: OperationsState, update: Partial updateState({ providerId }); + const setPlanId = (planId: CodingPlanId) => updateState({ planId }); const setEntriesText = (entriesText: string) => updateState({ entriesText }); const setCompleteInventoryId = (completeInventoryId: string | null) => updateState({ completeInventoryId }); @@ -64,6 +84,7 @@ export function CodingPlansOperationsContent() { const countsQuery = useQuery(trpc.codingPlans.adminKeyInventory.queryOptions({})); const queueQuery = useQuery(trpc.codingPlans.adminRevocationQueue.queryOptions({})); + const catalogQuery = useQuery(trpc.codingPlans.catalog.queryOptions()); const refreshOperations = async () => { await Promise.all([countsQuery.refetch(), queueQuery.refetch()]); @@ -118,6 +139,21 @@ export function CodingPlansOperationsContent() { .filter(entry => entry.length > 0); const workItems = queueQuery.data ?? []; const inventoryCounts = countsQuery.data ?? []; + const catalog = catalogQuery.data ?? []; + const providerOptions = Array.from( + new Map( + catalog.map(plan => [ + plan.providerId, + { providerId: plan.providerId, providerName: plan.providerName }, + ]) + ).values() + ); + const selectedProviderId = providerOptions.some(option => option.providerId === providerId) + ? providerId + : (providerOptions[0]?.providerId ?? providerId); + const planOptions = catalog.filter(plan => plan.providerId === selectedProviderId); + const selectedPlan = planOptions.find(plan => plan.planId === planId) ?? planOptions[0] ?? null; + const selectedPlanId = selectedPlan?.planId ?? planId; const totalCredentialCount = inventoryCounts.reduce((total, item) => total + item.count, 0); const countCredentialsByStatus = (status: string) => inventoryCounts.reduce((total, item) => total + (item.status === status ? item.count : 0), 0); @@ -150,7 +186,7 @@ export function CodingPlansOperationsContent() {

Coding plans operations

- Manage validated Token Plan Plus inventory and manual MiniMax credential revocation. + Manage validated MiniMax Coding Plan inventory and manual credential revocation.