feat: add local auth billing and usage management

This commit is contained in:
inman committed 2026-08-12 12:13:06 +08:00
1 parent f642b5e71f
commit 196fdde83f
119 files changed
+15695 -2650

No files matched your search

+223 -5
View File
@@ -1,7 +1,5 @@
export type ImageCapability =
| "image.generate"
| "image.inpaint"
| "image.upscale";
| "image.generate";
export type EnabledImageCapability = ImageCapability;
@@ -9,6 +7,214 @@ export type VideoCapability = "video.generate";
export type GenerationCapability = ImageCapability | VideoCapability;
export type GenerationProvider =
| "volcengine-visual"
| "evolink"
| "seedance"
| "bailian"
| "mock";
export type BillingCurrency = "CNY";
export type BillingUnit = "request" | "image" | "video_second";
export type BillingPriceSource = {
url: string;
currency: "CNY" | "USD";
unitPrice: number;
fxRate?: number;
basis?: string;
observedAt?: string;
};
export type BillingScalar = string | number | boolean;
export type BillingConditionValue =
| BillingScalar
| {
min?: number;
max?: number;
values?: BillingScalar[];
};
export type BillingRuleConditions = Record<string, BillingConditionValue>;
export type BillingQuantitySource = "request" | "image_count" | "duration";
export type BillingParameterSnapshot = Record<string, BillingScalar>;
export type BillingParameterTier = {
value: BillingScalar;
label: string;
standardFactor: number;
markupMultiplier: number;
enabled: boolean;
match?: BillingConditionValue;
note?: string;
};
export type BillingParameterDimension = {
key: string;
label: string;
baselineValue: BillingScalar;
defaultValue?: BillingScalar;
tiers: BillingParameterTier[];
};
export type BillingSelectedParameterTier = BillingParameterTier & {
dimensionKey: string;
dimensionLabel: string;
actualValue: BillingScalar;
standardUnitPriceFen: number;
};
export type BillingPriceRule = {
id: string;
provider: GenerationProvider;
capability: GenerationCapability;
reqKey?: string;
variantKey?: string;
unit: BillingUnit;
standardUnitPriceFen: number;
markupMultiplier: number;
enabled: boolean;
conditions?: BillingRuleConditions;
quantitySource?: BillingQuantitySource;
priority?: number;
note?: string;
source?: BillingPriceSource;
parameterDimensions?: BillingParameterDimension[];
createdAt: string;
updatedAt: string;
};
export type BillingQuote = {
priceRuleId: string;
provider: GenerationProvider;
capability: GenerationCapability;
reqKey: string;
variantKey?: string;
unit: BillingUnit;
quantity: number;
standardUnitPriceFen: number;
markupMultiplier: number;
amountFen: number;
currency: BillingCurrency;
conditions?: BillingRuleConditions;
quantitySource?: BillingQuantitySource;
parameters?: BillingParameterSnapshot;
baseStandardUnitPriceFen?: number;
parameterTiers?: BillingSelectedParameterTier[];
source?: BillingPriceSource;
quotaExempt?: boolean;
};
export type BillingJobCharge = BillingQuote & {
status: "not_charged" | "pending" | "charged" | "refunded";
reservedAmountFen?: number;
settlementStatus?: "pending" | "settled" | "estimated";
settlementLedgerEntryId?: string;
settledAt?: string;
settlementReason?: string;
providerUsage?: {
completionTokens: number;
resolution: string;
inputVideo: boolean;
tokenPriceFenPerMillion: number;
};
ledgerEntryId?: string;
refundLedgerEntryId?: string;
chargedAt?: string;
refundedAt?: string;
refundReason?: string;
};
export type OrganizationWallet = {
organizationId: string;
balanceFen: number;
totalRechargedFen: number;
totalChargedFen: number;
updatedAt: string;
};
export type BillingLedgerKind = "recharge" | "charge" | "refund" | "adjustment";
export type BillingLedgerEntry = {
id: string;
organizationId: string;
accountId?: string;
jobId?: string;
kind: BillingLedgerKind;
deltaFen: number;
balanceAfterFen: number;
currency: BillingCurrency;
idempotencyKey: string;
description: string;
metadata: Record<string, unknown>;
createdAt: string;
};
export type BillingAccountConfig = {
accountName?: string;
bankName?: string;
accountNumber?: string;
contact?: string;
};
export type UsageSource = "platform" | "api";
export type PlatformRole = "super_admin" | "organization_admin" | "user";
export type AccountStatus = "active" | "disabled";
export type OrganizationStatus = "active" | "disabled";
export type PlatformOrganization = {
id: string;
name: string;
status: OrganizationStatus;
archiveOwnerId: string;
createdAt: string;
updatedAt: string;
};
export type PlatformUserRecord = {
id: string;
phone: string;
displayName: string;
role: PlatformRole;
organizationId?: string;
status: AccountStatus;
passwordHash: string;
passwordSalt: string;
failedLoginCount: number;
lockedUntil?: string;
sessionVersion: number;
lastLoginAt?: string;
legacySubject?: string;
createdAt: string;
updatedAt: string;
};
export type AccountMigration = {
id: string;
legacyOwnerId: string;
legacyPhone?: string;
platformUserId: string;
createdAt: string;
};
export type UsageContext = {
source: UsageSource;
accountId: string;
username?: string;
displayName: string;
role?: PlatformRole;
tenantId?: string;
organizationId?: string;
organizationName?: string;
};
export type AssetKind = "image" | "video" | "mask" | "reference" | "other";
export type GenerationStatus =
@@ -46,7 +252,7 @@ export type GenerationJob = {
ownerId: string;
externalClientId?: string;
capability: GenerationCapability;
provider: "volcengine-visual" | "evolink" | "seedance" | "bailian" | "mock";
provider: GenerationProvider;
reqKey: string;
status: GenerationStatus;
prompt?: string;
@@ -75,6 +281,8 @@ export type GenerationJob = {
webhookUrl?: string;
webhookAttempts?: number;
webhookLastStatus?: WebhookLastStatus;
usageContext?: UsageContext;
billing?: BillingJobCharge;
createdAt: string;
updatedAt: string;
};
@@ -83,9 +291,19 @@ export type UsageEvent = {
id: string;
ownerId: string;
jobId: string;
source?: UsageSource;
capability: GenerationCapability;
provider?: GenerationProvider;
reqKey?: string;
accountUsername?: string;
accountDisplayName?: string;
tenantId?: string;
organizationId?: string;
organizationName?: string;
quantity: number;
estimatedUnit: "image" | "job";
estimatedUnit: "image" | "job" | "video_second";
chargedAmountFen?: number;
currency?: BillingCurrency;
createdAt: string;
};