UNPKG

kestrel.markets

Version:

A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.

65 lines (58 loc) 3.5 kB
/** * kestrel.markets/protocol — OfferTerms, the commercial-terms VOCABULARY carried on * an Offer (PLAT-ADR-0028 slice A1, owner-approved protocol-first split 2026-07-15). * * SHAPES ONLY. This module states the closed set of ways an Offer may be priced — * one-shot, recurring, minimum-commitment, included-credits, committed-use-discount — * as pure nouns/enums. It carries NO semantics: no billing, proration, renewal-clock, * or credit-burn logic lives here. Recurring-Envelope SEMANTICS are explicitly OUT of * scope (platform M2). Like the rest of `src/protocol/**` this file imports NOTHING and * pulls in no runtime (asserted by tests/protocol.boundary.test.ts). */ /* ─────────────────────────────── offer terms ───────────────────────────────── */ /** * Billing/commitment cadence for recurring and minimum-commitment terms. A closed, * calendar-grained vocabulary; opaque to the protocol (no scheduling semantics here). */ export type BillingPeriod = "day" | "week" | "month" | "quarter" | "year"; /** Whether a recurring term rolls over on its own or requires a fresh acceptance. */ export type RenewalMode = "auto" | "manual"; /** * The commercial terms an Offer prices, discriminated on `kind` (same `kind` idiom as * {@link import("./index.ts").SettlementMethod}). Additive union — a `PaymentRequired` * may list several as plural alternatives (`offers[]`). No member carries execution * semantics; every amount is a bare settlement number (asset lives on the Offer). */ export type OfferTerms = /** A single up-front purchase; no recurring or committed terms. */ | { readonly kind: "one_shot" } /** A subscription billed each `term`, rolling over per `renewal`. */ | { readonly kind: "recurring"; readonly term: BillingPeriod; readonly renewal: RenewalMode } /** A floor the buyer commits to spend (`amount`) each `period`. */ | { readonly kind: "min_commit"; readonly amount: number; readonly period: BillingPeriod } /** A bundle of prepaid `amount` credits, void after `expiry` (ISO-8601). */ | { readonly kind: "included_credits"; readonly amount: number; readonly expiry: string } /** A discount (`discountBps`, basis points) for committing to spend `amount` each `period`. */ | { readonly kind: "committed_use_discount"; readonly amount: number; readonly period: BillingPeriod; readonly discountBps: number; }; /** The discriminant of every {@link OfferTerms} member. */ export type OfferTermsKind = OfferTerms["kind"]; /** * Runtime tuple of every {@link OfferTermsKind}. Same both-ways closed-vocabulary guard * as {@link import("./index.ts").SCOPES}: a `.kind` added to (or removed from) the union * without editing this tuple fails the `satisfies`/exhaustiveness check below at compile * time. The platform's OpenAPI conformance check reads these contents. */ export const OFFER_TERMS_KINDS = [ "one_shot", "recurring", "min_commit", "included_credits", "committed_use_discount", ] as const satisfies readonly OfferTermsKind[]; /** Reverse-exhaustiveness proof: any `OfferTermsKind` omitted from {@link OFFER_TERMS_KINDS} makes `_Missing`'s default non-`never`, which violates its `never` constraint and fails to compile. */ type _OfferTermsKindsExhaustive<_Missing extends never = Exclude<OfferTermsKind, (typeof OFFER_TERMS_KINDS)[number]>> = true;