export const DEFAULT_PARTY_BUFF_POLICY = Object.freeze({ schemaVersion: 1, rules: Object.freeze([]) }); export function normalizePartyBuffPolicy(value) { if (!value || typeof value !== "object" || Array.isArray(value) || value.schemaVersion !== 1 || !Array.isArray(value.rules) || value.rules.length > 500) { throw new Error("Party buff policy must have schemaVersion 1 and at most 500 rules."); } const seen = new Set(); const rules = value.rules.map((rule, index) => { if (!rule || typeof rule !== "object" || Array.isArray(rule) || typeof rule.abilityId !== "string" || !/^[a-z0-9][a-z0-9:._-]{0,127}$/i.test(rule.abilityId) || !["party", "tank", "healer"].includes(rule.scope)) { throw new Error(`Party buff rule ${index} must have a valid abilityId and scope.`); } if (seen.has(rule.abilityId)) throw new Error(`Duplicate party buff rule: ${rule.abilityId}.`); seen.add(rule.abilityId); return { abilityId: rule.abilityId, scope: rule.scope }; }); return { schemaVersion: 1, rules }; }