* feat(arsenal): add subdomain-takeover classifier + fingerprint table
Pure, I/O-free detection logic split into src/arsenal/takeover.ts so it is fully
unit-testable without DNS or network:
- TAKEOVER_FINGERPRINTS: curated CNAME + unclaimed-resource-body signatures for 15
high-frequency services (S3, GitHub Pages, Heroku, Azure, Fastly, Shopify, Netlify, ...)
- classifySubdomainTakeover(): conservative verdict (confirmed / potential / none) driven by
a dangling CNAME and/or a service body fingerprint; no cross-service false matches
- renderTakeoverReport(): human-readable output block
* feat(arsenal): register subdomain_takeover_check built-in + bump tool count 108->109
- New keyless, self-contained built-in tool 'subdomain_takeover_check' (recon): resolves the
CNAME, checks whether the target still resolves (dangling), fetches the live body via the
scope-gated targetFetch, and classifies via classifySubdomainTakeover. Emits a real finding.
- Added to the Recon operator's default toolkit so the swarm can reach it (operator-toolkits
coverage invariant).
- Bumped the advertised arsenal size 108 -> 109 in lockstep across the count-honesty test,
README, and verify-claims (73 adapters + 36 built-in).
* test(arsenal): cover subdomain_takeover_check (classifier matrix + mocked DNS/fetch e2e)
- classifySubdomainTakeover decision matrix: confirmed via body fingerprint, confirmed via
dangling nxdomain-prone CNAME, potential (known service, no confirmation), potential
(dangling unknown), none (no CNAME / resolves clean), and no cross-service false matching
- renderTakeoverReport output shape
- end-to-end handler test with DNS + fetch mocked, driving the confirmed S3 path
* feat(llm): add Hugging Face provider + selectable local Claude Code models
Adds two operator-selectable LLM backbones, wired through both the backend
and the War Room UI.
Hugging Face (OpenAI-compatible Inference Providers router):
- New `huggingface` provider reusing OpenAIAdapter (router.huggingface.co/v1)
- HF_TOKEN / HUGGINGFACE_API_KEY / HUGGINGFACE_TOKEN env resolution, config,
setup wizard, CLI, factory, best-available, and .env.example
- Settings key card + 4 inference models in the picker + direct client routing
- Tests: src/__tests__/huggingface-provider.test.ts
Local Claude from Claude Code:
- Explicit "active backbone" pin in Settings so a connected agent (Claude Code)
can be chosen; a pin outranks stored API keys in both the client resolver and
mission dispatch
- Claude Code model picker (Account default / Opus / Sonnet / Haiku), threaded
to the CLI's --model via an "agentId::model" encoding parsed by LocalAgentAdapter;
requireLiveLocalAgent strips the suffix for connected-agent validation
* fix(llm): address PR #127 review — self-contained keyless path + centralized pin/model routing
Finding 1 — keyless mission path was not self-contained:
- Add the `local-agent` case to ConfigManager.getLLMConfig so provider:'local-agent'
resolves (keyless, agent id — optionally "agentId::model" — in `model`) instead of
hitting the default "Unknown provider" throw.
Finding 2 — inconsistent pin/model routing across dispatch surfaces:
- Centralize backend agent resolution in window.t3mpDispatchAgent (single source of truth).
It honors an explicit pin OVER a stored API key and encodes the picked local model as
"agentId::model" so it is never dropped.
- Route all three surfaces through it: mission dispatch, General (getGeneralConfig), and
Admiral (_admBackbone). Previously General/Admiral only picked an agent when no key
existed and sent the bare agent id, so a stored key overrode the pin and the selected
Claude model was lost.
Tests:
- getLLMConfig('local-agent') regression coverage (self-contained keyless path)
- LocalAgentAdapter "agentId::model" passthrough reaches the CLI --model flag
- t3mpDispatchAgent behavior: pin>key precedence, model encoding, fallbacks (evaluated
from the shipped docs/index.html)
- centralization invariant: mission/General/Admiral all route through t3mpDispatchAgent
- update the Op-Admiral keyless-routing static test to the centralized resolver
---------
Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>