{"record":{"id":"3a3eb400836c04a9","repo":"santifer/career-ops","slug":"glints-url-must-use-https-url","errorCode":null,"errorMessage":"glints: URL must use HTTPS: ${url}","messagePattern":"glints: URL must use HTTPS: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/glints.mjs","lineNumber":77,"sourceCode":"        minAmount\n        CurrencyCode\n      }\n      createdAt\n    }\n    expInfo\n    hasMore\n  }\n}`;\n\n/** @param {string} url */\nfunction assertGlintsUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`glints: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`glints: URL must use HTTPS: ${url}`);\n  if (!ALLOWED_GLINTS_HOSTS.has(parsed.hostname))\n    throw new Error(`glints: untrusted hostname \"${parsed.hostname}\" — must be one of: ${[...ALLOWED_GLINTS_HOSTS].join(', ')}`);\n  return url;\n}\n\n// NaN-safe Date.parse\nfunction toEpochMs(value) {\n  if (!value) return undefined;\n  const parsed = Date.parse(value);\n  return Number.isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * Derive the job detail base URL from the API hostname.\n * @param {string} apiUrl\n * @returns {string}\n */\nfunction deriveBaseUrl(apiUrl) {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/glints.mjs#L59-L95","documentation":"glints.mjs throws this in assertGlintsUrl() after the URL parses but its protocol is not 'https:'. It enforces TLS for the Glints GraphQL endpoint. Because Glints validates the operator-supplied entry.api (defaulting to DEFAULT_API), a live throw typically comes from an api: value using http:// in portals.yml.","triggerScenarios":"entry.api is set to an http:// URL (e.g. for local proxying); a test calls assertGlintsUrl('http://glints.com/...'); a stale config predates the HTTPS-only guard.","commonSituations":"Local debugging through a non-TLS intercepting proxy; a copy-paste of an old http doc link; an env override downgraded the scheme.","solutions":["Set api to its https:// form or remove the field to use the shipped default.","For local interception, trust a proxy CA against the HTTPS endpoint instead of downgrading to http.","Remove tests that pass http URLs unless they assert this specific throw."],"exampleFix":"# before\n- name: Glints (ID)\n  provider: glints\n  api: http://glints.com/api/v2-alc/graphql\n\n# after\n- name: Glints (ID)\n  provider: glints\n  api: https://glints.com/api/v2-alc/graphql","handlingStrategy":"validation","validationCode":"// Reject non-HTTPS Glints api values before they reach the provider.\nfunction glintsApiIsHttps(entry) {\n  const api = entry.api || 'https://glints.com/api/v2-alc/graphql';\n  try { return new URL(api).protocol === 'https:'; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never set api to http://; use a trusted proxy CA against the HTTPS endpoint for local interception.","Add a lint rule forbidding http: in any provider api: field.","Document the HTTPS-only policy for Glints in portals.yml comments."],"tags":["url-validation","tls","glints","config","portals-yml"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}