security(discovery): enforce Zone isolation and retire unsafe legacy writers

Bind Agent observations, review, enrichment and telemetry to current Zone
and inventory authority. Preserve immutable MAC ownership and historical
snapshots with stale-result rejection and transactional security audits.

Retire unbound direct/range/scheduled discovery and one/bulk legacy summary
writes in both modes. Require reconciled exact inventory identity or
explicit Zone-scoped IP selection for CSV metadata imports.

Independent Blocker #1 application-security re-audit: PASS on tree
cf863aadc9. Evidence: 141 focused PostgreSQL/HTTP
tests passed; Chromium and PowerShell checks passed. Two documented baseline
source assertions remain unchanged. Production deployment is not approved.
This commit is contained in:
lussierj committed 2026-10-17 00:45:04 +00:00
1 parent e898f283ab
commit 8b0d32cd6b
26 files changed
+3798 -4092

No files matched your search

+27
View File
@@ -10,6 +10,7 @@ from app.agent_zones.exceptions import (
from app.agent_zones.models import (
AgentCheckinRequest,
AgentCheckinResponse,
AgentDiscoveryMinerMatch,
AgentZoneRoutingContext,
AgentZoneCreateRequest,
AgentZoneSummary,
@@ -81,6 +82,8 @@ class AgentZoneService:
self.validate_agent_identity(authenticated_agent_id, request.agent_id)
existing = self.repository.get_agent(authenticated_agent_id)
if not existing or existing.get("agent_zone_id") is None:
raise AgentZoneValidationError("Agent requires an administrator-established Zone assignment")
requested_site = request.site_id
requested_zone = request.agent_zone_id
final_site = requested_site or (existing or {}).get("site_id")
@@ -199,6 +202,30 @@ class AgentZoneService:
],
}
def match_discovered_miner(
self,
agent_id: str,
*,
mac_address: str | None,
ip_address: str | None,
recorded_zone_id: UUID | None = None,
) -> AgentDiscoveryMinerMatch:
routing = self.routing_context(agent_id, recorded_zone_id)
if routing.routing_reason or routing.agent_zone_id is None:
return AgentDiscoveryMinerMatch(**routing.model_dump())
match = self.repository.find_miner_in_zone(
agent_id=agent_id,
agent_zone_id=routing.agent_zone_id,
mac_address=mac_address,
ip_address=ip_address,
)
return AgentDiscoveryMinerMatch(
**routing.model_dump(),
miner_id=match["id"] if match else None,
matched_by=match["matched_by"] if match else None,
)
def associate_miners_from_agent(
self, agent_id: str, miner_ids: list[UUID]
) -> MinerZoneAssociationResult: