feat(agent): add durable existing-agent credential transitions
This commit is contained in:
1 parent
abf5654a25
commit
3cfb0d1abe
33 files changed
+3828
-54
No files matched your search
@@ -78,8 +78,12 @@ 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}" != "0016_agent_zones" ]]; then
|
||||
echo "Refusing demo seed: database Alembic head is ${migration_head:-missing}, expected 0016_agent_zones." >&2
|
||||
expected_head="$(
|
||||
"${compose[@]}" run --rm --no-deps backend alembic heads 2>/dev/null |
|
||||
awk 'NR == 1 { print $1 }'
|
||||
)"
|
||||
if [[ -z "${expected_head}" || "${migration_head}" != "${expected_head}" ]]; then
|
||||
echo "Refusing demo seed: database Alembic head is ${migration_head:-missing}, expected ${expected_head:-unresolved}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
project_name="${MINEROPS_LEGACY_RETIREMENT_PROJECT:-minerops-legacy-retirement-$$}"
|
||||
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 160 postgres || true
|
||||
fi
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
exit "${status}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
run_db_alembic() {
|
||||
local database="$1"
|
||||
shift
|
||||
"${compose[@]}" run --rm --no-deps -e POSTGRES_DB="${database}" backend alembic "$@"
|
||||
}
|
||||
psql_named() {
|
||||
local database="$1"
|
||||
shift
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'database="$1"; shift; exec psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$database" "$@"' \
|
||||
sh "${database}" "$@"
|
||||
}
|
||||
create_database() {
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'exec createdb -U "$POSTGRES_USER" "$1"' sh "$1"
|
||||
}
|
||||
run_contract() {
|
||||
local database="$1"
|
||||
local case_name="$2"
|
||||
local agent_id="$3"
|
||||
"${compose[@]}" run --rm --no-deps \
|
||||
--volume "${repo_root}/backend/tests:/app/tests:ro" \
|
||||
--env POSTGRES_DB="${database}" \
|
||||
--env MINEROPS_LEGACY_RETIREMENT_DISPOSABLE=1 \
|
||||
--env MINEROPS_LEGACY_RETIREMENT_CASE="${case_name}" \
|
||||
--env MINEROPS_AGENT_ID="${agent_id}" \
|
||||
--env MINEROPS_AGENT_SHARED_SECRET=legacy-retirement-contract-secret \
|
||||
backend python -m unittest -v \
|
||||
tests.test_agent_legacy_auth_retirement_postgres
|
||||
}
|
||||
|
||||
[[ -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
|
||||
expected_head="$(run_db_alembic postgres heads 2>/dev/null | awk 'NR == 1 { print $1 }')"
|
||||
[[ "${expected_head}" == "0020_existing_agent_transition" ]]
|
||||
|
||||
echo "Testing selective 0019 backfill from the 0018 schema..."
|
||||
create_database legacy_retirement_uncredentialed
|
||||
run_db_alembic legacy_retirement_uncredentialed upgrade 0018_legacy_agent_routing
|
||||
psql_named legacy_retirement_uncredentialed -c \
|
||||
"INSERT INTO minerops_site_agents (agent_id, site_name) VALUES ('legacy-uncredentialed', 'Legacy')"
|
||||
run_db_alembic legacy_retirement_uncredentialed upgrade head
|
||||
[[ "$(psql_named legacy_retirement_uncredentialed -Atc "SELECT legacy_auth_disabled_at IS NULL FROM minerops_site_agents WHERE agent_id='legacy-uncredentialed'")" == "t" ]]
|
||||
[[ "$(psql_named legacy_retirement_uncredentialed -Atc "SELECT count(*) FROM agent_legacy_auth_retirements WHERE agent_id='legacy-uncredentialed'")" == "0" ]]
|
||||
|
||||
create_database legacy_retirement_credentialed
|
||||
run_db_alembic legacy_retirement_credentialed upgrade 0018_legacy_agent_routing
|
||||
psql_named legacy_retirement_credentialed <<'SQL'
|
||||
INSERT INTO minerops_site_agents (
|
||||
agent_id, site_name, agent_secret_hash,
|
||||
credential_created_at, credential_revoked_at
|
||||
) VALUES (
|
||||
'legacy-credentialed', 'Legacy', repeat('a', 64),
|
||||
now() - interval '1 hour', now()
|
||||
);
|
||||
SQL
|
||||
run_db_alembic legacy_retirement_credentialed upgrade head
|
||||
[[ "$(psql_named legacy_retirement_credentialed -Atc "SELECT legacy_auth_disabled_at = credential_created_at FROM minerops_site_agents WHERE agent_id='legacy-credentialed'")" == "t" ]]
|
||||
[[ "$(psql_named legacy_retirement_credentialed -Atc "SELECT retired_at = (SELECT credential_created_at FROM minerops_site_agents WHERE agent_id='legacy-credentialed') FROM agent_legacy_auth_retirements WHERE agent_id='legacy-credentialed'")" == "t" ]]
|
||||
|
||||
echo "Testing backfill from used enrollment history after credential clearing..."
|
||||
create_database legacy_retirement_enrollment
|
||||
run_db_alembic legacy_retirement_enrollment upgrade 0018_legacy_agent_routing
|
||||
psql_named legacy_retirement_enrollment <<'SQL'
|
||||
INSERT INTO sites (id, name)
|
||||
VALUES ('00000000-0000-4000-8000-000000001901', 'Enrollment Evidence');
|
||||
INSERT INTO agent_zones (id, site_id, name)
|
||||
VALUES (
|
||||
'00000000-0000-4000-8000-000000001902',
|
||||
'00000000-0000-4000-8000-000000001901',
|
||||
'Enrollment Evidence Zone'
|
||||
);
|
||||
INSERT INTO minerops_site_agents (
|
||||
agent_id, site_name, site_id, agent_zone_id
|
||||
) VALUES (
|
||||
'enrollment-evidence-cleared',
|
||||
'Enrollment Evidence',
|
||||
'00000000-0000-4000-8000-000000001901',
|
||||
'00000000-0000-4000-8000-000000001902'
|
||||
);
|
||||
INSERT INTO agent_enrollments (
|
||||
token_hash, site_id, agent_zone_id, display_name,
|
||||
created_at, expires_at, used_at, enrolled_agent_id
|
||||
) VALUES (
|
||||
repeat('c', 64),
|
||||
'00000000-0000-4000-8000-000000001901',
|
||||
'00000000-0000-4000-8000-000000001902',
|
||||
'Enrollment Evidence Agent',
|
||||
now() - interval '2 hours',
|
||||
now() + interval '1 hour',
|
||||
now() - interval '1 hour',
|
||||
'enrollment-evidence-cleared'
|
||||
);
|
||||
SQL
|
||||
run_db_alembic legacy_retirement_enrollment upgrade head
|
||||
[[ "$(psql_named legacy_retirement_enrollment -Atc "SELECT count(*) FROM agent_legacy_auth_retirements WHERE agent_id='enrollment-evidence-cleared'")" == "1" ]]
|
||||
[[ "$(psql_named legacy_retirement_enrollment -Atc "SELECT legacy_auth_disabled_at IS NOT NULL AND agent_secret_hash IS NULL AND credential_created_at IS NULL AND credential_revoked_at IS NULL FROM minerops_site_agents WHERE agent_id='enrollment-evidence-cleared'")" == "t" ]]
|
||||
|
||||
echo "Testing real PostgreSQL authentication before and after credential clearing..."
|
||||
run_contract legacy_retirement_uncredentialed legacy legacy-uncredentialed
|
||||
run_contract legacy_retirement_credentialed retired legacy-credentialed
|
||||
|
||||
echo "Testing database-enforced atomic retirement and ledger immutability..."
|
||||
psql_named legacy_retirement_credentialed -c \
|
||||
"INSERT INTO minerops_site_agents (agent_id, site_name, agent_secret_hash, credential_created_at) VALUES ('database-issued', 'Issued', repeat('b', 64), now())"
|
||||
[[ "$(psql_named legacy_retirement_credentialed -Atc "SELECT count(*) FROM agent_legacy_auth_retirements WHERE agent_id='database-issued'")" == "1" ]]
|
||||
[[ "$(psql_named legacy_retirement_credentialed -Atc "SELECT legacy_auth_disabled_at IS NOT NULL FROM minerops_site_agents WHERE agent_id='database-issued'")" == "t" ]]
|
||||
if psql_named legacy_retirement_credentialed -c \
|
||||
"UPDATE minerops_site_agents SET legacy_auth_disabled_at = NULL WHERE agent_id='legacy-credentialed'"; then
|
||||
echo "Permanent retirement marker was unexpectedly cleared" >&2
|
||||
exit 1
|
||||
fi
|
||||
if psql_named legacy_retirement_credentialed -c \
|
||||
"UPDATE agent_legacy_auth_retirements SET retired_at = now() WHERE agent_id='legacy-credentialed'"; then
|
||||
echo "Retirement history was unexpectedly updated" >&2
|
||||
exit 1
|
||||
fi
|
||||
if psql_named legacy_retirement_credentialed -c \
|
||||
"DELETE FROM agent_legacy_auth_retirements WHERE agent_id='legacy-credentialed'"; then
|
||||
echo "Retirement history was unexpectedly deleted" >&2
|
||||
exit 1
|
||||
fi
|
||||
if psql_named legacy_retirement_credentialed -c \
|
||||
"TRUNCATE agent_legacy_auth_retirements"; then
|
||||
echo "Retirement history was unexpectedly truncated" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Testing downgrade decision points..."
|
||||
run_db_alembic legacy_retirement_uncredentialed downgrade 0018_legacy_agent_routing
|
||||
[[ "$(psql_named legacy_retirement_uncredentialed -Atc 'SELECT version_num FROM alembic_version')" == "0018_legacy_agent_routing" ]]
|
||||
if output="$(run_db_alembic legacy_retirement_credentialed downgrade 0018_legacy_agent_routing 2>&1)"; then
|
||||
echo "0019 downgrade unexpectedly discarded retirement history" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"durable identity-level legacy-auth retirement history exists"* ]]
|
||||
[[ "$(psql_named legacy_retirement_credentialed -Atc 'SELECT version_num FROM alembic_version')" == "${expected_head}" ]]
|
||||
|
||||
echo "Durable legacy Agent authentication retirement checks passed."
|
||||
@@ -179,8 +179,9 @@ run_alembic upgrade 0016_agent_zones
|
||||
echo "Testing empty database through head..."
|
||||
"${compose[@]}" exec -T postgres sh -ec 'createdb -U "$POSTGRES_USER" minerops_agent_zones_empty'
|
||||
"${compose[@]}" run --rm --no-deps -e POSTGRES_DB=minerops_agent_zones_empty backend alembic upgrade head
|
||||
expected_head="$(run_alembic heads 2>/dev/null | awk 'NR == 1 { print $1 }')"
|
||||
empty_revision="$("${compose[@]}" exec -T postgres sh -ec \
|
||||
'psql -U "$POSTGRES_USER" -d minerops_agent_zones_empty -Atc "SELECT version_num FROM alembic_version"')"
|
||||
[[ "${empty_revision}" == "0016_agent_zones" ]]
|
||||
[[ -n "${expected_head}" && "${empty_revision}" == "${expected_head}" ]]
|
||||
|
||||
echo "Agent Zones migration lifecycle checks passed."
|
||||
@@ -132,7 +132,9 @@ health_json="$(cat "${health_file}")"
|
||||
|
||||
echo "Checking migrations and required schema..."
|
||||
current_revision="$("${compose[@]}" exec -T backend alembic current 2>/dev/null)"
|
||||
[[ "${current_revision}" == *"0017_agent_enrollment"* ]]
|
||||
expected_revision="$("${compose[@]}" exec -T backend alembic heads 2>/dev/null | awk 'NR == 1 { print $1 }')"
|
||||
[[ -n "${expected_revision}" ]]
|
||||
[[ "${current_revision}" == *"${expected_revision}"* ]]
|
||||
|
||||
missing_tables="$(
|
||||
"${compose[@]}" exec -T postgres sh -c \
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
project_name="${MINEROPS_LEGACY_HTTP_PROJECT:-minerops-legacy-http-$$}"
|
||||
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 160 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; }
|
||||
"${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 "Building a production-shaped 0014 database..."
|
||||
"${compose[@]}" run --rm --no-deps backend \
|
||||
alembic upgrade 0014_repair_parts_tracking
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'exec psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' <<'SQL'
|
||||
INSERT INTO sites (id, name) VALUES
|
||||
('00000000-0000-4000-8000-000000001a01', 'Plexus'),
|
||||
('00000000-0000-4000-8000-000000001a02', 'Contract Site B');
|
||||
INSERT INTO miners (
|
||||
id, site_id, asset_tag, current_ip, current_mac, status,
|
||||
first_seen_at, last_seen_at
|
||||
) VALUES
|
||||
(
|
||||
'00000000-0000-4000-8000-000000001a11',
|
||||
'00000000-0000-4000-8000-000000001a01',
|
||||
'LEGACY-HTTP-A', '192.0.2.201', '02:00:00:00:1a:11',
|
||||
'online', NULL, NULL
|
||||
),
|
||||
(
|
||||
'00000000-0000-4000-8000-000000001a12',
|
||||
'00000000-0000-4000-8000-000000001a02',
|
||||
'LEGACY-HTTP-B', '192.0.2.202', '02:00:00:00:1a:12',
|
||||
'online', NULL, NULL
|
||||
);
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name)
|
||||
VALUES ('legacy-plexus-http', ' plexus ');
|
||||
SQL
|
||||
"${compose[@]}" run --rm --no-deps backend alembic upgrade head
|
||||
|
||||
echo "Running real ASGI authentication and PostgreSQL routing checks..."
|
||||
"${compose[@]}" run --rm --no-deps \
|
||||
--volume "${repo_root}/backend/tests:/app/tests:ro" \
|
||||
--env MINEROPS_LEGACY_HTTP_POSTGRES_DISPOSABLE=1 \
|
||||
--env MINEROPS_AGENT_ID=legacy-plexus-http \
|
||||
--env MINEROPS_AGENT_SHARED_SECRET=legacy-http-contract-secret \
|
||||
backend python -m unittest -v \
|
||||
tests.test_legacy_agent_http_postgres
|
||||
|
||||
echo "Full-stack legacy Agent HTTP/PostgreSQL contract passed."
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
project_name="${MINEROPS_LEGACY_PRODUCTION_PROJECT:-minerops-legacy-production-$$}"
|
||||
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 160 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; }
|
||||
"${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 "Building the production-shaped database from the 0014 baseline..."
|
||||
"${compose[@]}" run --rm --no-deps backend \
|
||||
alembic upgrade 0014_repair_parts_tracking
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'exec psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' <<'SQL'
|
||||
INSERT INTO sites (id, name) VALUES
|
||||
('00000000-0000-4000-8000-000000001901', 'Plexus'),
|
||||
('00000000-0000-4000-8000-000000001902', 'Contract Site B');
|
||||
INSERT INTO miners (
|
||||
id, site_id, asset_tag, current_ip, current_mac, status,
|
||||
first_seen_at, last_seen_at
|
||||
) VALUES
|
||||
(
|
||||
'00000000-0000-4000-8000-000000001911',
|
||||
'00000000-0000-4000-8000-000000001901',
|
||||
'LEGACY-CONTRACT-A', '192.0.2.191', '02:00:00:00:19:11',
|
||||
'online', NULL, NULL
|
||||
),
|
||||
(
|
||||
'00000000-0000-4000-8000-000000001912',
|
||||
'00000000-0000-4000-8000-000000001902',
|
||||
'LEGACY-CONTRACT-B', '192.0.2.192', '02:00:00:00:19:12',
|
||||
'online', NULL, NULL
|
||||
);
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name)
|
||||
VALUES ('legacy-plexus-production', ' plexus ');
|
||||
SQL
|
||||
"${compose[@]}" run --rm --no-deps backend alembic upgrade head
|
||||
|
||||
echo "Running legacy authentication, routing, and inert telemetry contract..."
|
||||
"${compose[@]}" run --rm --no-deps \
|
||||
--volume "${repo_root}/backend/tests:/app/tests:ro" \
|
||||
--env MINEROPS_LEGACY_PRODUCTION_DISPOSABLE=1 \
|
||||
--env MINEROPS_AGENT_ID=legacy-plexus-production \
|
||||
--env MINEROPS_AGENT_SHARED_SECRET=legacy-production-contract-secret \
|
||||
backend python -m unittest -v \
|
||||
tests.test_legacy_agent_production_postgres
|
||||
|
||||
echo "Legacy production compatibility contract passed."
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
project_name="${MINEROPS_LEGACY_ROUTING_PROJECT:-minerops-legacy-routing-$$}"
|
||||
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 160 postgres || true
|
||||
fi
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
exit "${status}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
run_db_alembic() {
|
||||
local database="$1"
|
||||
shift
|
||||
"${compose[@]}" run --rm --no-deps -e POSTGRES_DB="${database}" backend alembic "$@"
|
||||
}
|
||||
psql_named() {
|
||||
local database="$1"
|
||||
shift
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'database="$1"; shift; exec psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$database" "$@"' \
|
||||
sh "${database}" "$@"
|
||||
}
|
||||
create_database() {
|
||||
"${compose[@]}" exec -T postgres sh -ec \
|
||||
'exec createdb -U "$POSTGRES_USER" "$1"' sh "$1"
|
||||
}
|
||||
|
||||
[[ -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
|
||||
expected_revision="0018_legacy_agent_routing"
|
||||
|
||||
echo "Testing the real single-Site production shape from 0014 -> 0018..."
|
||||
create_database legacy_routing_happy
|
||||
run_db_alembic legacy_routing_happy upgrade 0014_repair_parts_tracking
|
||||
psql_named legacy_routing_happy <<'SQL'
|
||||
DELETE FROM sites;
|
||||
INSERT INTO sites (id, name)
|
||||
VALUES (
|
||||
'191e6d8f-ce40-4488-a8f1-ad6ce1790266',
|
||||
'Plexus Mining Site'
|
||||
);
|
||||
INSERT INTO miners (id, site_id, asset_tag, first_seen_at, last_seen_at, current_mac)
|
||||
VALUES (
|
||||
'00000000-0000-4000-8000-000000001811',
|
||||
'191e6d8f-ce40-4488-a8f1-ad6ce1790266',
|
||||
'LEGACY-ROUTING-MINER', NULL, NULL, '02:00:00:00:18:11'
|
||||
);
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name)
|
||||
VALUES ('plexus-windows-agent', 'Plexus');
|
||||
INSERT INTO minerops_agent_snapshots (agent_id, site_name, miner_count, payload)
|
||||
VALUES ('plexus-windows-agent', 'Plexus', 1, '{}');
|
||||
INSERT INTO minerops_agent_discoveries (
|
||||
id, agent_id, site_name, ip_address, raw_payload, discovery_status
|
||||
) VALUES (
|
||||
'legacy-routing-discovery', 'plexus-windows-agent', 'Plexus',
|
||||
'192.0.2.181', '{}', 'new'
|
||||
);
|
||||
SQL
|
||||
run_db_alembic legacy_routing_happy upgrade "${expected_revision}"
|
||||
[[ "$(psql_named legacy_routing_happy -Atc 'SELECT version_num FROM alembic_version')" == "${expected_revision}" ]]
|
||||
psql_named legacy_routing_happy <<'SQL'
|
||||
DO $$
|
||||
DECLARE
|
||||
expected_site uuid := '191e6d8f-ce40-4488-a8f1-ad6ce1790266';
|
||||
expected_zone uuid;
|
||||
BEGIN
|
||||
SELECT id INTO expected_zone FROM agent_zones
|
||||
WHERE site_id = expected_site AND lower(name) = 'default zone' AND is_enabled;
|
||||
IF expected_zone IS NULL THEN
|
||||
RAISE EXCEPTION 'Expected enabled Default Zone is missing';
|
||||
END IF;
|
||||
IF (SELECT site_id FROM minerops_site_agents
|
||||
WHERE agent_id = 'plexus-windows-agent')
|
||||
IS DISTINCT FROM expected_site THEN
|
||||
RAISE EXCEPTION 'Sole-Site legacy Agent resolution failed';
|
||||
END IF;
|
||||
IF (SELECT agent_zone_id FROM minerops_site_agents
|
||||
WHERE agent_id = 'plexus-windows-agent')
|
||||
IS DISTINCT FROM expected_zone THEN
|
||||
RAISE EXCEPTION 'Legacy Agent Zone routing failed';
|
||||
END IF;
|
||||
IF (SELECT agent_zone_id FROM miners
|
||||
WHERE id = '00000000-0000-4000-8000-000000001811')
|
||||
IS DISTINCT FROM expected_zone THEN
|
||||
RAISE EXCEPTION 'Existing miner ownership was not preserved in its Site default Zone';
|
||||
END IF;
|
||||
IF (SELECT current_mac FROM miners
|
||||
WHERE id = '00000000-0000-4000-8000-000000001811')
|
||||
IS DISTINCT FROM '02:00:00:00:18:11' THEN
|
||||
RAISE EXCEPTION 'Miner identity/history projection was rewritten';
|
||||
END IF;
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM minerops_agent_snapshots
|
||||
WHERE agent_id = 'plexus-windows-agent'
|
||||
AND agent_zone_id IS DISTINCT FROM expected_zone
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Legacy snapshots were not attributed to the Agent Zone';
|
||||
END IF;
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM minerops_agent_discoveries
|
||||
WHERE agent_id = 'plexus-windows-agent'
|
||||
AND agent_zone_id IS DISTINCT FROM expected_zone
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Legacy discoveries were not attributed to the Agent Zone';
|
||||
END IF;
|
||||
END $$;
|
||||
SQL
|
||||
|
||||
echo "Testing unmatched multi-Site data fails closed before routing writes..."
|
||||
create_database legacy_routing_missing
|
||||
run_db_alembic legacy_routing_missing upgrade 0014_repair_parts_tracking
|
||||
psql_named legacy_routing_missing <<'SQL'
|
||||
DELETE FROM sites;
|
||||
INSERT INTO sites (id, name) VALUES
|
||||
('00000000-0000-4000-8000-000000001801', 'Candidate Site A'),
|
||||
('00000000-0000-4000-8000-000000001802', 'Candidate Site B');
|
||||
SQL
|
||||
psql_named legacy_routing_missing -c \
|
||||
"INSERT INTO minerops_site_agents (agent_id, site_name) VALUES ('missing-agent', 'No Such Site')"
|
||||
run_db_alembic legacy_routing_missing upgrade 0017_agent_enrollment
|
||||
if output="$(run_db_alembic legacy_routing_missing upgrade "${expected_revision}" 2>&1)"; then
|
||||
echo "Missing Site match unexpectedly passed" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"unmatched multi-Site installations fail closed"* ]]
|
||||
[[ "${output}" == *"missing-agent"* && "${output}" == *"/'0'/'2'"* ]]
|
||||
[[ "$(psql_named legacy_routing_missing -Atc 'SELECT version_num FROM alembic_version')" == "0017_agent_enrollment" ]]
|
||||
[[ "$(psql_named legacy_routing_missing -Atc "SELECT site_id IS NULL FROM minerops_site_agents WHERE agent_id='missing-agent'")" == "t" ]]
|
||||
[[ "$(psql_named legacy_routing_missing -Atc "SELECT agent_zone_id IS NULL FROM minerops_site_agents WHERE agent_id='missing-agent'")" == "t" ]]
|
||||
|
||||
echo "Testing ambiguous normalized Site match fails closed..."
|
||||
create_database legacy_routing_ambiguous
|
||||
run_db_alembic legacy_routing_ambiguous upgrade 0014_repair_parts_tracking
|
||||
psql_named legacy_routing_ambiguous <<'SQL'
|
||||
DELETE FROM sites;
|
||||
INSERT INTO sites (id, name) VALUES
|
||||
('00000000-0000-4000-8000-000000001821', 'Ambiguous Site'),
|
||||
('00000000-0000-4000-8000-000000001822', 'ambiguous site');
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name)
|
||||
VALUES ('ambiguous-agent', ' AMBIGUOUS SITE ');
|
||||
SQL
|
||||
run_db_alembic legacy_routing_ambiguous upgrade 0017_agent_enrollment
|
||||
if output="$(run_db_alembic legacy_routing_ambiguous upgrade "${expected_revision}" 2>&1)"; then
|
||||
echo "Ambiguous Site match unexpectedly passed" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"ambiguous-agent"* && "${output}" == *"/'2'"* ]]
|
||||
[[ "$(psql_named legacy_routing_ambiguous -Atc 'SELECT version_num FROM alembic_version')" == "0017_agent_enrollment" ]]
|
||||
[[ "$(psql_named legacy_routing_ambiguous -Atc "SELECT site_id IS NULL AND agent_zone_id IS NULL FROM minerops_site_agents WHERE agent_id='ambiguous-agent'")" == "t" ]]
|
||||
|
||||
echo "Testing an exact normalized match wins in a multi-Site database..."
|
||||
create_database legacy_routing_exact_multi
|
||||
run_db_alembic legacy_routing_exact_multi upgrade 0014_repair_parts_tracking
|
||||
psql_named legacy_routing_exact_multi <<'SQL'
|
||||
DELETE FROM sites;
|
||||
INSERT INTO sites (id, name) VALUES
|
||||
('00000000-0000-4000-8000-000000001825', 'Exact Site'),
|
||||
('00000000-0000-4000-8000-000000001826', 'Unrelated Site');
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name)
|
||||
VALUES ('exact-multi-agent', ' eXaCt SiTe ');
|
||||
SQL
|
||||
run_db_alembic legacy_routing_exact_multi upgrade 0017_agent_enrollment
|
||||
run_db_alembic legacy_routing_exact_multi upgrade "${expected_revision}"
|
||||
[[ "$(psql_named legacy_routing_exact_multi -Atc "SELECT site_id FROM minerops_site_agents WHERE agent_id='exact-multi-agent'")" == "00000000-0000-4000-8000-000000001825" ]]
|
||||
[[ "$(psql_named legacy_routing_exact_multi -Atc "SELECT agent.agent_zone_id = zone.id FROM minerops_site_agents AS agent JOIN agent_zones AS zone ON zone.site_id=agent.site_id AND zone.name='Default Zone' WHERE agent.agent_id='exact-multi-agent'")" == "t" ]]
|
||||
|
||||
echo "Testing two legacy Agents targeting one Default Zone fails closed..."
|
||||
create_database legacy_routing_conflict
|
||||
run_db_alembic legacy_routing_conflict upgrade 0014_repair_parts_tracking
|
||||
psql_named legacy_routing_conflict <<'SQL'
|
||||
DELETE FROM sites;
|
||||
INSERT INTO sites (id, name)
|
||||
VALUES ('00000000-0000-4000-8000-000000001831', 'Sole Durable Site');
|
||||
INSERT INTO minerops_site_agents (agent_id, site_name) VALUES
|
||||
('conflict-agent-a', 'Legacy Display A'),
|
||||
('conflict-agent-b', 'Legacy Display B');
|
||||
SQL
|
||||
run_db_alembic legacy_routing_conflict upgrade 0017_agent_enrollment
|
||||
if output="$(run_db_alembic legacy_routing_conflict upgrade "${expected_revision}" 2>&1)"; then
|
||||
echo "One-Agent-per-Zone conflict unexpectedly passed" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"one-Agent-per-Zone would be violated"* ]]
|
||||
[[ "$(psql_named legacy_routing_conflict -Atc 'SELECT version_num FROM alembic_version')" == "0017_agent_enrollment" ]]
|
||||
[[ "$(psql_named legacy_routing_conflict -Atc 'SELECT count(*) FROM minerops_site_agents WHERE site_id IS NOT NULL')" == "0" ]]
|
||||
[[ "$(psql_named legacy_routing_conflict -Atc 'SELECT count(*) FROM minerops_site_agents WHERE agent_zone_id IS NOT NULL')" == "0" ]]
|
||||
|
||||
echo "Testing explicit Site and Zone assignments win..."
|
||||
create_database legacy_routing_explicit
|
||||
run_db_alembic legacy_routing_explicit upgrade 0017_agent_enrollment
|
||||
psql_named legacy_routing_explicit <<'SQL'
|
||||
INSERT INTO sites (id, name)
|
||||
VALUES ('00000000-0000-4000-8000-000000001841', 'Explicit Site');
|
||||
INSERT INTO agent_zones (
|
||||
id, site_id, name
|
||||
) VALUES (
|
||||
'00000000-0000-4000-8000-000000001842',
|
||||
'00000000-0000-4000-8000-000000001841',
|
||||
'Explicit Zone'
|
||||
);
|
||||
INSERT INTO minerops_site_agents (
|
||||
agent_id, site_id, agent_zone_id, site_name
|
||||
) VALUES (
|
||||
'explicit-agent',
|
||||
'00000000-0000-4000-8000-000000001841',
|
||||
'00000000-0000-4000-8000-000000001842',
|
||||
'A Different Display Name'
|
||||
);
|
||||
SQL
|
||||
run_db_alembic legacy_routing_explicit upgrade "${expected_revision}"
|
||||
[[ "$(psql_named legacy_routing_explicit -Atc "SELECT site_id || '/' || agent_zone_id FROM minerops_site_agents WHERE agent_id='explicit-agent'")" == "00000000-0000-4000-8000-000000001841/00000000-0000-4000-8000-000000001842" ]]
|
||||
|
||||
echo "Testing conservative downgrade refusal..."
|
||||
if output="$(run_db_alembic legacy_routing_happy downgrade 0017_agent_enrollment 2>&1)"; then
|
||||
echo "0018 downgrade unexpectedly discarded routing attribution" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ "${output}" == *"Restore the pre-upgrade database backup"* ]]
|
||||
[[ "$(psql_named legacy_routing_happy -Atc 'SELECT version_num FROM alembic_version')" == "${expected_revision}" ]]
|
||||
|
||||
echo "Legacy Agent routing migration lifecycle checks passed."
|
||||
@@ -130,8 +130,9 @@ 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
|
||||
expected_head="$(run_alembic heads 2>/dev/null | awk 'NR == 1 { print $1 }')"
|
||||
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" ]]
|
||||
[[ -n "${expected_head}" && "${empty_revision}" == "${expected_head}" ]]
|
||||
|
||||
echo "Miner Control Foundation migration tests passed."
|
||||
Reference in new issue
Block a user