import { z } from "zod/v4"; import { EntInterval } from "../../productModels/intervals/entitlementInterval.js"; /** * Which dimension a usage window counts against: * - `balance`: the credit pool / balance itself (e.g. "max 3 credits/day") * - `metered_feature`: a member feature within a credit system * (e.g. "max 5 workflows", independent of credits remaining) */ export const UsageWindowDimensionSchema = z.enum([ "balance", "metered_feature", ]); export type UsageWindowDimension = z.infer; /** Whether the window is tracked per-customer (aggregate) or per-entity. */ export const UsageWindowScopeSchema = z.enum(["customer", "entity"]); export type UsageWindowScope = z.infer; /** * A resolved, enforceable usage-window limit: the runtime input handed to the * deduction script. Built each deduction from the windowed usage cap * (`usage_limit` + optional `usage_limit_interval` override) on a `spend_limit` billing * control plus the current window bounds (NOT stored). * Carries the resolved `limit` and `key`/window so Lua can find-or-create the * matching counter. */ export const UsageWindowLimitSchema = z.object({ feature_id: z.string(), key: z.string(), dimension_type: UsageWindowDimensionSchema, dimension_feature_id: z.string().nullable(), scope_type: UsageWindowScopeSchema, entity_id: z.string().nullable(), internal_entity_id: z.string().nullable(), interval: z.enum(EntInterval), window_start_at: z.number(), window_end_at: z.number(), limit: z.number(), // The single entitlement that owns this counter, resolved in TS so it is // deduction-order-independent. Null when no eligible owner exists (e.g. a // customer-scope cap with only entity-scoped entitlements) -> enforcement // must fail closed rather than split or silently allow. anchor_customer_entitlement_id: z.string().nullable(), anchor_feature_id: z.string().nullable(), }); export type UsageWindowLimit = z.infer;