| 109 | const MAX_TOKEN_LEN = 4096; |
| 110 | |
| 111 | function validateListRef(ref: unknown, pathLabel: string): { ref?: ListReference; error?: TaskError } { |
| 112 | if (ref === undefined || ref === null) return {}; |
| 113 | if (typeof ref !== 'object' || Array.isArray(ref)) { |
| 114 | return { error: { code: 'VALIDATION_ERROR', message: `${pathLabel}: must be an object with agent_url and list_id`, field: pathLabel } }; |
| 115 | } |
| 116 | const r = ref as Record<string, unknown>; |
| 117 | const agent_url = r.agent_url; |
| 118 | const list_id = r.list_id; |
| 119 | const auth_token = r.auth_token; |
| 120 | if (typeof agent_url !== 'string' || agent_url.length === 0 || agent_url.length > MAX_URL_LEN) { |
| 121 | return { error: { code: 'VALIDATION_ERROR', message: `${pathLabel}.agent_url: must be a non-empty string up to ${MAX_URL_LEN} chars`, field: `${pathLabel}.agent_url` } }; |
| 122 | } |
| 123 | if (!/^https?:\/\//i.test(agent_url)) { |
| 124 | return { error: { code: 'VALIDATION_ERROR', message: `${pathLabel}.agent_url: must use http:// or https://`, field: `${pathLabel}.agent_url` } }; |
| 125 | } |
| 126 | if (typeof list_id !== 'string' || list_id.length === 0 || list_id.length > MAX_ID_LEN) { |
| 127 | return { error: { code: 'VALIDATION_ERROR', message: `${pathLabel}.list_id: must be a non-empty string up to ${MAX_ID_LEN} chars`, field: `${pathLabel}.list_id` } }; |
| 128 | } |
| 129 | if (auth_token !== undefined && (typeof auth_token !== 'string' || auth_token.length > MAX_TOKEN_LEN)) { |
| 130 | return { error: { code: 'VALIDATION_ERROR', message: `${pathLabel}.auth_token: must be a string up to ${MAX_TOKEN_LEN} chars`, field: `${pathLabel}.auth_token` } }; |
| 131 | } |
| 132 | return { ref: { agent_url, list_id, ...(typeof auth_token === 'string' && { auth_token }) } }; |
| 133 | } |
| 134 | |
| 135 | function validateTargeting(t: unknown, pathLabel: string): { targeting?: PackageTargeting; errors: TaskError[] } { |
| 136 | if (t === undefined || t === null) return { errors: [] }; |