feat: add safe miner control foundation
This commit is contained in:
1 parent
6cd876b4b3
commit
f5965af914
39 files changed
+2952
-491
No files matched your search
@@ -78,8 +78,8 @@ migration_head="$(
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'psql -v ON_ERROR_STOP=1 -At -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT version_num FROM alembic_version"'
|
||||
)"
|
||||
if [[ "${migration_head}" != "0014_repair_parts_tracking" ]]; then
|
||||
echo "Refusing demo seed: database Alembic head is ${migration_head:-missing}, expected 0014_repair_parts_tracking." >&2
|
||||
if [[ "${migration_head}" != "0015_miner_control_foundation" ]]; then
|
||||
echo "Refusing demo seed: database Alembic head is ${migration_head:-missing}, expected 0015_miner_control_foundation." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ health_json="$(cat "${health_file}")"
|
||||
|
||||
echo "Checking migrations and required schema..."
|
||||
current_revision="$("${compose[@]}" exec -T backend alembic current 2>/dev/null)"
|
||||
[[ "${current_revision}" == *"0014_repair_parts_tracking"* ]]
|
||||
[[ "${current_revision}" == *"0015_miner_control_foundation"* ]]
|
||||
|
||||
missing_tables="$(
|
||||
"${compose[@]}" exec -T postgres sh -c \
|
||||
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
project_name="${MINEROPS_CONTROL_MIGRATION_PROJECT:-minerops-control-migration-$$}"
|
||||
compose=(docker compose --project-name "${project_name}" --env-file .env.dev -f compose.dev.yaml)
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
if (( status != 0 )); then
|
||||
"${compose[@]}" logs --no-color --tail 120 postgres || true
|
||||
fi
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
exit "${status}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
run_alembic() { "${compose[@]}" run --rm --no-deps backend alembic "$@"; }
|
||||
psql_db() {
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'exec psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" "$@"' sh "$@"
|
||||
}
|
||||
|
||||
[[ -f .env.dev ]] || { echo "Missing .env.dev" >&2; exit 1; }
|
||||
"${compose[@]}" up --detach postgres
|
||||
for attempt in $(seq 1 60); do
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"' >/dev/null 2>&1 && break
|
||||
(( attempt < 60 )) || { echo "PostgreSQL did not become ready" >&2; exit 1; }
|
||||
sleep 1
|
||||
done
|
||||
"${compose[@]}" build backend
|
||||
|
||||
echo "Testing 0015 preflight failures from the previous head..."
|
||||
run_alembic upgrade 0014_repair_parts_tracking
|
||||
psql_db -c "INSERT INTO minerops_agent_command_queue (id, agent_id, command_type, command_status) VALUES ('unknown-status', 'test-agent', 'test', 'mystery')"
|
||||
if output="$(run_alembic upgrade 0015_miner_control_foundation 2>&1)"; then
|
||||
echo "Unknown queue status unexpectedly passed migration preflight" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"unsupported command_status values: mystery"* ]]
|
||||
psql_db -c "DELETE FROM minerops_agent_command_queue WHERE id = 'unknown-status'"
|
||||
|
||||
duplicate_miner="00000000-0000-4000-8000-000000001599"
|
||||
psql_db <<SQL
|
||||
INSERT INTO minerops_agent_command_queue (id, agent_id, command_type, command_status, request_payload)
|
||||
VALUES
|
||||
('duplicate-one', 'test-agent', 'miner_control', 'pending', '{"miner_id":"${duplicate_miner}"}'),
|
||||
('duplicate-two', 'test-agent', 'miner_control', 'claimed', '{"miner_id":"${duplicate_miner}"}');
|
||||
SQL
|
||||
if output="$(run_alembic upgrade 0015_miner_control_foundation 2>&1)"; then
|
||||
echo "Duplicate live controls unexpectedly passed migration preflight" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"more than one pending or claimed miner_control"* ]]
|
||||
[[ "${output}" == *"${duplicate_miner}"* ]]
|
||||
psql_db -c "DELETE FROM minerops_agent_command_queue WHERE id IN ('duplicate-one', 'duplicate-two')"
|
||||
|
||||
psql_db <<'SQL'
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name)
|
||||
VALUES ('legacy-unassigned-agent', 'Legacy Display Name');
|
||||
INSERT INTO minerops_agent_command_queue (
|
||||
id, agent_id, command_type, command_status, request_payload
|
||||
) VALUES (
|
||||
'preserved-history', 'legacy-unassigned-agent', 'miner_control', 'completed',
|
||||
'{"miner_id":"00000000-0000-4000-8000-000000001598","action":"suspend"}'
|
||||
);
|
||||
SQL
|
||||
run_alembic upgrade 0015_miner_control_foundation
|
||||
[[ "$(run_alembic current 2>/dev/null)" == *"0015_miner_control_foundation"* ]]
|
||||
|
||||
echo "Checking assignment, status, uniqueness, history, and preservation..."
|
||||
psql_db <<'SQL'
|
||||
DO $$
|
||||
BEGIN
|
||||
IF (SELECT site_id IS NOT NULL FROM minerops_site_agents
|
||||
WHERE agent_id = 'legacy-unassigned-agent') THEN
|
||||
RAISE EXCEPTION 'Legacy site_name was silently converted to site_id';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM minerops_agent_command_queue
|
||||
WHERE id = 'preserved-history' AND command_status = 'completed') THEN
|
||||
RAISE EXCEPTION 'Historical queue row was not preserved';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint
|
||||
WHERE conname = 'ck_minerops_agent_command_queue_status') THEN
|
||||
RAISE EXCEPTION 'Queue status constraint missing';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_indexes
|
||||
WHERE indexname = 'uq_agent_queue_live_miner_control')
|
||||
OR NOT EXISTS (SELECT 1 FROM pg_indexes
|
||||
WHERE indexname = 'idx_agent_queue_miner_control_history') THEN
|
||||
RAISE EXCEPTION 'Miner control queue indexes missing';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
INSERT INTO sites (id, name)
|
||||
VALUES ('00000000-0000-4000-8000-000000001590', 'Control Migration Site');
|
||||
UPDATE minerops_site_agents SET site_id = '00000000-0000-4000-8000-000000001590'
|
||||
WHERE agent_id = 'legacy-unassigned-agent';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
INSERT INTO minerops_site_agents (agent_id, site_id, site_name)
|
||||
VALUES ('duplicate-site-agent', '00000000-0000-4000-8000-000000001590', 'Duplicate');
|
||||
RAISE EXCEPTION 'Duplicate durable site assignment was accepted';
|
||||
EXCEPTION WHEN unique_violation THEN NULL;
|
||||
END;
|
||||
BEGIN
|
||||
DELETE FROM sites WHERE id = '00000000-0000-4000-8000-000000001590';
|
||||
RAISE EXCEPTION 'Assigned site deletion was accepted';
|
||||
EXCEPTION WHEN foreign_key_violation THEN NULL;
|
||||
END;
|
||||
BEGIN
|
||||
INSERT INTO minerops_agent_command_queue (id, agent_id, command_type, command_status)
|
||||
VALUES ('bad-status-after', 'legacy-unassigned-agent', 'test', 'mystery');
|
||||
RAISE EXCEPTION 'Unknown status passed CHECK';
|
||||
EXCEPTION WHEN check_violation THEN NULL;
|
||||
END;
|
||||
END $$;
|
||||
SQL
|
||||
|
||||
echo "Testing downgrade, historical preservation, and re-upgrade..."
|
||||
run_alembic downgrade 0014_repair_parts_tracking
|
||||
[[ "$(run_alembic current 2>/dev/null)" == *"0014_repair_parts_tracking"* ]]
|
||||
[[ "$(psql_db -Atc "SELECT count(*) FROM minerops_agent_command_queue WHERE id = 'preserved-history'")" == "1" ]]
|
||||
[[ "$(psql_db -Atc "SELECT count(*) FROM information_schema.columns WHERE table_name='minerops_site_agents' AND column_name='site_id'")" == "0" ]]
|
||||
run_alembic upgrade 0015_miner_control_foundation
|
||||
|
||||
echo "Testing empty database through head..."
|
||||
"${compose[@]}" exec -T postgres sh -ec 'createdb -U "$POSTGRES_USER" minerops_control_empty'
|
||||
"${compose[@]}" run --rm --no-deps -e POSTGRES_DB=minerops_control_empty backend alembic upgrade head
|
||||
empty_revision="$("${compose[@]}" exec -T postgres sh -ec \
|
||||
'psql -U "$POSTGRES_USER" -d minerops_control_empty -Atc "SELECT version_num FROM alembic_version"')"
|
||||
[[ "${empty_revision}" == "0015_miner_control_foundation" ]]
|
||||
|
||||
echo "Miner Control Foundation migration tests passed."
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
project_name="${MINEROPS_CONTROL_TEST_PROJECT:-minerops-control-test-$$}"
|
||||
compose=(docker compose --project-name "${project_name}" --env-file .env.dev -f compose.dev.yaml)
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
if (( status != 0 )); then
|
||||
"${compose[@]}" logs --no-color --tail 120 postgres || true
|
||||
fi
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
exit "${status}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
[[ -f .env.dev ]] || { echo "Missing .env.dev" >&2; exit 1; }
|
||||
for source_file in backend/tests/test_miner_control.py backend/tests/test_agent_commands.py backend/tests/test_miner_control_postgres.py; do
|
||||
permissions="$(stat -c '%a' "${source_file}")"
|
||||
(( (10#${permissions} % 10) & 4 )) || {
|
||||
echo "${source_file} is not readable by the non-root test container" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
for source_directory in agents agents/windows agents/windows/tests; do
|
||||
permissions="$(stat -c '%a' "${source_directory}")"
|
||||
(( (10#${permissions} % 10) & 1 )) || {
|
||||
echo "${source_directory} is not traversable by the non-root test container" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
"${compose[@]}" up --detach postgres
|
||||
for attempt in $(seq 1 60); do
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"' >/dev/null 2>&1 && break
|
||||
(( attempt < 60 )) || { echo "PostgreSQL did not become ready" >&2; exit 1; }
|
||||
sleep 1
|
||||
done
|
||||
"${compose[@]}" build backend
|
||||
"${compose[@]}" run --rm --no-deps backend alembic upgrade head
|
||||
"${compose[@]}" run --rm --no-deps \
|
||||
-v "${repo_root}/backend/tests:/app/tests:ro" \
|
||||
-v "${repo_root}/agents:/agents:ro" \
|
||||
backend python -m unittest -v \
|
||||
tests.test_miner_control \
|
||||
tests.test_agent_commands \
|
||||
tests.test_miner_control_postgres
|
||||
|
||||
echo "Miner Control Foundation focused tests passed."
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
service="agents/windows/MinerOpsAgentService.ps1"
|
||||
control="agents/windows/MinerOpsControl.ps1"
|
||||
rg -q 'X-MinerOps-Agent-ID' "${service}"
|
||||
! rg -q 'commands/pending\?agent_id=' "${service}"
|
||||
! rg -q 'DefaultValue "super"' "${service}"
|
||||
rg -q 'get\.miner\.setting' "${control}"
|
||||
rg -q '\$attempt -le 3' "${control}"
|
||||
rg -q 'VerificationStatus "unconfirmed"' "${control}"
|
||||
for secret_field in 'api3_password =' 'api3_account =' 'raw_vendor' 'salt_response'; do
|
||||
! rg -q "${secret_field}" "${control}"
|
||||
done
|
||||
|
||||
if command -v pwsh >/dev/null 2>&1; then
|
||||
pwsh -NoProfile -File agents/windows/tests/Test-MinerOpsControl.ps1
|
||||
else
|
||||
echo "pwsh is not installed; deterministic PowerShell harness retained but not executed."
|
||||
fi
|
||||
echo "Windows Agent source contract checks passed."
|
||||
Reference in new issue
Block a user