mirror of
https://github.com/Such-Software/adaptive-multi-protocol-gateway.git
synced 2026-10-17 07:31:32 +02:00
Model transport provider sources
This commit is contained in:
@@ -1634,6 +1634,7 @@ def _print_transport_status(status: TransportStatus) -> None:
|
||||
f"supervisor={status.supervisor} "
|
||||
f"adapter={status.adapter} "
|
||||
f"backend={status.backend} "
|
||||
f"provider_source={status.provider_source} "
|
||||
f"installed={_bool(status.installed)} "
|
||||
f"running={_bool(status.running)} "
|
||||
f"adoptable={_bool(status.adoptable)} "
|
||||
|
||||
@@ -73,6 +73,10 @@ def _daemon_adapters_doc() -> str:
|
||||
sections.append(f"- Protocols: {', '.join(adapter.protocols)}")
|
||||
sections.append(f"- Default policy: `{adapter.default_policy}`")
|
||||
sections.append(f"- Generated artifacts: {', '.join(adapter.generated_artifacts)}")
|
||||
sections.append(
|
||||
"- Provider sources: "
|
||||
+ (", ".join(f"`{source}`" for source in adapter.provider_sources) or "-")
|
||||
)
|
||||
sections.append("")
|
||||
sections.append("Notes:")
|
||||
for note in adapter.notes:
|
||||
|
||||
@@ -31,6 +31,7 @@ class DaemonAdapter:
|
||||
default_policy: str
|
||||
generated_artifacts: tuple[str, ...]
|
||||
notes: tuple[str, ...]
|
||||
provider_sources: tuple[str, ...] = ()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -512,6 +513,7 @@ DAEMON_ADAPTERS = (
|
||||
"Clearnet defaults to adopt because TLS and public vhost policy are operator-owned.",
|
||||
"Tor/I2P HTTP targets can use loopback-only server blocks.",
|
||||
),
|
||||
provider_sources=("configured", "system-adopted", "system-managed", "platform-package"),
|
||||
),
|
||||
DaemonAdapter(
|
||||
daemon=DEFAULT_DAEMONS["tor"],
|
||||
@@ -522,6 +524,7 @@ DAEMON_ADAPTERS = (
|
||||
"AMPG should preserve existing HiddenServiceDir material when adopting.",
|
||||
"Managed hidden-service keys belong under AMPG state.",
|
||||
),
|
||||
provider_sources=("configured", "bundled-sidecar", "system-adopted", "system-managed", "platform-package"),
|
||||
),
|
||||
DaemonAdapter(
|
||||
daemon=DEFAULT_DAEMONS["i2p"],
|
||||
@@ -532,6 +535,7 @@ DAEMON_ADAPTERS = (
|
||||
"Web tunnels should use web-specific key files.",
|
||||
"Existing RPC/P2P tunnel keys are not reused for web publishing.",
|
||||
),
|
||||
provider_sources=("configured", "bundled-sidecar", "system-adopted", "system-managed", "platform-package"),
|
||||
),
|
||||
DaemonAdapter(
|
||||
daemon=DEFAULT_DAEMONS["gemini"],
|
||||
@@ -542,6 +546,7 @@ DAEMON_ADAPTERS = (
|
||||
"Gemini serves generated Gemtext output directly.",
|
||||
"Certificate and key paths are plan values until install/apply support exists.",
|
||||
),
|
||||
provider_sources=("configured", "bundled-sidecar", "system-adopted", "system-managed", "platform-package"),
|
||||
),
|
||||
DaemonAdapter(
|
||||
daemon=DEFAULT_DAEMONS["ipfs"],
|
||||
@@ -552,6 +557,7 @@ DAEMON_ADAPTERS = (
|
||||
"IPFS output is static web content for a local gateway or later pinning.",
|
||||
"IPFS is content-addressed distribution, not an anonymity layer.",
|
||||
),
|
||||
provider_sources=("configured", "bundled-sidecar", "system-adopted", "system-managed", "platform-package"),
|
||||
),
|
||||
DaemonAdapter(
|
||||
daemon=DEFAULT_DAEMONS["reticulum"],
|
||||
@@ -563,5 +569,13 @@ DAEMON_ADAPTERS = (
|
||||
"Reticulum is resilient/private routing, not an anonymity layer.",
|
||||
"Physical interfaces may require explicit operator setup.",
|
||||
),
|
||||
provider_sources=(
|
||||
"configured",
|
||||
"bundled-sidecar",
|
||||
"system-adopted",
|
||||
"system-managed",
|
||||
"platform-package",
|
||||
"operator-interface",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -40,6 +40,7 @@ class TransportStatus:
|
||||
supervisor: str
|
||||
adapter: str
|
||||
backend: str
|
||||
provider_source: str
|
||||
installed: bool
|
||||
running: bool
|
||||
adoptable: bool
|
||||
@@ -265,6 +266,11 @@ def _transport_status(
|
||||
supervisor=provider.process_supervisor,
|
||||
adapter=f"{adapter.protocol}/{adapter.daemon}",
|
||||
backend=adapter.backend,
|
||||
provider_source=_provider_source_for_status(
|
||||
action=action,
|
||||
installed=daemon.installed,
|
||||
executable_path=daemon.executable_path,
|
||||
),
|
||||
installed=daemon.installed,
|
||||
running=daemon.running,
|
||||
adoptable=adoptable,
|
||||
@@ -276,6 +282,18 @@ def _transport_status(
|
||||
)
|
||||
|
||||
|
||||
def _provider_source_for_status(*, action: str, installed: bool, executable_path: str | None) -> str:
|
||||
if action == "adopt-existing":
|
||||
return "system-adopted"
|
||||
if action == "manage-owned":
|
||||
if installed or executable_path:
|
||||
return "system-managed"
|
||||
return "platform-package"
|
||||
if action == "render-only":
|
||||
return "external"
|
||||
return "unavailable"
|
||||
|
||||
|
||||
def _process_running(executable: str) -> bool:
|
||||
pgrep = shutil.which("pgrep")
|
||||
if not pgrep:
|
||||
|
||||
@@ -3,6 +3,14 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ProviderSource:
|
||||
kind: str
|
||||
discovery: str
|
||||
lifecycle: str
|
||||
notes: tuple[str, ...] = ()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TransportAdapter:
|
||||
protocol: str
|
||||
@@ -13,9 +21,48 @@ class TransportAdapter:
|
||||
managed_supported: bool
|
||||
default_ports: tuple[int, ...] = ()
|
||||
generated_artifacts: tuple[str, ...] = ()
|
||||
provider_sources: tuple[ProviderSource, ...] = ()
|
||||
notes: tuple[str, ...] = ()
|
||||
|
||||
|
||||
COMMON_SERVICE_PROVIDER_SOURCES = (
|
||||
ProviderSource(
|
||||
kind="configured",
|
||||
discovery="explicit daemon config and approved generated snippets",
|
||||
lifecycle="operator-owned unless daemon_policy selects manage",
|
||||
notes=("Explicit config always wins over automatic discovery.",),
|
||||
),
|
||||
ProviderSource(
|
||||
kind="system-adopted",
|
||||
discovery="running system daemon, service, or listen endpoint",
|
||||
lifecycle="operator-owned; AMPG may generate snippets but does not own the service",
|
||||
notes=("Used when daemon_policy is adopt or auto with a healthy daemon.",),
|
||||
),
|
||||
ProviderSource(
|
||||
kind="system-managed",
|
||||
discovery="installed daemon binary on the selected platform",
|
||||
lifecycle="AMPG-owned state and AMPG-named supervisor entry",
|
||||
notes=("Used when daemon_policy is manage or auto and the platform can supervise it.",),
|
||||
),
|
||||
ProviderSource(
|
||||
kind="platform-package",
|
||||
discovery="allowlisted package backend such as apt, brew, or pkg",
|
||||
lifecycle="installed only through reviewed deploy apply package stage",
|
||||
notes=("Package install is separate from state, supervisor, start, address, and health stages.",),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
USERSPACE_PROVIDER_SOURCES = COMMON_SERVICE_PROVIDER_SOURCES + (
|
||||
ProviderSource(
|
||||
kind="bundled-sidecar",
|
||||
discovery="AMPG package or app resource provider directory",
|
||||
lifecycle="AMPG-owned process and state",
|
||||
notes=("Useful for old laptops, single-purpose boxes, and mobile-server shells.",),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
TRANSPORT_ADAPTERS = (
|
||||
TransportAdapter(
|
||||
protocol="clearnet",
|
||||
@@ -26,6 +73,7 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=True,
|
||||
default_ports=(80, 443),
|
||||
generated_artifacts=("nginx server block snippet",),
|
||||
provider_sources=COMMON_SERVICE_PROVIDER_SOURCES,
|
||||
notes=(
|
||||
"Clearnet ingress is usually adopted because TLS and public vhost policy are operator-owned.",
|
||||
),
|
||||
@@ -39,6 +87,7 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=True,
|
||||
default_ports=(18080,),
|
||||
generated_artifacts=("torrc hidden-service snippet", "loopback HTTP server block"),
|
||||
provider_sources=USERSPACE_PROVIDER_SOURCES,
|
||||
notes=(
|
||||
"Adopted Tor keeps existing HiddenServiceDir material.",
|
||||
"Managed Tor stores onion service keys under AMPG state.",
|
||||
@@ -53,6 +102,18 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=False,
|
||||
default_ports=(18080,),
|
||||
generated_artifacts=("future Arti onion-service config",),
|
||||
provider_sources=(
|
||||
ProviderSource(
|
||||
kind="bundled-sidecar",
|
||||
discovery="AMPG package or app resource provider directory",
|
||||
lifecycle="future AMPG-owned Arti onion-service process",
|
||||
),
|
||||
ProviderSource(
|
||||
kind="configured",
|
||||
discovery="explicit arti binary path and onion-service config",
|
||||
lifecycle="future AMPG-owned or operator-owned by policy",
|
||||
),
|
||||
),
|
||||
notes=("Modeled as a future backend until the AMPG Arti adapter is implemented.",),
|
||||
),
|
||||
TransportAdapter(
|
||||
@@ -64,6 +125,7 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=True,
|
||||
default_ports=(18081,),
|
||||
generated_artifacts=("i2pd server tunnel snippet", "loopback HTTP server block"),
|
||||
provider_sources=USERSPACE_PROVIDER_SOURCES,
|
||||
notes=("Destination keys are transport identity material and must be preserved.",),
|
||||
),
|
||||
TransportAdapter(
|
||||
@@ -75,6 +137,7 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=True,
|
||||
default_ports=(1965,),
|
||||
generated_artifacts=("Agate plan values",),
|
||||
provider_sources=USERSPACE_PROVIDER_SOURCES,
|
||||
notes=("Gemini serves generated Gemtext output directly.",),
|
||||
),
|
||||
TransportAdapter(
|
||||
@@ -86,6 +149,7 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=True,
|
||||
default_ports=(5001, 8080),
|
||||
generated_artifacts=("pin/add plan",),
|
||||
provider_sources=USERSPACE_PROVIDER_SOURCES,
|
||||
notes=("IPFS is content-addressed distribution, not an anonymity layer.",),
|
||||
),
|
||||
TransportAdapter(
|
||||
@@ -97,6 +161,15 @@ TRANSPORT_ADAPTERS = (
|
||||
managed_supported=True,
|
||||
default_ports=(),
|
||||
generated_artifacts=("Reticulum page-service plan",),
|
||||
provider_sources=USERSPACE_PROVIDER_SOURCES
|
||||
+ (
|
||||
ProviderSource(
|
||||
kind="operator-interface",
|
||||
discovery="explicit Reticulum interface configuration",
|
||||
lifecycle="operator-owned physical or link-layer interface",
|
||||
notes=("AMPG can manage page serving while interface setup may remain manual.",),
|
||||
),
|
||||
),
|
||||
notes=(
|
||||
"Reticulum is resilient/private routing, not an anonymity layer.",
|
||||
"Physical interfaces may require operator setup outside AMPG.",
|
||||
|
||||
Reference in New Issue
Block a user