Files
cfw-autumn/shared/models/cusProductModels/cusEntModels/usageWindowModels.ts
2026-06-11 15:28:59 +01:00

54 lines
2.2 KiB
TypeScript

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<typeof UsageWindowDimensionSchema>;
/** Whether the window is tracked per-customer (aggregate) or per-entity. */
export const UsageWindowScopeSchema = z.enum(["customer", "entity"]);
export type UsageWindowScope = z.infer<typeof UsageWindowScopeSchema>;
/**
* 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(),
internal_feature_id: z.string(),
internal_customer_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(),
// Bounds/interval provenance: the entitlement whose reset interval and
// billing-cycle anchor shaped this window. Stamped onto the counter row at
// creation; storage no longer depends on it, so null just means calendar
// bounds with no provenance.
anchor_customer_entitlement_id: z.string().nullable(),
// Candidate row id (ksuid) minted server-side per request. Lua uses it ONLY
// when this request creates the counter row; lookups match the logical key
// (window_start_at + entity), never the id.
new_window_id: z.string().optional(),
});
export type UsageWindowLimit = z.infer<typeof UsageWindowLimitSchema>;