vpp-ai-platform/packages/domain/src/envelope.ts

49 lines
1.7 KiB
TypeScript
Raw Normal View History

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<typeof Envelope>
/**
* 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<typeof FlexibilityEnvelope>