f5e7e966e3
- add migrations for owner/member workspace roles and application admins - centralize /admin access checks with DB-backed admin resolution - audit admin analytics/billing route access - update account/admin UI typing and env/docs for ADMIN_EMAILS fallback behavior
280 lines
7.1 KiB
TypeScript
280 lines
7.1 KiB
TypeScript
import type { AddonCode, BillingInterval, PlanCode } from './billing/plans.js';
|
|
import type { UsageAllowanceAvailability, UsageResource } from './billing/entitlements.js';
|
|
import type { BillingSyncStatus, BillingTimelineEventType } from './billing/lifecycle.js';
|
|
|
|
export type JobStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';
|
|
|
|
export interface AppUser {
|
|
id: string;
|
|
email: string;
|
|
displayName: string;
|
|
avatarUrl?: string | null;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface SessionUser extends AppUser {
|
|
sessionId: string;
|
|
}
|
|
|
|
export type WorkspaceType = 'personal' | 'company';
|
|
export type WorkspaceRole = 'owner' | 'member';
|
|
|
|
export interface AccountWorkspace {
|
|
id: string;
|
|
name: string;
|
|
workspaceType: WorkspaceType;
|
|
role: WorkspaceRole;
|
|
memberCount: number;
|
|
}
|
|
|
|
export interface AccountSummary {
|
|
totalSearchJobs: number;
|
|
totalDeepResearchBatches: number;
|
|
totalBusinesses: number;
|
|
}
|
|
|
|
export type AccountBillingStatus = 'not_configured' | 'inactive' | 'active' | 'past_due' | 'canceled';
|
|
|
|
export interface BillingUsageResourceSummary {
|
|
resource: UsageResource;
|
|
availability: UsageAllowanceAvailability;
|
|
included: number | null;
|
|
consumed: number;
|
|
remaining: number | null;
|
|
}
|
|
|
|
export interface BillingAddonBalanceSummary {
|
|
addonCode: AddonCode;
|
|
resource: UsageResource;
|
|
remainingQuantity: number;
|
|
expiresAt: string | null;
|
|
}
|
|
|
|
export interface BillingWebhookEventSummary {
|
|
id: string;
|
|
provider: 'stripe';
|
|
externalEventId: string;
|
|
eventType: string;
|
|
status: 'received' | 'processed' | 'failed' | 'ignored';
|
|
externalCustomerRef: string | null;
|
|
externalSubscriptionRef: string | null;
|
|
errorMessage: string | null;
|
|
receivedAt: string;
|
|
processedAt: string | null;
|
|
}
|
|
|
|
export interface BillingTimelineEventSummary {
|
|
id: string;
|
|
workspaceId: string;
|
|
billingAccountId: string | null;
|
|
eventType: BillingTimelineEventType;
|
|
source: 'stripe' | 'app' | 'system';
|
|
payloadJson: Record<string, unknown>;
|
|
externalEventId: string | null;
|
|
externalCustomerRef: string | null;
|
|
externalSubscriptionRef: string | null;
|
|
occurredAt: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface AccountBillingState {
|
|
status: AccountBillingStatus;
|
|
planCode: PlanCode | null;
|
|
billingInterval: BillingInterval | null;
|
|
currentPeriodStartsAt: string | null;
|
|
currentPeriodEndsAt: string | null;
|
|
cancelAtPeriodEnd: boolean;
|
|
canceledAt?: string | null;
|
|
trialEndsAt?: string | null;
|
|
gracePeriodEndsAt: string | null;
|
|
pendingPlanCode: PlanCode | null;
|
|
pendingPlanEffectiveAt: string | null;
|
|
billingSyncStatus: BillingSyncStatus;
|
|
lastStripeSyncAt: string | null;
|
|
provider: 'stripe' | null;
|
|
externalCustomerRef: string | null;
|
|
externalSubscriptionRef: string | null;
|
|
usage: BillingUsageResourceSummary[];
|
|
addonBalances: BillingAddonBalanceSummary[];
|
|
message: string;
|
|
}
|
|
|
|
export interface BillingCheckoutSessionResponse {
|
|
checkoutUrl: string;
|
|
}
|
|
|
|
export interface BillingPortalSessionResponse {
|
|
url: string;
|
|
}
|
|
|
|
export interface BillingDebugData {
|
|
events: BillingWebhookEventSummary[];
|
|
}
|
|
|
|
export interface BillingAdminWorkspaceSummary {
|
|
workspaceId: string;
|
|
workspaceName: string;
|
|
workspaceType: WorkspaceType;
|
|
memberCount: number;
|
|
status: AccountBillingStatus;
|
|
planCode: PlanCode | null;
|
|
billingInterval: BillingInterval | null;
|
|
currentPeriodEndsAt: string | null;
|
|
cancelAtPeriodEnd: boolean;
|
|
gracePeriodEndsAt: string | null;
|
|
pendingPlanCode: PlanCode | null;
|
|
pendingPlanEffectiveAt: string | null;
|
|
billingSyncStatus: BillingSyncStatus;
|
|
lastStripeSyncAt: string | null;
|
|
externalCustomerRef: string | null;
|
|
externalSubscriptionRef: string | null;
|
|
}
|
|
|
|
export interface BillingAdminWorkspaceDetail {
|
|
summary: BillingAdminWorkspaceSummary;
|
|
billing: AccountBillingState;
|
|
usagePeriodId: string | null;
|
|
timeline: BillingTimelineEventSummary[];
|
|
webhookEvents: BillingWebhookEventSummary[];
|
|
}
|
|
|
|
export interface BillingAdminWorkspaceListResponse {
|
|
workspaces: BillingAdminWorkspaceSummary[];
|
|
}
|
|
|
|
export interface BillingAdminWorkspaceDetailResponse {
|
|
workspace: BillingAdminWorkspaceDetail;
|
|
}
|
|
|
|
export interface AnalyticsMetricBucket {
|
|
key: string;
|
|
count: number;
|
|
}
|
|
|
|
export interface AdminAnalyticsSummary {
|
|
pricingConversionByPlan: AnalyticsMetricBucket[];
|
|
quotaExhaustionEvents: AnalyticsMetricBucket[];
|
|
upgradeTriggers: AnalyticsMetricBucket[];
|
|
addonAttach: AnalyticsMetricBucket[];
|
|
planMix: AnalyticsMetricBucket[];
|
|
churnSignals: AnalyticsMetricBucket[];
|
|
expansionSignals: AnalyticsMetricBucket[];
|
|
}
|
|
|
|
export interface AccountTeamPlaceholder {
|
|
canManageMembers: boolean;
|
|
message: string;
|
|
}
|
|
|
|
export interface AccountPageData {
|
|
profile: AppUser;
|
|
workspace: AccountWorkspace;
|
|
summary: AccountSummary;
|
|
billing: AccountBillingState;
|
|
team: AccountTeamPlaceholder;
|
|
isAdmin?: boolean;
|
|
isBillingAdmin?: boolean;
|
|
}
|
|
|
|
export interface UpdateAccountProfileRequest {
|
|
displayName?: string;
|
|
avatarUrl?: string | null;
|
|
workspaceName?: string;
|
|
}
|
|
|
|
export interface GeoJsonGeometry {
|
|
type: 'Polygon' | 'MultiPolygon';
|
|
coordinates: unknown;
|
|
}
|
|
|
|
export interface GeoJsonFeature<TProperties = Record<string, unknown>> {
|
|
type: 'Feature';
|
|
geometry: GeoJsonGeometry;
|
|
properties: TProperties;
|
|
}
|
|
|
|
export interface GeoJsonFeatureCollection<TProperties = Record<string, unknown>> {
|
|
type: 'FeatureCollection';
|
|
features: Array<GeoJsonFeature<TProperties>>;
|
|
}
|
|
|
|
export interface PostalAreaPreview {
|
|
id: string;
|
|
countryCode: string;
|
|
postalCode: string;
|
|
normalizedPostalCode: string;
|
|
displayName: string;
|
|
propagationRing: number;
|
|
centroidLat: number | null;
|
|
centroidLng: number | null;
|
|
}
|
|
|
|
export interface DeepResearchOverlayProperties {
|
|
postalAreaId: string;
|
|
countryCode: string;
|
|
postalCode: string;
|
|
displayName: string;
|
|
propagationRing: number;
|
|
}
|
|
|
|
export interface DeepResearchPreviewRequest {
|
|
lat: number;
|
|
lng: number;
|
|
propagation: number;
|
|
businessType: string;
|
|
keywords?: string;
|
|
}
|
|
|
|
export interface DeepResearchPreview {
|
|
baseArea: PostalAreaPreview;
|
|
areas: PostalAreaPreview[];
|
|
overlay: GeoJsonFeatureCollection<DeepResearchOverlayProperties>;
|
|
propagation: number;
|
|
countryCode: string;
|
|
totalAreas: number;
|
|
estimatedChildJobs: number;
|
|
businessType: string;
|
|
keywords?: string;
|
|
}
|
|
|
|
export interface DeepResearchChildJobSummary {
|
|
id: string;
|
|
name: string;
|
|
postalCode?: string;
|
|
status: JobStatus;
|
|
totalResults: number;
|
|
createdAt: string;
|
|
completedAt?: string;
|
|
}
|
|
|
|
export interface DeepResearchBatchSummary {
|
|
id: string;
|
|
userId: string;
|
|
pinLat: number;
|
|
pinLng: number;
|
|
basePostalCode?: string;
|
|
countryCode?: string;
|
|
propagation: number;
|
|
businessType: string;
|
|
keywords?: string;
|
|
status: JobStatus;
|
|
totalPostalAreas: number;
|
|
totalResults: number;
|
|
childJobCount: number;
|
|
completedJobCount: number;
|
|
failedJobCount: number;
|
|
startedAt?: string;
|
|
completedAt?: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface DeepResearchBatchDetail extends DeepResearchBatchSummary {
|
|
childJobs: DeepResearchChildJobSummary[];
|
|
jobIds: string[];
|
|
}
|
|
|
|
export interface CreateDeepResearchBatchRequest extends DeepResearchPreviewRequest {}
|