atris 3.80.0 → 3.80.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -446,7 +446,11 @@ function renderAuditLanding({ dir, meta, records }) {
446
446
  const L = ['', ` ◉ sentinel security audit · ${meta.profile}${meta.scope_paths.length ? ` · ${meta.scope_paths.join(', ')}` : ''}`, ''];
447
447
  if (meta.incomplete_reason === 'plan_only') {
448
448
  L.push(` plan only: ${cov.in_scope} areas to review, no engines called`);
449
- L.push(` a ${meta.profile} run with budget ${meta.budget} sends ${meta.plan.hunters} hunters (${meta.plan.units_per_hunter} area${meta.plan.units_per_hunter === 1 ? '' : 's'} each) and keeps ${meta.plan.verifyReserve} checks for verifying`);
449
+ const { hunters, hunters_needed: needed, units_per_hunter: per, verifyReserve } = meta.plan;
450
+ const sending = Math.min(hunters, needed);
451
+ L.push(` a ${meta.profile} run with budget ${meta.budget} sends about ${sending} hunter${sending === 1 ? '' : 's'} (up to ${per} area${per === 1 ? '' : 's'} each) and keeps ${verifyReserve} checks for verifying`);
452
+ if (hunters < 1) L.push(' this budget is too small to send a hunter; try --budget 8 or more');
453
+ else L.push(needed <= hunters ? ' one run can read every area' : ` about ${Math.ceil(needed / hunters)} runs to read every area`);
450
454
  } else {
451
455
  L.push(` ${confirmed.length} confirmed${sevText ? ` (${sevText})` : ''} · ${needs.length} need a fact from you · ${rejected.length} disproved`);
452
456
  L.push(` read ${cov.fresh} areas this run, ${cov.carried} carried unchanged, ${cov.deferred || 0} left for the next run`);
@@ -113,13 +113,17 @@ function validateSlug(slug) {
113
113
  return null;
114
114
  }
115
115
 
116
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
117
+
116
118
  function validateApiBase(value) {
117
119
  try {
118
120
  const parsed = new URL(value);
119
121
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') throw new Error('bad protocol');
122
+ // The login token rides on every request, so plain http is only for this machine.
123
+ if (parsed.protocol === 'http:' && !LOOPBACK_HOSTS.has(parsed.hostname)) throw new Error('bad protocol');
120
124
  return parsed.toString().replace(/\/$/, '');
121
125
  } catch {
122
- throw new Error('--api-base must be a valid http or https url');
126
+ throw new Error('--api-base must be an https url (http only for localhost, 127.0.0.1, or [::1])');
123
127
  }
124
128
  }
125
129