feat(host-agent): add Console task submission with Host self-submission client
Adds a CSRF-protected task submission form to the local Console Tasks page
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from host_agent.history import ConsoleHistoryStore
|
||||
@@ -67,3 +68,71 @@ def test_history_store_uses_injected_now_for_occurred_at(tmp_path) -> None:
|
||||
entries = store.list_recent()
|
||||
|
||||
assert entries[0]["occurred_at"] == fixed_now.isoformat()
|
||||
|
||||
|
||||
def test_history_store_records_task_submission_with_device(tmp_path) -> None:
|
||||
store = ConsoleHistoryStore(tmp_path / "history.sqlite3")
|
||||
|
||||
store.record_task_submission(task_id="task-cloud-1", device_id="device-cloud-a")
|
||||
|
||||
entries = store.list_recent()
|
||||
|
||||
assert len(entries) == 1
|
||||
assert entries[0]["kind"] == "task_submission"
|
||||
assert entries[0]["summary"] == "task submitted: task-cloud-1 on device-cloud-a"
|
||||
assert entries[0]["detail"] == {
|
||||
"task_id": "task-cloud-1",
|
||||
"device_id": "device-cloud-a",
|
||||
}
|
||||
|
||||
|
||||
def test_history_store_records_task_submission_without_device(tmp_path) -> None:
|
||||
store = ConsoleHistoryStore(tmp_path / "history.sqlite3")
|
||||
|
||||
store.record_task_submission(task_id="task-cloud-2", device_id=None)
|
||||
|
||||
entries = store.list_recent()
|
||||
|
||||
assert entries[0]["summary"] == (
|
||||
"task submitted: task-cloud-2 (automatic device)"
|
||||
)
|
||||
assert entries[0]["detail"] == {"task_id": "task-cloud-2"}
|
||||
|
||||
|
||||
def test_history_store_task_submission_redacts_goal_and_secrets(tmp_path) -> None:
|
||||
store = ConsoleHistoryStore(tmp_path / "history.sqlite3")
|
||||
secret_goal = (
|
||||
"rotate secret-XYZ-abcdef-very-secret "
|
||||
"cookie=session-abc; lease=lease-stale"
|
||||
)
|
||||
|
||||
store.record_task_submission(task_id="task-cloud-3", device_id="device-cloud-a")
|
||||
store.record_heartbeat(device_count=1)
|
||||
|
||||
entries = store.list_recent()
|
||||
rendered = "\n".join(
|
||||
repr(entry["summary"]) + " " + json.dumps(entry["detail"])
|
||||
for entry in entries
|
||||
)
|
||||
|
||||
assert secret_goal not in rendered
|
||||
assert "session-abc" not in rendered
|
||||
assert "lease-stale" not in rendered
|
||||
|
||||
|
||||
def test_history_store_task_submissions_prune_beyond_limit(tmp_path) -> None:
|
||||
store = ConsoleHistoryStore(tmp_path / "history.sqlite3", limit=3)
|
||||
|
||||
for index in range(5):
|
||||
store.record_task_submission(
|
||||
task_id=f"task-{index}", device_id=f"device-{index}"
|
||||
)
|
||||
|
||||
entries = store.list_recent()
|
||||
|
||||
assert len(entries) == 3
|
||||
assert [entry["detail"]["task_id"] for entry in entries] == [
|
||||
"task-4",
|
||||
"task-3",
|
||||
"task-2",
|
||||
]
|
||||
Reference in New Issue
Block a user