{"record":{"id":"65904d93d3f1a9eb","repo":"santifer/career-ops","slug":"torre-url-must-use-https-url","errorCode":null,"errorMessage":"torre: URL must use HTTPS: ${url}","messagePattern":"torre: URL must use HTTPS: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/torre.mjs","lineNumber":92,"sourceCode":"// same result set, so the default is arbitrary among them.\nconst EXPERIENCE_LEVELS = new Set([\n  'potential-to-develop',\n  '1-plus-year',\n  '2-plus-years',\n  '3-plus-years',\n  '5-plus-years',\n]);\nconst DEFAULT_EXPERIENCE = '1-plus-year';\n\n/** @param {string} url */\nfunction assertTorreUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`torre: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`torre: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_API_HOST) {\n    throw new Error(`torre: untrusted hostname \"${parsed.hostname}\" — must be ${TRUSTED_API_HOST}`);\n  }\n  return url;\n}\n\n/**\n * Build the search body from the portal entry. Only filters proven to affect\n * `total` are emitted — see the header note. Exported for tests.\n *\n * @param {any} entry\n * @returns {object}\n */\nexport function buildTorreQuery(entry) {\n  /** @type {Record<string, unknown>} */\n  const body = {};\n\n  const search = typeof entry?.search === 'string' ? entry.search.trim() : '';","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/providers/torre.mjs#L74-L110","documentation":"assertTorreUrl requires the https: protocol for every URL it validates; this error is thrown for syntactically valid URLs using another scheme (http:, ftp:, etc.). Enforcing HTTPS prevents credentials/job payloads from being sent in cleartext and blocks downgrade tricks before any fetch happens.","triggerScenarios":"Calling assertTorreUrl with 'http://torre.ai/...' or another non-HTTPS scheme — typically a config entry written with http://, an internal proxy URL, or a URL harvested from a page that linked insecurely.","commonSituations":"Legacy bookmarks using http://; local/staging test URLs (http://localhost:3000); a reverse-proxy config with TLS terminated upstream; copy-pasting from an old document.","solutions":["Change the URL scheme to https:// (confirm the target actually serves TLS).","If it's an internal test endpoint, use a test seam/mocking rather than pointing the provider at non-HTTPS URLs.","If the target host genuinely has no HTTPS, it is not a valid Torre API endpoint — find the official HTTPS endpoint."],"exampleFix":"// before\nassertTorreUrl('http://torre.ai/api/search');\n// Error: torre: URL must use HTTPS: http://torre.ai/api/search\n// after\nassertTorreUrl('https://torre.ai/api/search');","handlingStrategy":"validation","validationCode":"function isHttpsUrl(url) {\n  try { return new URL(url).protocol === 'https:'; } catch { return false; }\n}\nif (!isHttpsUrl(url)) url = url.replace(/^http:/, 'https:');","typeGuard":"function isHttps(v) {\n  if (typeof v !== 'string') return false;\n  try { return new URL(v).protocol === 'https:'; } catch { return false; }\n}","tryCatchPattern":"try {\n  assertTorreUrl(url);\n} catch (err) {\n  if (String(err.message).startsWith('torre: URL must use HTTPS')) {\n    console.error('Upgrade the configured endpoint to https://');\n  } else throw err;\n}","preventionTips":["Never configure http:// endpoints for job feeds; terminate TLS properly in staging too.","Audit portal configs for scheme typos (htp://, http:// on API hosts).","Use mock/seam testing instead of pointing the provider at localhost over http.","Adopt a linter/checker on config files that flags non-HTTPS URLs."],"tags":["url-validation","https","security","config"],"backgroundTag":"insecure-scheme-rejected","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}