import { z } from 'zod' import { Curve96, DecimalString, Id, IsoUtc, MarketDate, Timescale } from './common.js' import { ApprovalLevel } from './approval.js' import { ProposalType } from './proposal.js' /** * Authority envelope (授权包络, downward): human-pre-approved autonomy bounds. * Bound keys are type-specific and documented in docs/03 §3; initial values are * OPEN-QUESTION B1/B2 — never hardcode them. */ export const Envelope = z.object({ id: Id, scope: z.object({ proposal_type: ProposalType, timescales: z.array(Timescale).min(1), resource_set: Id, }), bounds: z.record(z.string(), DecimalString), validity: z.object({ from: IsoUtc, to: IsoUtc }), approval: z.object({ level: ApprovalLevel, approved_by: z.array(Id).min(1) }), escalation: z.object({ max_consecutive_deviations: z.int().positive(), deviation_threshold_pct: DecimalString, }), status: z.enum(['ACTIVE', 'SUSPENDED', 'EXPIRED']), }) export type Envelope = z.infer /** * Capability envelope (灵活性包络, upward): adjustable capacity report from an * aggregation unit — the same schema crosses the federation boundary in * phase 2 (docs/10 §5, no-rework reservation #1). */ export const FlexibilityEnvelope = z.object({ id: Id, provider: z.object({ unit_id: Id, level: z.enum(['SITE', 'AGGREGATION_UNIT', 'PROVINCE']), }), market_date: MarketDate, up_mw: Curve96, down_mw: Curve96, valid_until: IsoUtc, schema_version: z.string().min(1), /** Signing arrives with federation (phase 2); null within-province. */ signature: z.string().nullable(), }) export type FlexibilityEnvelope = z.infer