home@ubuntu-dev:~/p/g/HackTuah/HackTUI-Hermes-Jido$ sudo -u postgres psql
psql (16.13 (Ubuntu 16.13-0ubuntu0.24.04.1))
Type "help" for help.
postgres=# CREATE USER hacktui WITH PASSWORD 'hacktui';
CREATE DATABASE hacktui_dev OWNER hacktui;
CREATE ROLE
CREATE DATABASE
postgres=# \q
home@ubuntu-dev:~/p/g/HackTuah/HackTUI-Hermes-Jido$ export HACKTUI_START_REPO=true
export HACKTUI_DB_NAME=hacktui_dev
export HACKTUI_DB_USER=hacktui
export HACKTUI_DB_PASS=hacktui
export HACKTUI_DB_HOST=localhost
export HACKTUI_DB_PORT=5432
home@ubuntu-dev:~/p/g/HackTuah/HackTUI-Hermes-Jido$ mix ecto.create
mix ecto.migrate
The database for HacktuiStore.Repo has already been created
13:44:37.636 [info] == Running 20260307000100 HacktuiStore.Repo.Migrations.CreateAlertsAndTransitions.change/0 forward
13:44:37.637 [info] create table alerts
13:44:37.651 [info] create index alerts_alert_id_index
13:44:37.653 [info] create table alert_transitions
13:44:37.659 [info] == Migrated 20260307000100 in 0.0s
13:44:37.703 [info] == Running 20260307000200 HacktuiStore.Repo.Migrations.CreateCasesActionsAndAudit.change/0 forward
13:44:37.703 [info] create table cases
13:44:37.709 [info] create index cases_case_id_index
13:44:37.711 [info] create table case_timeline_entries
13:44:37.716 [info] create table action_requests
13:44:37.721 [info] create index action_requests_action_request_id_index
13:44:37.723 [info] create table audit_events
13:44:37.727 [info] create index audit_events_audit_id_index
13:44:37.730 [info] == Migrated 20260307000200 in 0.0s
home@ubuntu-dev:~/p/g/HackTuah/HackTUI-Hermes-Jido$ mix test
==> hacktui_core
13:44:41.331 [info] [hacktui_store] start_repo=false
13:44:41.379 [info] [hacktui_collab] enabled_providers=[]
13:44:41.541 [info] [hacktui_agent] enabled_backends=[]
Running ExUnit with seed: 566974, max_cases: 48
.......................
Finished in 0.1 seconds (0.1s async, 0.00s sync)
23 tests, 0 failures
==> hacktui_store
Running ExUnit with seed: 566974, max_cases: 48
Excluding tags: [integration: true]
.........
1) test builds alert queue query (HacktuiStore.ReadModelsTest)
apps/hacktui_store/test/hacktui_store_read_models_test.exs:7
Assertion with == failed
code: assert query.from.source == {"alerts", Alert}
left: %Ecto.SubQuery{
select: nil,
cache: nil,
params: nil,
query: #Ecto.Query<from a0 in HacktuiStore.Schema.Alert, union_all: (from a0 in HacktuiStore.Schema.AuditEvent,
where: fragment("? ILIKE '%alert%'", a0.entry_type),
select: %{
alert_id: fragment("?->>'alert_id'", a0.payload),
title: fragment("?->>'title'", a0.payload),
severity: fragment("?->>'severity'", a0.payload),
state: fragment("'open'"),
inserted_at: a0.occurred_at,
metadata: a0.payload
}), select: %{
alert_id: a0.alert_id,
title: a0.title,
severity: a0.severity,
state: a0.state,
inserted_at: a0.inserted_at,
metadata: fragment("'{}'::jsonb")
}>
}
right: {"alerts", HacktuiStore.Schema.Alert}
stacktrace:
test/hacktui_store_read_models_test.exs:9: (test)
.........
13:44:42.025 [notice] Application hacktui_store exited: :stopped
13:44:42.028 [info] [hacktui_store] start_repo=true
13:44:42.090 [error] Postgrex.Protocol (#PID<0.611.0> ("db_conn_1")) failed to connect: ** (DBConnection.ConnectionError) tcp connect (127.0.0.1:65432): connection refused - :econnrefused
13:44:44.624 [error] Postgrex.Protocol (#PID<0.611.0> ("db_conn_1")) failed to connect: ** (DBConnection.ConnectionError) tcp connect (127.0.0.1:65432): connection refused - :econnrefused
13:44:48.078 [notice] Application hacktui_store exited: :stopped
......
Finished in 6.2 seconds (0.1s async, 6.0s sync)
33 tests, 1 failure, 8 excluded
==> hacktui_sensor
Running ExUnit with seed: 566974, max_cases: 48
Excluding tags: [integration: true]
.
1) test starts collector supervision boundaries and ingests live observations locally (HacktuiSensorTest)
apps/hacktui_sensor/test/hacktui_sensor_test.exs:6
condition was not met in time
code: assert_eventually(fn ->
stacktrace:
test/hacktui_sensor_test.exs:20: (test)
Finished in 2.0 seconds (0.00s async, 2.0s sync)
2 tests, 1 failure
==> hacktui_hub
Running ExUnit with seed: 566974, max_cases: 48
Excluding tags: [integration: true]
...........
1) test orchestrates alert transitions (HacktuiHub.RuntimeTest)
apps/hacktui_hub/test/hacktui_hub_runtime_test.exs:44
** (UndefinedFunctionError) function HacktuiHub.TestSupport.FakeTransactionRepo.get_by/2 is undefined or private
code: Runtime.create_alert(create, repo: FakeTransactionRepo, event_id: "evt-1", occurred_at: now)
stacktrace:
HacktuiHub.TestSupport.FakeTransactionRepo.get_by(HacktuiStore.Schema.Alert, [alert_id: "alert-1"])
(hacktui_hub 0.1.0) lib/hacktui_hub/runtime.ex:461: HacktuiHub.Runtime.persist_alert_correlation_metadata/7
(hacktui_hub 0.1.0) lib/hacktui_hub/runtime.ex:356: HacktuiHub.Runtime.persist_or_correlate_alert/6
(hacktui_hub 0.1.0) lib/hacktui_hub/runtime.ex:84: HacktuiHub.Runtime.create_alert/2
test/hacktui_hub_runtime_test.exs:54: (test)
.
2) test orchestrates alert creation and persistence (HacktuiHub.RuntimeTest)
apps/hacktui_hub/test/hacktui_hub_runtime_test.exs:23
** (UndefinedFunctionError) function HacktuiHub.TestSupport.FakeTransactionRepo.get_by/2 is undefined or private
code: Runtime.create_alert(command,
stacktrace:
HacktuiHub.TestSupport.FakeTransactionRepo.get_by(HacktuiStore.Schema.Alert, [alert_id: "alert-1"])
(hacktui_hub 0.1.0) lib/hacktui_hub/runtime.ex:461: HacktuiHub.Runtime.persist_alert_correlation_metadata/7
(hacktui_hub 0.1.0) lib/hacktui_hub/runtime.ex:356: HacktuiHub.Runtime.persist_or_correlate_alert/6
(hacktui_hub 0.1.0) lib/hacktui_hub/runtime.ex:84: HacktuiHub.Runtime.create_alert/2
test/hacktui_hub_runtime_test.exs:33: (test)
3) test exposes query functions over store read models (HacktuiHub.RuntimeTest)
apps/hacktui_hub/test/hacktui_hub_runtime_test.exs:144
** (FunctionClauseError) no function clause matching in HacktuiHub.QueryService.normalize_alert/1
The following arguments were given to HacktuiHub.QueryService.normalize_alert/1:
# 1
{"alerts", HacktuiStore.Schema.Alert}
Attempted function clauses (showing 2 out of 2):
defp normalize_alert(%HacktuiStore.Schema.Alert{} = alert)
defp normalize_alert(%{metadata: metadata} = alert)
code: assert [{"alerts", HacktuiStore.Schema.Alert}] = QueryService.alert_queue(FakeQueryRepo)
stacktrace:
(hacktui_hub 0.1.0) lib/hacktui_hub/query_service.ex:348: HacktuiHub.QueryService.normalize_alert/1
(elixir 1.18.4) lib/enum.ex:1714: Enum."-map/2-lists^map/1-1-"/2
(hacktui_hub 0.1.0) lib/hacktui_hub/query_service.ex:26: HacktuiHub.QueryService.alert_queue/1
test/hacktui_hub_runtime_test.exs:145: (test)
warning: HacktuiHub.ThreatIntel.Indexer.table/0 is undefined or private
│
8 │ case :ets.whereis(Indexer.table()) do
│ ~
│
└─ test/threat_intel_test.exs:8:31: HacktuiHub.ThreatIntelTest.__ex_unit_setup_0/1
warning: HacktuiHub.ThreatIntel.Indexer.load/1 is undefined or private
│
17 │ :ok = Indexer.load(keywords: [%{keyword: "mimikatz", severity: :high, source: "test"}])
│ ~
│
└─ test/threat_intel_test.exs:17:19: HacktuiHub.ThreatIntelTest."test loads keywords into ets and enriches matching observations"/1
warning: HacktuiHub.ThreatIntel.Enricher.enrich/2 is undefined or private. Did you mean:
* enrich/1
│
43 │ enriched = Enricher.enrich(observation, dataset_path: "/missing/path.json")
│ ~
│
└─ test/threat_intel_test.exs:43:25: HacktuiHub.ThreatIntelTest."test ingestion remains resilient when datasets are unavailable"/1
.....
4) test ingestion remains resilient when datasets are unavailable (HacktuiHub.ThreatIntelTest)
apps/hacktui_hub/test/threat_intel_test.exs:33
** (UndefinedFunctionError) function HacktuiHub.ThreatIntel.Indexer.table/0 is undefined or private
stacktrace:
(hacktui_hub 0.1.0) HacktuiHub.ThreatIntel.Indexer.table()
test/threat_intel_test.exs:8: HacktuiHub.ThreatIntelTest.__ex_unit_setup_0/1
test/threat_intel_test.exs:1: HacktuiHub.ThreatIntelTest.__ex_unit__/2
5) test loads keywords into ets and enriches matching observations (HacktuiHub.ThreatIntelTest)
apps/hacktui_hub/test/threat_intel_test.exs:16
** (UndefinedFunctionError) function HacktuiHub.ThreatIntel.Indexer.table/0 is undefined or private
stacktrace:
(hacktui_hub 0.1.0) HacktuiHub.ThreatIntel.Indexer.table()
test/threat_intel_test.exs:8: HacktuiHub.ThreatIntelTest.__ex_unit_setup_0/1
test/threat_intel_test.exs:1: HacktuiHub.ThreatIntelTest.__ex_unit__/2
...
Finished in 0.1 seconds (0.1s async, 0.00s sync)
28 tests, 5 failures, 3 excluded
==> hacktui_collab
Running ExUnit with seed: 566974, max_cases: 48
Excluding tags: [integration: true]
..........
Finished in 0.05 seconds (0.05s async, 0.00s sync)
11 tests, 0 failures, 1 excluded
==> hacktui_agent
Running ExUnit with seed: 566974, max_cases: 48
Excluding tags: [integration: true]
.........
13:44:50.571 [notice] Executing HacktuiAgent.Actions.Investigation.CorrelateContext with params: %{} and context: %{state: %{status: :queued, context: %{timeline: [%{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}], alerts: [%{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}]}, case_id: "case-1", correlation: %{}, report_draft: %{}}, action_metadata: %{name: "investigation_correlate_context", description: "Correlate case context and alert context to identify shared indicators.", vsn: nil, category: nil, tags: [], schema: [], output_schema: [], compensation: %{timeout: 5000, enabled: false, max_retries: 1}}}
13:44:50.571 [notice] Executing HacktuiAgent.Actions.Investigation.DraftReport with params: %{} and context: %{state: %{status: :correlated, context: %{timeline: [%{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}], alerts: [%{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}]}, case_id: "case-1", correlation: %{case_id: "case-1", matched_alert_ids: ["alert-1", "alert-2"], shared_indicators: ["10.0.0.4", "malicious.example"]}, report_draft: %{}}, action_metadata: %{name: "investigation_draft_report", description: "Draft a report from the correlated investigation state.", vsn: nil, category: nil, tags: [], schema: [], output_schema: [], compensation: %{timeout: 5000, enabled: false, max_retries: 1}}}
13:44:50.572 [notice] Executing HacktuiAgent.Actions.Investigation.EmitCompletion with params: %{} and context: %{state: %{status: :report_drafted, context: %{timeline: [%{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}], alerts: [%{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}, %{size: 3, type: :map, __truncated_depth__: 4}]}, case_id: "case-1", correlation: %{case_id: "case-1", matched_alert_ids: ["alert-1", "alert-2"], shared_indicators: ["10.0.0.4", "malicious.example"]}, report_draft: %{summary: "Draft report for case-1: correlated alerts [alert-1, alert-2] across indicators [10.0.0.4, malicious.example]", case_id: "case-1", matched_alert_ids: ["alert-1", "alert-2"], shared_indicators: ["10.0.0.4", "malicious.example"]}}, action_metadata: %{name: "investigation_emit_completion", description: "Emit an investigation completed signal for downstream consumers.", vsn: nil, category: nil, tags: [], schema: [], output_schema: [], compensation: %{timeout: 5000, enabled: false, max_retries: 1}}}
.......
Finished in 0.1 seconds (0.1s async, 0.00s sync)
22 tests, 0 failures, 6 excluded
==> hacktui_tui
Running ExUnit with seed: 566974, max_cases: 48
Excluding tags: [integration: true]
1) test renders threat-context observations with a visible threat marker (HacktuiTui.LiveDashboardViewTest)
apps/hacktui_tui/test/live_dashboard_view_test.exs:6
** (UndefinedFunctionError) function HacktuiTui.LiveDashboardView.render/1 is undefined or private. Did you mean:
* render/2
* render/3
code: LiveDashboardView.render(%{
stacktrace:
(hacktui_tui 0.1.0) HacktuiTui.LiveDashboardView.render(%{alerts: [], cases: [], observations: [%{metadata: %{threat_context: %{keyword: "mimikatz", severity: :high}}, kind: "process_start", payload: %{raw_message: "mimikatz executed", summary: "credential access"}, accepted_at: ~U[2026-03-14 00:00:00Z]}], health: %{summary: "ok"}, refreshed_at: "now", status_line: "ready", ui: %{mode: :normal, focused_pane: :observations, selections: %{observations: 0}}})
test/live_dashboard_view_test.exs:8: (test)
......... warning: HacktuiTui.LiveDashboardView.render/1 is undefined or private. Did you mean:
* render/2
* render/3
│
8 │ LiveDashboardView.render(%{
│ ~
│
└─ test/live_dashboard_view_test.exs:8:25: HacktuiTui.LiveDashboardViewTest."test renders threat-context observations with a visible threat marker"/1
...
Finished in 0.06 seconds (0.06s async, 0.00s sync)
13 tests, 1 failure
I'm still waiting for the GPT-tooth-fairy to gift me with free inference, at which point I will be glad to tinker around and submit a PR.
Just bringing this to your attention in the meantime. Looking forward to diving in.
Haven't looked too closely but I tried doing the onboarding steps in
README.md. Ran tests and had some errors:I'm still waiting for the GPT-tooth-fairy to gift me with free inference, at which point I will be glad to tinker around and submit a PR.
Just bringing this to your attention in the meantime. Looking forward to diving in.