mirror of
https://github.com/Such-Software/adaptive-multi-protocol-gateway.git
synced 2026-10-17 15:41:41 +02:00
199 lines
6.7 KiB
Python
199 lines
6.7 KiB
Python
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
|
|
daemon: str
|
|
executable: str
|
|
backend: str
|
|
adopt_supported: bool
|
|
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",
|
|
daemon="nginx",
|
|
executable="nginx",
|
|
backend="http",
|
|
adopt_supported=True,
|
|
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.",
|
|
),
|
|
),
|
|
TransportAdapter(
|
|
protocol="tor",
|
|
daemon="tor",
|
|
executable="tor",
|
|
backend="hidden-service",
|
|
adopt_supported=True,
|
|
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.",
|
|
),
|
|
),
|
|
TransportAdapter(
|
|
protocol="tor",
|
|
daemon="arti",
|
|
executable="arti",
|
|
backend="hidden-service",
|
|
adopt_supported=False,
|
|
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(
|
|
protocol="i2p",
|
|
daemon="i2pd",
|
|
executable="i2pd",
|
|
backend="server-tunnel",
|
|
adopt_supported=True,
|
|
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(
|
|
protocol="gemini",
|
|
daemon="agate",
|
|
executable="agate",
|
|
backend="gemini-server",
|
|
adopt_supported=True,
|
|
managed_supported=True,
|
|
default_ports=(1965,),
|
|
generated_artifacts=("Agate plan values",),
|
|
provider_sources=USERSPACE_PROVIDER_SOURCES,
|
|
notes=("Gemini serves generated Gemtext output directly.",),
|
|
),
|
|
TransportAdapter(
|
|
protocol="ipfs",
|
|
daemon="ipfs",
|
|
executable="ipfs",
|
|
backend="content-addressed",
|
|
adopt_supported=True,
|
|
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(
|
|
protocol="reticulum",
|
|
daemon="rnsd",
|
|
executable="rnsd",
|
|
backend="reticulum-page-service",
|
|
adopt_supported=True,
|
|
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.",
|
|
),
|
|
),
|
|
)
|
|
|
|
|
|
def transport_adapter(protocol: str, daemon: str) -> TransportAdapter | None:
|
|
for adapter in TRANSPORT_ADAPTERS:
|
|
if adapter.protocol == protocol and adapter.daemon == daemon:
|
|
return adapter
|
|
return None
|
|
|
|
|
|
def fallback_transport_adapter(protocol: str, daemon: str) -> TransportAdapter:
|
|
return TransportAdapter(
|
|
protocol=protocol,
|
|
daemon=daemon,
|
|
executable=daemon,
|
|
backend="unknown",
|
|
adopt_supported=False,
|
|
managed_supported=False,
|
|
generated_artifacts=(),
|
|
notes=("No AMPG adapter is registered for this protocol/daemon pair.",),
|
|
)
|