Make AMPB Firefox-first

This commit is contained in:
jwinterm
2026-07-07 16:51:32 -04:00
parent f0ffc039d1
commit 8a96957f62
13 changed files with 145 additions and 18 deletions
+6 -1
View File
@@ -1,11 +1,15 @@
# Adaptive Multi-Protocol Browser
> Status: draft | Updated 2026-07-05 | Applies to: AMPB contributors and operators
> Status: draft | Updated 2026-07-07 | Applies to: AMPB contributors and operators
Adaptive Multi-Protocol Browser, or AMPB, is a transport-aware browser shell. It routes
URLs to the right network, adopts transports that are already healthy, and manages missing
transports when configured to do so.
AMPB is Firefox-first for normal web browsing. The initial product should control a
hardened Firefox runtime, transport-specific profiles, and AMPB-owned transport setup
before graduating into a deeper Firefox or Tor Browser fork.
The first fixture is Wownero across clearnet, Tor, I2P, Gemini, and Reticulum-oriented
targets generated by AMPG. Interactive fixtures include `ai-gen-bot` and the Medusa
multi-tenant platform.
@@ -56,6 +60,7 @@ python3 -m unittest discover -s tests
- [Transport management](docs/transport-management.md)
- [Test fixtures](docs/test-fixtures.md)
- [Autodocs and drift gates](docs/autodocs.md)
- [Generated browser strategy](docs/generated/browser-strategy.md)
## Reusable checklist
+2 -2
View File
@@ -23,7 +23,7 @@ class ConfigError(ValueError):
@dataclass(frozen=True)
class AppConfig:
state_dir: str = ".ampb"
default_engine: str = "system"
default_engine: str = "hardened-firefox"
isolate_by_transport: bool = True
transport_modes: dict[str, str] | None = None
@@ -68,7 +68,7 @@ def _parse_config(data: dict[str, Any], path: Path) -> AppConfig:
transports = _table(data, "transports", path)
state_dir = _string(browser, "state_dir", ".ampb", path)
default_engine = _string(browser, "default_engine", "system", path)
default_engine = _string(browser, "default_engine", "hardened-firefox", path)
isolate_by_transport = _bool(profiles, "isolate_by_transport", True, path)
transport_modes = _transport_modes(transports, path)
+15 -1
View File
@@ -4,7 +4,7 @@ from pathlib import Path
from .adapters import ADAPTERS
from .candidates import CANDIDATE_TRANSPORTS
from .metadata import ROUTE_RULES, TRANSPORT_DEFINITIONS
from .metadata import BROWSER_BACKENDS, ROUTE_RULES, TRANSPORT_DEFINITIONS
from .platforms import PLATFORM_CAPABILITIES
@@ -18,6 +18,7 @@ def generate_docs(root: Path, *, check: bool = False) -> list[Path]:
GENERATED_DIR / "adapters.md": _adapters_doc(),
GENERATED_DIR / "candidate-transports.md": _candidate_transports_doc(),
GENERATED_DIR / "platform-capabilities.md": _platform_capabilities_doc(),
GENERATED_DIR / "browser-strategy.md": _browser_strategy_doc(),
}
changed: list[Path] = []
for rel_path, content in docs.items():
@@ -104,3 +105,16 @@ def _candidate_transports_doc() -> str:
f"[source]({candidate.source}) | {candidate.note} |"
)
return _header("Generated Candidate Transports") + "\n".join(rows) + "\n"
def _browser_strategy_doc() -> str:
rows = [
"| Backend | Role | Status | Platforms | Launch Mode | Privacy Posture | Note |",
"| --- | --- | --- | --- | --- | --- | --- |",
]
for backend in BROWSER_BACKENDS:
rows.append(
f"| `{backend.name}` | {backend.role} | `{backend.status}` | {backend.platforms} | "
f"{backend.launch_mode} | {backend.privacy_posture} | {backend.note} |"
)
return _header("Generated Browser Strategy") + "\n".join(rows) + "\n"
+59
View File
@@ -20,6 +20,17 @@ class TransportDefinition:
note: str
@dataclass(frozen=True)
class BrowserBackend:
name: str
role: str
status: str
platforms: str
launch_mode: str
privacy_posture: str
note: str
ROUTE_RULES = (
RouteRule("*.onion", "tor", "tor", "route through Tor SOCKS"),
RouteRule("*.i2p", "i2p", "i2p", "route through I2P HTTP proxy"),
@@ -66,3 +77,51 @@ TRANSPORT_DEFINITIONS = (
"Adapter planned for resilient/private routing; physical/link-layer setup may require operator config.",
),
)
BROWSER_BACKENDS = (
BrowserBackend(
"hardened-firefox",
"primary web runtime",
"planned",
"desktop, android",
"managed profile, policy, and native transport launcher",
"strong baseline; track Firefox ESR and Tor Browser hardening choices",
"Default AMPB web runtime before a full browser fork.",
),
BrowserBackend(
"tor-browser-compatible",
"tor-hardened target",
"planned",
"desktop, android",
"adopt, launch, or fork after transport contracts are stable",
"highest Tor web target; do not claim equivalence until Tor Browser patches are tracked",
"Path toward real Tor Browser-grade behavior for .onion browsing.",
),
BrowserBackend(
"webkit-ios-shell",
"ios runtime",
"planned",
"ios",
"native shell with embedded transports and isolated web views",
"platform constrained; avoid clearnet fallback and isolate transport state",
"Required for App Store-style iOS builds outside special browser-engine entitlements.",
),
BrowserBackend(
"gemini-native-viewer",
"alternate-web viewer",
"planned",
"desktop, android, ios",
"built-in fetch and render path",
"no web engine or shared browser storage required",
"Used for Gemini and similar lightweight document transports.",
),
BrowserBackend(
"chromium-cef",
"prototype fallback",
"fallback",
"desktop",
"profile launcher only when Firefox path is blocked",
"not a Tor Browser privacy baseline",
"Allowed for experiments, but not the main privacy-browser strategy.",
),
)
+16 -8
View File
@@ -1,6 +1,6 @@
# Architecture
> Status: draft | Updated 2026-07-05 | Applies to: AMPB contributors and integrators
> Status: draft | Updated 2026-07-07 | Applies to: AMPB contributors and integrators
AMPB is a browser orchestration layer for privacy, resilient-network, content-addressed,
and alternate-web transports. It keeps the routing, transport management, and profile
@@ -29,14 +29,22 @@ isolation decisions outside the browser engine until those contracts are stable.
## Browser Strategy
The first implementation should be a launcher and profile manager, not a browser-engine
fork. Tor Browser, Mullvad Browser, Firefox profiles, Chromium profiles, terminal Gemini
clients, local IPFS gateways, and future Reticulum-native viewers can all sit behind the same route and
transport contracts.
The first implementation should be Firefox-first without becoming a browser-engine fork
immediately. AMPB should control a hardened Firefox runtime, AMPB-owned profiles,
transport proxy policy, native transport setup, and health checks while the orchestration
contracts become stable.
The long-term browser can become more integrated once the orchestration surface is boring:
profile isolation is reliable, transport adoption is predictable, and generated fixtures
from AMPG can be opened without manual proxy setup.
Tor Browser compatibility is the high bar for `.onion` browsing. AMPB must not claim Tor
Browser equivalence until it tracks the relevant Tor Browser hardening, fingerprinting,
proxy, and update behavior. Chromium or CEF can remain a prototype fallback, but it is not
the main privacy-browser strategy.
The long-term browser can become a deeper Firefox or Tor Browser fork once the
orchestration surface is reliable: profile isolation is predictable, transport adoption is
boring, and generated fixtures from AMPG open without manual proxy setup.
Generated backend metadata lives in
[generated browser strategy](generated/browser-strategy.md).
## Relationship To AMPG
+4 -2
View File
@@ -1,6 +1,6 @@
# Autodocs
> Status: draft | Updated 2026-07-05 | Applies to: AMPB maintainers
> Status: draft | Updated 2026-07-07 | Applies to: AMPB maintainers
Public docs should stay concise and current. Code-owned behavior is documented from code,
while manual docs explain stable concepts and operator-facing choices.
@@ -19,7 +19,9 @@ Check for drift:
python3 -m ampbrowser docs generate --check
```
Generated files live under `docs/generated/` and must not be edited by hand.
Generated files live under `docs/generated/` and must not be edited by hand. They cover
route rules, active transports, browser backend strategy, adapter contracts, candidate
transports, and platform capabilities.
## Manual Docs
+2 -2
View File
@@ -1,6 +1,6 @@
# Configuration
> Status: draft | Updated 2026-07-05 | Applies to: AMPB users and package maintainers
> Status: draft | Updated 2026-07-07 | Applies to: AMPB users and package maintainers
AMPB should work without a config file for common local setups. Explicit configuration is
for changing defaults, pinning binary paths, choosing managed state directories, and
@@ -27,7 +27,7 @@ Example configs live under `examples/`.
```toml
[browser]
default_engine = "system"
default_engine = "hardened-firefox"
state_dir = ".ampb"
[transports.tor]
+13
View File
@@ -0,0 +1,13 @@
# Generated Browser Strategy
> Status: generated | Updated by `python3 -m ampbrowser docs generate` | Applies to: AMPB
This file is generated from code. Do not edit it by hand.
| Backend | Role | Status | Platforms | Launch Mode | Privacy Posture | Note |
| --- | --- | --- | --- | --- | --- | --- |
| `hardened-firefox` | primary web runtime | `planned` | desktop, android | managed profile, policy, and native transport launcher | strong baseline; track Firefox ESR and Tor Browser hardening choices | Default AMPB web runtime before a full browser fork. |
| `tor-browser-compatible` | tor-hardened target | `planned` | desktop, android | adopt, launch, or fork after transport contracts are stable | highest Tor web target; do not claim equivalence until Tor Browser patches are tracked | Path toward real Tor Browser-grade behavior for .onion browsing. |
| `webkit-ios-shell` | ios runtime | `planned` | ios | native shell with embedded transports and isolated web views | platform constrained; avoid clearnet fallback and isolate transport state | Required for App Store-style iOS builds outside special browser-engine entitlements. |
| `gemini-native-viewer` | alternate-web viewer | `planned` | desktop, android, ios | built-in fetch and render path | no web engine or shared browser storage required | Used for Gemini and similar lightweight document transports. |
| `chromium-cef` | prototype fallback | `fallback` | desktop | profile launcher only when Firefox path is blocked | not a Tor Browser privacy baseline | Allowed for experiments, but not the main privacy-browser strategy. |
+1 -1
View File
@@ -1,5 +1,5 @@
[browser]
default_engine = "system"
default_engine = "hardened-firefox"
state_dir = ".ampb"
[transports.tor]
+1 -1
View File
@@ -1,5 +1,5 @@
[browser]
default_engine = "system"
default_engine = "hardened-firefox"
state_dir = ".ampb"
[transports.i2p]
+24
View File
@@ -0,0 +1,24 @@
from __future__ import annotations
import unittest
from ampbrowser.metadata import BROWSER_BACKENDS
class BrowserStrategyTest(unittest.TestCase):
def test_primary_backend_is_hardened_firefox(self) -> None:
primary = [backend for backend in BROWSER_BACKENDS if backend.role == "primary web runtime"]
self.assertEqual(1, len(primary))
self.assertEqual("hardened-firefox", primary[0].name)
self.assertIn("Firefox", primary[0].privacy_posture)
def test_chromium_is_fallback_not_privacy_baseline(self) -> None:
chromium = next(backend for backend in BROWSER_BACKENDS if backend.name == "chromium-cef")
self.assertEqual("fallback", chromium.status)
self.assertIn("not a Tor Browser", chromium.privacy_posture)
if __name__ == "__main__":
unittest.main()
+1
View File
@@ -13,6 +13,7 @@ class ConfigTest(unittest.TestCase):
config = load_config(Path(tmp))
self.assertEqual(".ampb", config.state_dir)
self.assertEqual("hardened-firefox", config.default_engine)
self.assertEqual("adopt-or-prompt-manage", config.transport_mode("tor"))
self.assertEqual(".ampb/profiles/tor", config.profile_path("tor"))
+1
View File
@@ -16,6 +16,7 @@ class DocsGenTest(unittest.TestCase):
self.assertEqual(
{
Path("docs/generated/adapters.md"),
Path("docs/generated/browser-strategy.md"),
Path("docs/generated/candidate-transports.md"),
Path("docs/generated/platform-capabilities.md"),
Path("docs/generated/route-rules.md"),