scooling-external-ref.mjs
sha256:700fafdd1afa490919f9515d660ca6e75456bcd5bb67513abcd8757a634c01f6
docs: record AIP-b SD-21 land (KN #308)
Human
10 days ago
| 1 | /** |
| 2 | * Scooling propose-time external_ref validation (FINISH-COMPLETE-APPLY §FCA.4 + |
| 3 | * FLOW-WRITE-LIVE §FWL.4.1). Kept separate from hub-proposal-personal-self-apply |
| 4 | * to avoid import cycles with task-write / attachment-write / flow-authoring |
| 5 | * (which those modules import for SOURCE constants). |
| 6 | */ |
| 7 | |
| 8 | /** @type {RegExp} */ |
| 9 | export const SCOOLING_TASK_EXTERNAL_REF_RE = /^scooling\.task:[A-Za-z0-9._:-]{1,200}$/; |
| 10 | |
| 11 | /** @type {RegExp} */ |
| 12 | export const SCOOLING_MEDIA_EXTERNAL_REF_RE = /^scooling\.media:[A-Za-z0-9._:-]{1,200}$/; |
| 13 | |
| 14 | /** FLOW-WRITE-LIVE §FWL.4.1 — Flow authoring admission ref (max 128 after prefix). */ |
| 15 | /** @type {RegExp} */ |
| 16 | export const SCOOLING_FLOW_EXTERNAL_REF_RE = /^scooling\.flow:[A-Za-z0-9._:-]{1,128}$/; |
| 17 | |
| 18 | /** |
| 19 | * Validate optional Scooling external_ref on propose (absent → ok/undefined; malformed → 400). |
| 20 | * @param {unknown} raw |
| 21 | * @param {RegExp} expectedRe |
| 22 | * @returns {{ ok: true, externalRef: string|undefined } | { ok: false, status: number, code: string, error: string }} |
| 23 | */ |
| 24 | export function resolveOptionalScoolingExternalRef(raw, expectedRe) { |
| 25 | if (raw == null) return { ok: true, externalRef: undefined }; |
| 26 | const s = String(raw).trim(); |
| 27 | if (!s) return { ok: true, externalRef: undefined }; |
| 28 | if (!expectedRe.test(s)) { |
| 29 | return { |
| 30 | ok: false, |
| 31 | status: 400, |
| 32 | code: 'EXTERNAL_REF_INVALID', |
| 33 | error: 'external_ref does not match the required Scooling pattern', |
| 34 | }; |
| 35 | } |
| 36 | return { ok: true, externalRef: s }; |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * Read optional external_ref from propose input / body. |
| 41 | * @param {object} input |
| 42 | * @returns {unknown} |
| 43 | */ |
| 44 | export function readProposeExternalRefRaw(input) { |
| 45 | if (!input || typeof input !== 'object') return undefined; |
| 46 | if (typeof input.externalRef === 'string') return input.externalRef; |
| 47 | if (typeof input.external_ref === 'string') return input.external_ref; |
| 48 | const body = input.body && typeof input.body === 'object' ? input.body : null; |
| 49 | if (body && typeof body.external_ref === 'string') return body.external_ref; |
| 50 | return undefined; |
| 51 | } |
File History
1 commit
sha256:700fafdd1afa490919f9515d660ca6e75456bcd5bb67513abcd8757a634c01f6
docs: record AIP-b SD-21 land (KN #308)
Human
10 days ago