Commit Graph
44 Commits
Author SHA1 Message Date
2alfandJoseph Magly 8ccea7c82a feat(llm): add Hugging Face provider + selectable local Claude Code models (#127)
* 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>
2026-07-27 15:47:06 -04:00
lyubomir-bozhinov 58f35276c5 fix(ui): repair botched-merge syntax errors that break app boot (#111)
docs/index.html is a single classic <script>. Eight scars from bad
auto-merges (duplicated old/new versions of the same LLM-call sites left
side by side) made the script fail to PARSE, so nothing ran: the UI stuck
on "Initializing…", every link/handler dead, only the pre-registered
selfimprove/ledger poller still firing.

A parse error surfaces one at a time (the engine stops at the first), so
these were only visible once each prior one was fixed. Repaired:

- _safeLLMCallOnce: duplicate `response` decl + a leftover pre-refactor
  fetch; restored backend-aware endpoint/headers (OpenRouter + Venice,
  backend.key) and kept the cancellable AbortController.
- runLLMJudge: two function bodies concatenated (one nested, never closed).
- safeLLMCall: the whole function duplicated (old truncated head + new
  loop that referenced an undefined `backend`); reunified into one
  function with backend resolution, agent/server routing, model chain and
  the fallback loop.
- runBenchmarks / autoApplyRecommendations: old "ANY LLM backend"
  guard left un-closed before the new "reachable (key or local mode)"
  guard — dropped the dead old guard / restored the missing brace.
- generateAnalysis auto-apply button, config-optimizer, self-improve and
  CTF call sites: duplicated option objects / double catch collapsed to
  the newer (_noFallback / cancellable) variant.

Verified on macOS: new regression test compiles every classic inline
<script> with node:vm (the RED baseline failed with "Identifier response
has already been declared"); full suite 646 green; headless-Chromium boot
now reaches "Connected", navigateTo is defined, zero uncaught errors.
2026-07-21 12:38:25 +03:00
Joseph Magly 937c6e9837 add reproducible cross-model benchmark matrix (#107) 2026-07-20 14:52:32 -04:00
Joseph Magly 58193d688d fix Op Admiral local-agent and approval flow (#106) 2026-07-20 14:30:45 -04:00
Joseph Magly 0c35a833b9 docs: add usage and developer documentation
Add user and developer documentation plus Pagenary docsite publishing support.

Includes Getting Started, Developer Guide, API and MCP references, Pagenary tenant metadata, npm scripts for sync/build/check/serve, and validation coverage for the generated docsite.

Closes #102
2026-07-20 12:59:53 -04:00
SiNaPsEr0x 7b1d12a07c feat: SOCKS5 egress proxy + harden local-model path (#79)
Integrate SOCKS5 attack-traffic proxying, egress leak visibility, and local-model hardening. Preserve direct local/LAN model traffic while the proxy is active and reconcile the branch with current upstream.
2026-07-20 11:54:29 -04:00
Lyubomir BozhinovandJoseph Magly 151d3555c6 feat(ingest): multi-language white-box ingest (web-tree-sitter) (#75)
* chore(ingest): pin web-tree-sitter@0.25.10 + tree-sitter-wasms@0.1.13; add multilang-ingest design docs

* feat(ingest): multi-language grammar registry (web-tree-sitter, 8 langs, fail-open); 100% cov

* feat(ingest): language-aware param-name splitter (py/go/ts/java/c); 100% cov

* feat(ingest): tree-sitter CodeBlock extractor with wall-clock parse budget + fail-open

* feat(ingest): cross-lang sinks + multilang config + wire tree-sitter into ingestRepository (sync)

* feat(ingest): repoint white-box production callers to multilang config + prod regression test

* server-init-wiring: load multi-language grammars once at bootstrap

initGrammars() runs after LLM init, before app.listen. Internally
fail-open (never rejects): on failure the grammar registry stays empty
and ingest falls back to the Python regex parser.

* adversarial-tests: hostile-input hardening for untrusted target source

Malformed per-language source, wrong-language content, binary/non-UTF8,
empty, unicode identifiers, 20k-func large file (wall-clock budget),
deeply nested input, and a symlink-loop crawl — all must fail-open, never
throw or spin. Drives parseFileMultiLang + ingestRepository/crawl.

* readme-status + docs: flip white-box status to multi-language ingest

README source-code rows now state web-tree-sitter multi-language ingest
(fail-open to Python regex). whitebox.ts scope caveat + no-source error
message updated off the stale Python-only wording.

* coverage-setup: enforce 100% coverage gate on the three new ingest files

vitest.config.ts adds a coverage-only block (v8, perFile thresholds=100)
scoped to ts-grammars.ts, param-split.ts, ts-parse.ts. Test discovery and
env stay on defaults. Edited files gate on new-branch coverage via the
regression suites; the server.ts initGrammars bootstrap line is the
documented smoke-covered carve-out.

* review: fix WASM heap leak, language-scoped fail-open, sink recall/precision

Adversarial security + strict code review (two independent subagents)
returned one blocking bug and several correctness findings; remediated:

BLOCKING #1 — native WASM memory leak: web-tree-sitter Tree/Parser objects
were never .delete()'d. Both reviewers reproduced a process-global wedge:
after ~7 large parses the shared WASM heap exhausts, every subsequent parse
aborts (caught by fail-open), and non-Python ingest silently returns []
forever. Fix: free the tree in a finally; delete the parser in resetParser.
Regression test parses ~8MB through the real shared parser 12x.

regex, which mis-parses brace/class syntax into corrupt blocks (wrong line
spans, lost methods). Now non-.py fail-open returns [] (honest absence); the
Python regex only ever runs on .py. Isolated ts-parse-fallback test.

http(s).request, axios(config), C exec-family); negative lookbehind stops
bare system(/popen(/fetch( from matching Python receivers (os.system etc.
still matched, corpus rankings unchanged). Recall+precision tests added.

operator sees non-Python degradation.

(one-line call-graph edges, no decorators, C++ member methods).

* review round 2: fix sink-regex regressions, real timeout test, deterministic leak guard

Third review round (correctness + security re-attack + test-quality) against
the round-1 fixes surfaced issues in the fixes themselves; remediated:

- Sink-regex regressions I introduced: (1) my fetch lookbehind dropped
  window.fetch/this.fetch (top JS SSRF idiom) — reverted to \bfetch\(;
  (2) bare .Get/.Post/.Do flagged db.Get/cache.Get/queue.Do as SSRF —
  receiver-qualified to [Cc]lient. Recall+precision tests cover both;
  regex is ReDoS-free (timed).
- Placebo leak test: the 12x function-dense loop did NOT wedge the parser
  on machines with heap headroom (proven: passed with tree.delete removed).
  Replaced with a deterministic vi.spyOn(Tree.prototype,'delete') assertion,
  verified RED without the fix.
- Real (non-mocked) parse-timeout test: parseFileMultiLang gains an injectable
  budgetMs; a 0ms budget drives the real progressCallback cancellation to [].
- runWhiteboxAnalysis swap now has coverage (spy on orchestrator.run) so the
  2nd production caller can't silently revert to the Python-only config.
- Un-vacuoused weak tests: unicode now asserts the extracted block; nested/
  wrong-language wrapped in invariants() + timing bounds.
- CI now runs npm run test:coverage (the 100% gate was defined but unenforced).
- Security: documented maxFileBytes as the control bounding a single parse's
  peak WASM memory below the 2GB heap-abort ceiling.
- Stale 'fail-open to Python regex' docs fixed (ts-parse, whitebox, server,
  adversarial); circular-import note added; temp-dir cleanup; honest coverage
  wording in spec + config.

* docs(ingest): align fallback-contract text with the shipped language-scoped fail-open

Review feedback (#75, @jmagly): the design docs + one ts-grammars comment
still described the pre-implementation 'fall back to the Python regex'
model for non-Python files. The shipped contract is language-scoped: .py
uses parseFile; any non-.py file with a missing/unsupported/failed grammar
or a parse timeout returns [] (never the Python regex, which would mis-parse
brace/class syntax into corrupt blocks). Updated every stale reference in
multilang-ingest-spec.md, multilang-ingest-plan.md, and ts-grammars.ts so
the docs match the security boundary. Docs/comment only — no code change.

* fix(test): make the ReDoS wall-clock guard robust under coverage instrumentation

Review feedback (#75, @jmagly): the CI step this PR adds (npm run
test:coverage = vitest run --coverage) runs the full suite under V8
coverage, and that overhead pushes the pathological-brace DoS timing guard
in local-agent-tool-calling.test.ts:69 over its <300ms bound (320 < 300
fails on CI). Raise the bound to 1000ms — still 2x below the ~2100ms
quadratic-ReDoS regression it guards against, so it fails hard if the
regression returns, but no longer false-fails under coverage/slow CI.

Chose the reviewer's option (a) (robust bound) over scoping test:coverage,
so the gate stays a simple full-suite run and no test-file enumeration can
rot. Verified: npm run test:coverage is green and the 3 new files stay at
100%.

* fix(ingest): cover pointer-returning C functions

---------

Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
2026-07-20 11:41:21 -04:00
Krzysztof MarciniakandJoseph Magly 440dedd9c1 feat: update DeepSeek models to V4 Flash and V4 Pro (#103)
* feat: update DeepSeek models to V4 Flash and V4 Pro

- Replace deprecated deepseek-chat / deepseek-reasoner with deepseek-v4-flash / deepseek-v4-pro
- Update base URL from api.deepseek.com/v1 to api.deepseek.com
- Update context window (1M) and max output (384K) per official API docs
- Old models deprecated 2026-07-24

* fix: resolveGeneralLLMConfig missing baseUrl + Admiral timeout 180s

resolveGeneralLLMConfig constructed a new LLMConfig but omitted
baseUrl, causing the adapter to fall back to api.openai.com/v1
regardless of provider — DeepSeek keys hit OpenAI (401).
Also raised Admiral preview timeout to 180s for thinking-mode models.

* fix: createTempestCommandInstance missing baseUrl for operator exec

Operator LLM calls also lacked baseUrl, same 401-for-DeepSeek bug
as resolveGeneralLLMConfig. Reads provider-specific baseUrl from config.

* fix(deepseek): migrate retired persisted defaults

---------

Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
2026-07-20 11:36:50 -04:00
Lyubomir BozhinovandJoseph Magly 9cce68e804 feat(settings): Universal API Config panel with server-side model fetch (#90) (#101)
* feat(settings): Universal API Config panel with server-side model fetch (#90)

Consolidates provider configuration into one "Universal API Config" panel in
Settings — provider dropdown (OpenAI-compatible / Anthropic), base URL, API key,
model with a live "Fetch models" button, and max context tokens — above the
existing per-provider key sections.

Backward-compatible by design: the panel reads and writes the SAME state.settings
keys the individual sections already use (${provider}Key, selectedModel), so
nothing migrates and nothing is lost; the individual sections keep working and
stay in sync.

- src/config/provider-models.ts (new): listProviderModels queries a provider's
  own model endpoint (OpenAI-compatible Bearer /models, Anthropic x-api-key
  /v1/models, OpenRouter public list); resolveModels wraps it fail-open.
- POST /api/models (new route): server-side so the browser dodges provider CORS.
  Binds key+baseUrl by source — a caller-supplied base URL must bring its own
  key, so the server never lends its configured key to a body-chosen URL. Always
  responds, failing open to the static AVAILABLE_MODELS list on a missing key,
  network error, or unknown provider (incl. local-agent) — never hangs.
- Model options are built via the DOM API (createElement/textContent), never
  innerHTML, so untrusted provider-returned model ids cannot inject markup.

Scope notes: augment-not-replace (removing the individual sections is deferred
to maintainer preference); base URL + context cap are stored and used for model
discovery and server/agent flows — in-browser mission routing still uses
OpenRouter/Venice, matching the existing "not wired" hints; the "Model Reasoning
(Eino)" sub-proposal is a separate follow-up pending a mapping.

Verified on macOS: 12 unit tests (RED->GREEN) for the model module, full suite
462 green, and Playwright QA (17 checks) driving the real panel — render,
provider switch, persistence across reload, backward-compat, and both the static
and live Fetch paths.

Refs #90

* fix(settings): harden model list fetch

---------

Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
2026-07-20 11:34:26 -04:00
Joseph Magly 95868c3d37 Merge remote-tracking branch 'upstream/main' into pr-47
# Conflicts:
#	README.md
2026-07-16 11:55:20 -04:00
Joseph Magly db48d881f7 Merge branch 'pr-80' into pr80-delivery
# Conflicts:
#	docs/index.html
#	src/__tests__/local-api-hardening-static.test.ts
2026-07-16 01:18:03 -04:00
Fred BlaiseandFred Blaise 26fe8495b9 feat: allow origin-scoped target headers from env (#65)
Enable authenticated scans across the HTTP arsenal while binding configured credentials to an exact target origin.

Includes case-insensitive per-request overrides, cross-origin redirect containment, protected curl configuration, result redaction, documentation, and regression coverage.

Co-authored-by: Fred Blaise <fred.blaise@protonmail.com>
2026-07-15 23:07:08 -04:00
Junaid Y. SheikhandClaude Opus 4.8 266655abcf fix(ui): separate tour control and add theme switcher (#22)
Two War Room UI fixes (docs/index.html):

1. The floating "guided tour" relaunch button (#t3mpTourRelaunch) was
   position:fixed pinned bottom-left, landing on top of the sidebar
   "Connected" status pill and hiding its first character. Moved it to
   bottom-right (the conventional help-FAB corner) so it collides with
   nothing.

2. Added a theme switcher in the sidebar footer with four themes: Storm
   (the existing teal/green default, visually unchanged), Ember (amber),
   Crimson (red), and Void (violet). The choice persists in localStorage
   and is applied before first paint to avoid a flash of the default theme.

   To make themes reskin the whole UI rather than only the ~87 var(--accent)
   sites, the dominant hardcoded brand colors (#00ff88 / #2fffd2 / #00d4ff
   and their rgba() forms) were converted to CSS variables -- but only
   inside <style> and inline style="..." attributes, where var() is valid.
   Bare JS string literals and SVG fill= attributes are left as-is; most are
   semantic status colors (green=ready, red=error) that should stay fixed.

No JS logic changed; the page renders and all scripts run unchanged.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:51:58 -04:00
Reuben BowlbyandClaude 0f3213b310 docs: add contribution receipt template (#29)
Co-authored-by: Claude (agent) <238336761+hummbl-dev@users.noreply.github.com>
2026-07-15 19:42:38 -04:00
adrianwandCodex 089591b18f feat(scan): add live progress and recon bootstrap (#81)
* Add live scan progress view

* Make local-agent recon report real tool progress

* Feed recon bootstrap into local agent ReAct loop

* Remove stale local-agent JSON tool parser

* Label backend-seeded scan progress

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-15 19:42:20 -04:00
Junaid Y. SheikhandClaude Opus 4.8 8959a288e5 fix(ui): reset War Room after declined or aborted hunt (#63)
* fix(ui): reset War Room to idle when a hunt is declined or aborted

A declined-approval hunt ("hunt not started") — or the red-X abort — left the
War Room stuck advertising an active run: the ENGAGE button stayed on the
"ENGAGING…" spinner (disabled), the LIVE fidelity banner kept claiming "real
tools probing the target", and the narration rail kept showing "Looking at your
target". completeMission() only toggled the button's display, never restoring
its label/disabled/opacity, and never cleared the fidelity banner or narration
rail; abortMission() had the same gap and no-op'd entirely when nothing was
"running" (so the red X did nothing on a declined hunt).

Add resetEngageUI(): restores the ENGAGE button (▶ ENGAGE, enabled) and clears
the fidelity banner (setFidelity('off')) + narration rail. Route both
completeMission() and abortMission() through it, and let the red X clear a
leftover engaging/probing UI even when missionRunning is already false.

Client-side only; no behavior change to an actually-running mission.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): clear stale substatus when the red X resets an idle War Room

Review nit: the idle-abort branch set cmdMissionName='STANDBY' but left
cmdMissionStatus unchanged, so after an approval-declined the header could read
STANDBY with a stale red "approval declined" line beneath it. Reset the
substatus to the initial idle state ("Awaiting orders", #666) too.

Verified: abort after a decline now shows STANDBY / "Awaiting orders" (grey).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:41:11 -04:00
Junaid Y. SheikhandClaude Opus 4.8 168f7df62c fix(ui): route OBSIDIVM benchmarks through any backend (#64)
* fix(ui): route OBSIDIVM benchmarks through any backend, not OpenRouter-only

The OBSIDIVM benchmark/self-improvement UI ran its own client-side,
OpenRouter-only LLM path: getApiKey() read only the OpenRouter key, every
call hardcoded openrouter.ai, and the gate hard-blocked with "Configure
OpenRouter API key first" — so a configured Venice key was ignored and a
connected local agent was never used.

Add a client-side backend resolver (OpenRouter key -> Venice key -> connected
agent -> server LLM) and route all benchmark executors, judges, and gates
through it:

- resolveLLMBackend() + LLM_BACKEND_HINT; safeLLMCall()/_safeLLMCallOnce()
  become backend-aware (Venice uses api.venice.ai with a Venice-valid model;
  OpenRouter unchanged). _backendCall() routes keyless backends through the
  existing server endpoints: /api/agents/local/dispatch (drives the connected
  Claude Code/Codex/Hermes agent) and /api/llm/chat (server LLM).
- runLiveBenchmark, ctfCallLLM, the self-improvement analyzer, and the config
  optimizer now call safeLLMCall instead of a hardcoded openrouter.ai fetch.
- Live-Test / improvement-loop gates and runLLMJudge accept any backend.

Client-side only; no server changes (endpoints already existed). The
recon-only SPECTRA helper is intentionally left OpenRouter-only (out of scope).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): keyless routing must use the API base URL (cross-origin) + model consistency

Addresses review feedback on the OBSIDIVM backend-routing PR.

1. Relative keyless URLs broke the primary cross-origin deployment. _backendCall
   fetched '/api/agents/local/dispatch' and '/api/llm/chat' as RELATIVE URLs, but
   when the static War Room (GitHub Pages docs/) talks to a separate backend the
   app sets T3MP3ST_API.baseUrl = http://<host>:3333. There the relative fetches
   hit the Pages origin → 404/CORS, so the headline local-agent / server-LLM
   routing silently failed (worked only same-origin). Fix: prefix
   `${T3MP3ST_API.baseUrl}` on both; empty base stays relative for same-origin.
   Verified: with baseUrl set, both now resolve to http://<host>:3333/api/...

2. Model default consistency. Four benchmark fallbacks read
   'anthropic/claude-opus-4.8', out of step with the state default, the <option>,
   renderModels and saveApiKey (all 'claude-opus-4.6'). Reverted to 4.6 to match.

(The /api/agents/local/dispatch server route exists — src/server.ts.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): backend-aware gates on the last OpenRouter-only benchmark paths

Addresses the re-review on this PR: two flows this PR claims support Venice /
connected local agent / server LLM still hard-gated on an OpenRouter key.

1. runSingleBenchTest() (single benchmark click): replaced the getApiKey()
   length check with `resolveLLMBackend().kind === 'none'` (+ LLM_BACKEND_HINT),
   matching runBenchmarks('live'). A Venice-only / agent / server backend can now
   click-run a single test instead of being blocked before safeLLMCall().

2. Self-improvement auto-apply:
   - autoApplyForLoop() now falls back to applyFallbackImprovements() only when
     NO backend exists (resolveLLMBackend().kind === 'none'), not merely when the
     OpenRouter key is empty — so the optimizer step uses Venice/agent/server.
   - autoApplyRecommendations() entry gate uses the backend check.
   - The Auto-Apply button show/hide (displayAnalysis) uses `hasBackend =
     resolveLLMBackend().kind !== 'none'` instead of an OpenRouter-only key test.

Verified: gates pass for venice/agent/server, block only when kind==='none';
node --check clean on the inline scripts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:40:46 -04:00
Junaid Y. SheikhandClaude Opus 4.8 8e436d0da2 fix(ui): preserve server-reported live agent count (#71)
The Settings agent card's render() set window.__t3mpLiveAgents from CLIENT-side
pings only (Object.keys(pingStatus).filter(ok)). Agents connected server-side —
via autoReconnect (ping:false) or a status?check=1 re-ping — are live on the
server even though this client never pinged them, so every re-render reset the
count to 0. Since upstream's t3mpHasBackend() is now `llmAvailable || live > 0`,
that clobber made the War Room show "No LLM backbone — connect an agent before
hunting" on localhost even with a genuinely-live local agent (repro: 3 agents
connected, hermes lastPing.ok on the server, yet hasBackend=false after any
detect/render).

Fix: live = max(client-pinged-ok, server-reported-live), reading the server's
own agent state (window.__t3mpServerAgents, refreshed via status?check=1). The
summary and the global now both reflect reality and re-renders no longer break
the gate. Verified: hasBackend stays true across detect/connect re-renders.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:40:26 -04:00
Joseph Magly 4b81bf6436 fix(local): honor server LLM for keyless missions 2026-07-15 18:13:27 -04:00
Joseph Magly 6a2834e6c9 docs: add PR delivery procedure 2026-07-15 18:11:02 -04:00
Codex 3d6dc62957 Tighten approval receipt scoping 2026-07-12 09:50:43 -04:00
Codex 06e1edb4b8 Retry Admiral launch after receipt approval 2026-07-12 09:50:43 -04:00
Codex 964fe5b3ba Add scope receipts approval UI 2026-07-12 09:50:43 -04:00
Codex d500a29186 Ask approval for Admiral expanded scope 2026-07-12 09:50:43 -04:00
Nicolas Pastorello ef5c7c3f51 fix: address Docker security and stability issues from PR review
Fixes all issues raised in PR #47 review:

1. Add .dockerignore to prevent:
   - Real .env secrets baked into image layers
   - Host node_modules (glibc) overwriting alpine (musl) → ABI mismatch
   - .git, reports/, evidence/ bloating the image

2. Fix compose host-binding:
   - Remove T3MP3ST_HOST=127.0.0.1 override (was breaking port forwarding)
   - Server now binds to 0.0.0.0 in-container (DOCKER=true from Dockerfile)
   - Host mapping stays 127.0.0.1:3333:3333 for security

3. Add critical security warning in DOCKER.md:
   - Explain exposure risk of 0.0.0.0 binding + disabled Host-header guard
   - Document safe vs unsafe deployment patterns
   - Warn against network_mode: host and -p 3333:3333 without 127.0.0.1

4. Update base image:
   - node:18-alpine → node:22-alpine (Node 18 EOL)
   - Pin by digest @sha256:16e22a550... (prevent floating tag drift)

5. Fix healthcheck in compose:
   - Was always returning success (process.exit(0))
   - Now actually tests /api/health endpoint
   - Add start_period: 40s to align with Dockerfile

6. Fix port typos in DOCKER.md:
   - 3000 → 3333 in troubleshooting examples
   - Update all example snippets to node:22-alpine with digest
2026-07-08 20:34:34 -03:00
Codex d9a4c47241 Show backend failure reason in UI refusal 2026-07-07 16:04:40 -04:00
Codex 73d888f4a1 Expose stalled local agent failures 2026-07-07 16:04:40 -04:00
Codex fb0feb0028 Report stale local agent backends 2026-07-07 16:04:40 -04:00
Nicolas Pastorello 3aa4023c8f feat: add Docker deployment support
- Add Dockerfile with Node.js 18 alpine build
- Add docker-compose.yml with environment configuration
- Add docs/DOCKER.md deployment guide
- Update README.md with Docker quick start section
- Server binds to 0.0.0.0:3333 for external access
- UI available at http://localhost:3333/ui/
- Volumes mounted for reports and evidence persistence
2026-07-06 17:44:20 -03:00
Tyson Rudd 24d0c3ad5b docs: explain verified provenance setup 2026-07-05 21:23:03 -06:00
pliny 1e20ce1c03 Merge pull request #19 from younger-plinius/keyless-and-readme-v1
fix(keyless): local-agent tool-calling + README readability + 2 review fixes
2026-07-05 14:48:53 -04:00
t3mp3st contributors 921ccc2fa6 fix(keyless): text-CLI tool-calling (hardened per audit) + 2 review fixes 2026-07-05 14:09:50 -04:00
pliny 2f2f6678f4 Merge pull request #15 from joey-david/fix/local-agent-deselection
fix: local agent deselection
2026-07-05 13:57:48 -04:00
pliny 45ec6e4884 Merge pull request #2 from bizstpa/fix/gemini-pro-openrouter-typo
fix: update outdated OpenRouter gemini-3-pro-preview model ID to gemini-3.1
2026-07-05 13:56:50 -04:00
Joey e8dc0b465e Fix local agent deselection 2026-07-05 14:58:12 +02:00
faber 6c57e09023 T3MP3ST v1 — hardened launch (AGPL, verify-claims 24/24, leak-scrubbed) 2026-07-04 21:11:05 -04:00
t3mp3st contributorsandClaude Opus 4.8 5ea8c0af58 Remove the retired Pliny Specials theater
The nine "Pliny Specials" dashboard cards (HYDRA / ARACHNE / CERBERUS /
GORGON / SPHINX / LEVIATHAN / TYPHON / GRIFFIN / SIMURGH) were decorative.
Their backend routes were retired long ago; the in-browser versions ran
randomized [SIMULATED] output; none of them were ever on the hunt path.
They only inflated the arsenal with power:100 / offense:100 stat bars that
measured nothing.

Cut them entirely — the cards, the ~5k-line client-side engine block, their
helper functions (runPlinyDemo / renderStatBars / the tabbed info panel),
the associated CSS, and the "Pliny Specials" category filter. The real
tools (CHIMERA / SPECTRA / ORACLE and the rest of the arsenal) are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 11:30:25 -04:00
t3mp3st contributorsandClaude Opus 4.8 06ffe3ef66 feat: pack-hunt safety + opt-in Kali+ arsenal + capability-approval gate + tester-feedback UX
Adds three coordinated capabilities and tightens two defaults on purpose — this is
safety hardening, NOT a backward-compatible drop-in (see "Tightened defaults").
Fifteen independent adversarial review passes; findings fixed and test-pinned.

- Pack-hunt safety: a strict-majority adjudicator with a comment/string/regex/
  raw-string/heredoc/POD-aware cite-check (language-gated across C/C++/Py/Rust/Go/
  Java/JS/TS/shell/SQL/PHP/Ruby/Perl) so a hallucinated killing-guard can't refute
  a real finding — the cited comparison's operator must match source, and a
  string/regex/heredoc/generic-arglist/template-interpolation is blanked before
  matching. Plus a rate-limit/degraded-health tracker, a global LLM semaphore, and
  a PackBoard with an atomic claim CAS + snapshot-on-emit/clone-on-ingest.
- Opt-in Kali+ arsenal (T3MP3ST_FULL_ARSENAL, OFF by default): 35 default tools
  (31 built-in + 4 external-CLI wrappers) -> 83 with the catalog armed (verify-claims
  CLAIM 4). Most adapters need the underlying binary installed. metasploit / hydra /
  bloodhound are never minted through the generic factory.
- Capability-approval + spicy-action gate for the NEW dangerous arsenal only
  (pre-existing built-ins keep running freely): approve-once, fail-safe deny when
  unattended, redacted audit trail over SSE. T3MP3ST_GATE_BUILTINS=1 extends it to
  the spicy built-in probes. Audit redaction is a pure, unit-tested module.

Tightened defaults (intentional, ON by default — NOT backward-compatible):
- Egress containment: once a mission target is set, built-in networked tools refuse
  off-scope public hosts (not the target/subdomains, not loopback/private) with
  SCOPE DENIED — keeps the agent on authorized scope.
- Role-specialized operator toolkits: each archetype gets a curated default tool
  menu (scanner -> scan tools, exploiter -> sqli/xss/etc). Tools stay registered
  team-wide; the per-role menu is the operator's working set.

UX (from live-tester feedback): a one-click "Approve & run" modal when a standard
Hunt blocks on an external-target receipt (was a dead-end); bounded-parallel
benchmark file ingestion; the deterministic mission-gate chip co-located with the
subjective SITREP pace narration (no more "behind schedule" next to a clean gate);
and click-through finding detail + evidence in the UI (was export-only).

Docs: README + INTEGRITY_LEDGER made re-derivable — honest 35/83 tool count, the
egress-containment default documented, and the Cybench number reconciled to the
single verify-claims-enforced 23/40 = 58% (dropped the stale/uncited 21 and 26).
README voice pass: killed the underselling `Successful Exploits: 0` disqualifier
(read as "never popped anything" — false, given CVE-Zero + the live disclosure
pipeline); swagger now rests on receipts, not vibes. Also corrected the operator
status — the downstream operators run the SAME real tool-backed ReAct loop as
recon (not "orchestration stubs"); the honest limit is that the coordinated swarm
is unproven (single-agent is the benchmarked path), not that they're scaffolding.

Gates: 292 tests, tsc + lint clean, verify-claims 20/20, arsenal:smoke 125/0,
disclosure-CLI self-test 11/11.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 09:38:23 -04:00
t3mp3st contributors 184c7d4e59 T3MP3ST public launch build 2026-07-03 10:57:20 -04:00
Ryan Khatib f3e0af53a1 fix(ui): patch hardcoded sk- string matching for OpenRouter API keys & update Gemini preview model ID 2026-07-03 02:10:35 +03:00
pliny a303b917db Delete docs/LAUNCH_SCORECARD.md 2026-07-02 14:05:08 -04:00
pliny 82b0870205 Delete docs/AI_REDTEAM_TECHNIQUES.md 2026-07-02 14:04:35 -04:00
pliny d12fe6fea1 Delete docs/THE_CLAIM.md 2026-07-02 14:04:22 -04:00
pliny 38fac38311 Add files via upload 2026-07-02 13:57:34 -04:00