Files
DECNET/decnet/orchestrator/drivers/__init__.py
anti 6a8af315fb fix(core): close HIGH ASVS findings V7.1.1 and correctness bugs BUG-1..6
- V7.1.1: /swarm/check no longer returns raw exception text; logs detail
  server-side, returns generic 'probe failed'.
- BUG-1: register EditAction -> SSHDriver so edit ticks no longer crash.
- BUG-2: topology reconcile matches generator-named deckies by
  expected-name membership instead of a hyphen heuristic.
- BUG-3: intel provider lookups acquire the per-provider semaphore so
  declared concurrency bounds are enforced.
- BUG-4: RuleIndex.install evicts a rule from kinds it no longer applies to.
- BUG-5: UnixSocketBus.connect() is lock-guarded with a double-check so
  concurrent first-connects open exactly one socket and reader task.
- BUG-6/V5.1.3: multi-token JSON-field search binds each token to a
  distinct parameter instead of collapsing to the last value.

Regression tests added for every fix, verified red-before/green-after.
V4.1.1c/V12.1.1 (updater master-CN gate) and V12.5.1 (tarball include-list)
confirmed already fixed in prior commits and left untouched.
2026-06-09 23:12:49 -04:00

76 lines
2.8 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""Activity drivers for the orchestrator.
Concrete drivers register dispatch in :func:`get_driver_for`. Same
lazy-import pattern as :mod:`decnet.canary.factory`: the import-time
cost of :mod:`decnet.orchestrator.drivers` stays low for callers that
only need :class:`ActivityResult` / :class:`ActivityDriver`.
"""
from __future__ import annotations
from decnet.orchestrator.drivers.base import (
ActivityDriver,
ActivityResult,
Driver,
)
from decnet.orchestrator.scheduler import Action, EditAction, FileAction, TrafficAction
__all__ = [
"ActivityDriver",
"ActivityResult",
"Driver",
"SSHDriver",
"get_driver_for",
]
def __getattr__(name: str): # pragma: no cover - import passthrough
"""Lazy access to concrete drivers.
Avoids dragging the docker-exec / email-driver code into every
consumer that only needs the ABC.
"""
if name == "SSHDriver":
from decnet.orchestrator.drivers.ssh import SSHDriver
return SSHDriver
if name == "EmailDriver":
from decnet.orchestrator.drivers.email import EmailDriver
return EmailDriver
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
def get_driver_for(action: Action) -> ActivityDriver:
"""Return the concrete driver that handles *action*.
Stage 4 of the realism migration adds this seam so the orchestrator
worker can dispatch by action type without an isinstance chain in
``_one_tick``. Stage 5 wires the worker to call this function
instead of holding a single ``SSHDriver`` instance.
The set of action shapes the orchestrator can plan grows with the
migration:
* :class:`TrafficAction` / :class:`FileAction` → :class:`SSHDriver`
* :class:`EmailAction` (post-stage-5) → ``EmailDriver``
* :class:`EditAction` (post-stage-3b) → :class:`SSHDriver`
"""
# Lazy imports keep the side-effecting docker-exec / email-driver
# modules out of every importer's graph.
from decnet.orchestrator.drivers.ssh import SSHDriver
if isinstance(action, (TrafficAction, FileAction, EditAction)):
return SSHDriver()
# EmailAction lands in stage 5; reachable only after that import is
# added to scheduler. Importing inside the branch avoids a cycle
# with realism.llm at module load time.
try:
from decnet.orchestrator.emailgen.scheduler import EmailAction
except ImportError: # pragma: no cover - scheduler always exists
EmailAction = None # type: ignore[misc]
if EmailAction is not None and isinstance(action, EmailAction):
from decnet.orchestrator.drivers.email import EmailDriver
return EmailDriver()
raise TypeError(
f"no driver registered for action type {type(action).__name__}"
)