Initial AMPG spec and Wownero prototype

This commit is contained in:
jwinterm
2026-07-05 19:29:00 -04:00
commit e01d35132f
24 changed files with 1899 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
# Architecture
> Status: draft | Updated 2026-07-05 | Applies to: AMPG core
AMPG is a compiler plus an ingress manager. The compiler turns one site into a
protocol-neutral content graph, then renders protocol-specific outputs. The ingress
manager connects those outputs to daemons selected by the operator.
## System shape
```text
source site
-> source adapter
-> content graph
-> render profiles
-> output roots
-> daemon adapters
-> clearnet / Tor / I2P / Gemini / Reticulum
```
## Source adapters
`static-html`
: Reads an existing static site tree. AMPG preserves the clearnet version, parses HTML
into a content graph, rewrites local links, and extracts text for Gemini and Micron
renderers. This is the default path for the Wownero pilot.
`markdown`
: Reads Markdown plus frontmatter. This is the cleanest authoring model for new sites.
`ssg-output`
: Reads the built output of another static site generator. AMPG does not own that
generator; it adapts the generated files.
## Content graph
The internal graph is intentionally small:
- `Site`: domain, aliases, selected protocols, source metadata.
- `Page`: route, title, language, headings, body blocks, links, assets.
- `Asset`: path, media type, size, dimensions, privacy policy.
- `Link`: target, relation, transport compatibility.
Renderers should not scrape each other. They read the content graph and write their
own output.
## Render profiles
`clearnet`
: High-fidelity output. Static HTML sources are copied by default. Markdown sources render
to full HTML and may include CSS, JavaScript, web fonts, and rich media.
`privacy-html`
: Tor and I2P default. Removes JavaScript, tracking pixels, external fonts, third-party
embeds, remote assets, and stateful browser storage assumptions. CSS is local and small.
`gemtext`
: Gemini output. Converts headings, paragraphs, lists, code blocks, and links to `.gmi`.
Inline links become block links near the paragraph by default.
`micron`
: Reticulum/Nomad output. Produces terminal-oriented Micron markup with small pages,
plain links, and no heavy media by default.
## Daemon adapters
Daemon adapters provide a common interface:
- `detect`: find existing services, ports, config files, and health endpoints.
- `plan`: decide whether to adopt, manage, or fail.
- `render_config`: produce config snippets and complete managed configs.
- `apply`: write approved managed config and start or reload services.
- `health`: verify the selected transport can serve the generated output.
Adapters must be conservative. They do not modify non-AMPG config without showing a
plan first, and managed config lives under AMPG-owned state directories.
## Interaction boundary
v1 is static-first, but the architecture reserves a path for interactive applications.
Interactivity is declared per route group:
- `static`: files only.
- `forms`: server-rendered actions and full-page responses.
- `sessions`: authenticated flows with strict session policy.
- `realtime`: rich browser/admin interfaces; HTTP transports only.
- `internal`: workers, webhooks, private admin APIs; never published automatically.
Dynamic support comes through application adapters that expose action metadata. HTTP
transports can use normal forms or reverse proxies. Gemini uses status-code input prompts
for simple actions. Reticulum uses page scripts or Micron action links. The core compiler
must remain useful when no application adapter is configured.
## Reusable checklist
- [ ] Add a source adapter only when it can produce the content graph.
- [ ] Add a renderer only when it reads the graph directly.
- [ ] Add a daemon adapter only with `detect`, `plan`, `render_config`, `apply`, and `health`.
- [ ] Keep privacy defaults stricter than clearnet defaults.
+62
View File
@@ -0,0 +1,62 @@
# Autodocs And Drift Gates
> Status: draft | Updated 2026-07-05 | Applies to: AMPG generated docs
AMPG should publish concise hand-written docs and generate the parts that can drift from
code. Generated artifacts are committed, then checked in CI by regenerating and diffing.
## Generated artifacts
`docs/generated/config-schema.md`
: Generated from the `gateway.toml` schema. Includes fields, defaults, enum values, and
examples.
`docs/generated/daemon-adapters.md`
: Generated from registered daemon adapters. Lists supported daemons, discovery paths,
managed-state paths, health checks, and known limitations.
`docs/generated/render-profiles.md`
: Generated from renderer definitions. Lists stripped tags, asset limits, link modes,
and defaults for each target.
`openapi.json`
: Generated if AMPG exposes a local control API for status, builds, plans, and daemon
health.
## Drift gates
CI should run:
```sh
python3 -m ampg docs generate
python3 -m ampg docs generate --check
git diff --exit-code docs/generated openapi.json
python3 tools/docs_check.py
```
`ampg docs check` should verify:
- every Markdown file starts with a `> Status:` header.
- internal links resolve.
- generated docs are not edited by hand.
- public docs contain no private keys, onion keys, I2P keys, Reticulum identities, or
local production secrets.
## Public/private boundary
Public docs include reusable contracts, generated references, and concise operator-facing
guidance. Private docs are ignored under `docs/private/` and are the place for strategy,
internal discussion, deployment inventory, working notes, tracking, timelines, and any
real host-specific material.
Public docs can include example domains, ports, and fake keys. Real daemon keys,
production paths with secrets, private host inventory, and internal planning notes belong
outside the public repo.
## Reusable checklist
- [ ] Generate config schema docs from code.
- [ ] Generate daemon adapter docs from registered adapters.
- [ ] Generate renderer docs from renderer defaults.
- [ ] Commit generated artifacts.
- [ ] Fail CI when regeneration produces a diff.
+171
View File
@@ -0,0 +1,171 @@
# Configuration
> Status: draft | Updated 2026-07-05 | Applies to: `gateway.toml`
AMPG is configured from one TOML file. The file declares global paths, sites, source
adapters, render targets, and daemon policy.
## Minimal Wownero pilot config
```toml
[gateway]
state_dir = "/var/lib/ampg"
cache_dir = "/var/cache/ampg"
run_dir = "/run/ampg"
user = "ampg"
[[site]]
id = "wownero"
domain = "wownero.org"
[site.source]
kind = "static-html"
path = "../wownero.org-website"
canonical_url = "https://wownero.org"
[site.outputs]
root = "/var/www/ampg/wownero"
[site.interactions]
default_tier = "static"
deny_routes = ["/admin/*", "/internal/*", "/webhooks/*"]
[site.protocols.clearnet]
enabled = true
renderer = "clearnet"
daemon = "caddy"
daemon_policy = "adopt"
[site.protocols.tor]
enabled = true
renderer = "privacy-html"
daemon = "tor"
daemon_policy = "auto"
local_port = 18080
onion_location = "auto"
[site.protocols.i2p]
enabled = false
renderer = "privacy-html"
daemon = "i2pd"
daemon_policy = "auto"
local_port = 18081
[site.protocols.gemini]
enabled = false
renderer = "gemtext"
daemon = "agate"
daemon_policy = "auto"
port = 1965
[site.protocols.reticulum]
enabled = false
renderer = "micron"
daemon = "rnsd"
daemon_policy = "auto"
aspect = "web"
```
## Defaults
Selected protocols default to `daemon_policy = "auto"` unless the protocol is clearnet.
Clearnet defaults to `adopt`, because most operators already have a web server and TLS
workflow.
| Protocol | Default renderer | Default daemon | Default policy |
| --- | --- | --- | --- |
| clearnet | `clearnet` | `caddy` | `adopt` |
| tor | `privacy-html` | `tor` | `auto` |
| i2p | `privacy-html` | `i2pd` | `auto` |
| gemini | `gemtext` | `agate` | `auto` |
| reticulum | `micron` | `rnsd` | `auto` |
## Renderer defaults
`privacy-html` removes:
- `<script>` blocks and event handler attributes.
- remote fonts, analytics, and third-party embeds.
- localStorage/sessionStorage assumptions.
- non-local asset references unless explicitly allowed.
`gemtext` defaults:
- one `.gmi` page per HTML or Markdown page.
- inline links emitted after the paragraph that referenced them.
- images and PDFs emitted as links with file size metadata when known.
`micron` defaults:
- one `.mu` page per high-value page.
- headings converted to terminal-safe emphasis.
- images omitted unless the site config opts into small downloadable assets.
## Daemon policy values
`external`
: Build outputs and print config. Never inspect, write, start, or reload daemons.
`adopt`
: Use a configured or detected daemon. Fail with a clear diagnostic if missing.
`manage`
: Create an AMPG-owned daemon instance and supervise it.
`auto`
: Adopt a healthy daemon when one is found. Otherwise create an AMPG-owned instance.
## Interactive app config
Applications can declare route groups and upstreams. AMPG only exposes the tiers each
transport can safely support.
```toml
[[site]]
id = "shop_platform"
domain = "example-shop.net"
[site.source]
kind = "reverse-proxy"
upstream = "http://127.0.0.1:8000"
openapi = "http://127.0.0.1:9000/openapi.json"
[site.interactions]
default_tier = "forms"
session_policy = "http-only-cookie"
deny_routes = ["/admin/*", "/api/internal/*", "/webhooks/*"]
[[site.interactions.route]]
match = "/admin/*"
tier = "internal"
[[site.interactions.route]]
match = "/checkout/*"
tier = "sessions"
[[site.interactions.route]]
match = "/catalog/*"
tier = "forms"
[site.protocols.tor]
enabled = true
renderer = "privacy-html"
daemon_policy = "auto"
allow_javascript = false
[site.protocols.gemini]
enabled = true
renderer = "gemtext"
daemon_policy = "auto"
max_tier = "forms"
```
`max_tier` is a hard cap. If a route needs a higher tier than the protocol allows, AMPG
omits it or renders a safe alternate page.
## Reusable checklist
- [ ] Keep paths explicit in production configs.
- [ ] Use `ampg plan` before `ampg apply`.
- [ ] Use `daemon_policy = "external"` for package-maintainer examples.
- [ ] Use `daemon_policy = "auto"` for single-box deployments.
+94
View File
@@ -0,0 +1,94 @@
# Daemon Management
> Status: draft | Updated 2026-07-05 | Applies to: protocol adapters
AMPG can use daemons that already exist on a server or create AMPG-owned daemons when
the selected protocol is not running. This keeps simple deployments simple while avoiding
surprise edits to operator-owned services.
## Ownership rules
Adopted daemons:
- are already installed and healthy.
- keep their existing service manager and primary config ownership.
- receive generated snippets only after the operator approves the plan.
- are never rewritten wholesale by AMPG.
Managed daemons:
- store config under `state_dir`.
- expose logs and health through AMPG.
- use AMPG-owned ports, sockets, hidden-service dirs, key files, and output roots.
- can be stopped, restarted, or removed by AMPG.
## Discovery order
For each enabled protocol, AMPG checks:
1. Explicit config in `gateway.toml`.
2. AMPG-owned state from previous runs.
3. Common system services and ports.
4. Known config paths for supported daemons.
The result is shown in `ampg plan`.
## Adapter notes
### Clearnet
Default daemon: Caddy.
AMPG should usually adopt clearnet ingress instead of managing it. Existing TLS,
firewall, and reverse proxy rules are operator-owned. Managed clearnet is useful for
development and single-purpose boxes.
### Tor
Default daemon: Tor.
If Tor is already running, AMPG can add a hidden service snippet that points to the
`privacy-html` local server. If Tor is missing and policy is `auto` or `manage`, AMPG
creates an AMPG-owned Tor instance or service unit and stores hidden-service material
under the AMPG state directory.
### I2P
Default daemon: i2pd.
AMPG first supports server tunnels through i2pd. I2P-Zero can be added as a second
adapter with the same interface. Managed I2P must keep destination keys in AMPG state
and include backup warnings in the plan.
### Gemini
Default daemon: Agate.
Gemini is static-friendly and can be managed safely. AMPG generates `.gmi` output,
certificates when requested, and an Agate config pointing at the Gemini output root.
### Reticulum
Default daemon: rnsd or a compatible page server.
Reticulum management is split: AMPG can manage generated Micron pages and a page-serving
process, but physical interfaces such as LoRa, serial, packet radio, or custom transports
may require explicit operator setup. `ampg plan` must distinguish page-server readiness
from transport-interface readiness.
## Safety requirements
- Show every config write before applying it.
- Back up any adopted-daemon snippet AMPG touches.
- Never delete hidden-service keys, I2P keys, or Reticulum identities without an explicit
destructive command.
- Refuse to bind public ports when the selected renderer is not built.
- Health-check every enabled protocol after apply.
## Reusable checklist
- [ ] Adapter detects existing daemon state.
- [ ] Adapter can produce a dry-run plan.
- [ ] Managed config is isolated under AMPG state.
- [ ] Key material is backed up or clearly called out.
- [ ] Health check validates the generated site through the selected transport.
+20
View File
@@ -0,0 +1,20 @@
# Generated Config Schema
> Status: generated | Updated by `python3 -m ampg docs generate` | Applies to: AMPG
This file is generated from code. Do not edit it by hand.
| Section | Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- | --- |
| site | `id` | string | yes | - | Stable site identifier used in output paths. |
| site | `domain` | string | yes | - | Canonical public domain for the site. |
| site.source | `kind` | enum | yes | static-html | Source adapter kind. |
| site.source | `path` | path | yes | - | Source tree path. |
| site.source | `canonical_url` | url | no | - | Canonical clearnet URL. |
| site.outputs | `root` | path | yes | - | Generated output root. |
| site.interactions | `default_tier` | enum | no | static | Default interaction tier for routes. |
| site.interactions | `deny_routes` | array<string> | no | [] | Route patterns that must not be published. |
| site.protocols.<name> | `enabled` | boolean | no | false | Whether this protocol target is built and planned. |
| site.protocols.<name> | `renderer` | enum | no | <protocol> | Renderer profile to use for this protocol. |
| site.protocols.<name> | `daemon` | enum | no | protocol default | Ingress daemon adapter. |
| site.protocols.<name> | `daemon_policy` | enum | no | protocol default | Whether AMPG adopts, manages, or only renders config. |
+36
View File
@@ -0,0 +1,36 @@
# Generated Daemon Adapters
> Status: generated | Updated by `python3 -m ampg docs generate` | Applies to: AMPG
This file is generated from code. Do not edit it by hand.
## nginx
- Protocols: clearnet, tor, i2p
- Default policy: `adopt`
- Generated artifacts: server block snippets
Notes:
- Clearnet defaults to adopt because TLS and public vhost policy are operator-owned.
- Tor/I2P HTTP targets can use loopback-only server blocks.
## tor
- Protocols: tor
- Default policy: `auto`
- Generated artifacts: torrc hidden-service snippet
Notes:
- AMPG should preserve existing HiddenServiceDir material when adopting.
- Managed hidden-service keys belong under AMPG state.
## i2pd
- Protocols: i2p
- Default policy: `auto`
- Generated artifacts: i2pd server tunnel snippet
Notes:
- Web tunnels should use web-specific key files.
- Existing RPC/P2P tunnel keys are not reused for web publishing.
+31
View File
@@ -0,0 +1,31 @@
# Generated Render Profiles
> Status: generated | Updated by `python3 -m ampg docs generate` | Applies to: AMPG
This file is generated from code. Do not edit it by hand.
## clearnet
High-fidelity static web output.
- Output: HTML/CSS/JS/assets
Defaults:
- Copies source files except hidden/editor/VCS clutter.
- Keeps local JavaScript and rich media.
- Writes only to AMPG-marked generated output roots.
## privacy-html
Static HTML for Tor and I2P.
- Output: HTML/CSS/assets
Defaults:
- Removes active tags: script, style.
- Removes inline event handlers such as onclick and onload.
- Removes inline style attributes.
- Skips JavaScript and source-map files.
- Skips oversized assets above max_asset_bytes.
- Removes remote src/poster/link asset references.
+123
View File
@@ -0,0 +1,123 @@
# Interactive Applications
> Status: draft | Updated 2026-07-05 | Applies to: dynamic app support
AMPG must support real applications without pretending every transport can offer the same
experience. The design goal is graceful capability mapping: expose the safest useful version
of each surface on each protocol, and keep private surfaces private.
## Interaction tiers
`static`
: Rendered files only. Works everywhere.
`forms`
: Server-rendered GET/POST actions with full-page responses. Works on clearnet, Tor, I2P,
and can be mapped to Gemini input prompts or Reticulum page scripts for simple actions.
`sessions`
: Authenticated account flows. Supported on HTTP transports with strict cookies. Gemini can
use client certificates or signed links later, but this is not a v1 requirement.
`realtime`
: Rich browser UI, dashboards, live charts, websockets, or client-side state. HTTP transports
only, and usually clearnet or private Tor/I2P.
`internal`
: Worker APIs, webhooks, private admin APIs, payment callbacks, chain watchers, and service
health endpoints. AMPG must not publish these automatically.
## Application adapter contract
An application adapter describes what AMPG may expose:
- upstream service and health check.
- OpenAPI spec or route manifest when available.
- route groups with interaction tier, auth requirement, and idempotency behavior.
- form/action schemas for protocol translation.
- public asset and cache policy.
- private route denylist.
Adapters do not bypass the application. They translate constrained protocol input into the
application's public action surface, then render safe responses.
## Protocol mapping
| Tier | Clearnet | Tor/I2P | Gemini | Reticulum |
| --- | --- | --- | --- | --- |
| `static` | yes | yes | yes | yes |
| `forms` | yes | yes, no JS by default | simple single-field prompts | simple scripts/actions |
| `sessions` | yes | yes, strict cookies | later | later |
| `realtime` | yes | optional private surface | no | no |
| `internal` | no public publish | no public publish | no | no |
## Challenge profile: Medusa multi-tenant platform
Source: `../medusa-multi-tenant-platform`.
Why it matters:
- multi-tenant domain routing.
- storefront, tenant admin, backend, worker, database, Redis, S3/MinIO.
- cart, checkout, orders, bookings, blogs, email, payment providers, and webhooks.
- tenant-specific themes and custom domains.
AMPG support target:
- Clearnet: adopt existing Caddy/reverse-proxy deployment.
- Tor/I2P: expose storefront routes with `forms` or `sessions` tier, no JavaScript by default.
- Gemini/Reticulum: expose catalog, blog, policy, product detail, and inquiry/request flows.
- Admin: `internal` unless explicitly bound to a private operator transport.
- Webhooks, payment callbacks, worker queues, health internals: always `internal`.
Required adapter capabilities:
- read tenant/domain registry or accept an exported tenant manifest.
- generate per-tenant protocol targets and daemon plans.
- cap checkout/payment routes by protocol.
- use OpenAPI route metadata where available.
- never expose tenant admin or backend admin by wildcard.
## Challenge profile: evaluetron / ai-gen-bot
Source: `../ai-gen-bot`.
Why it matters:
- OpenAPI-first core.
- customer storefront plus operator console.
- auth, payments, credit ledger, job queue, workers, moderation, and generated artifacts.
- public web channel, Telegram channel, internal worker APIs, and admin APIs.
AMPG support target:
- Clearnet: public storefront and docs.
- Tor/I2P: public storefront with server-rendered account/job flows when enabled.
- Gemini/Reticulum: catalog browsing, deposit instructions, simple generation request, and job
status lookup only after explicit adapter support.
- Operator console: private clearnet, LAN, mesh, or private onion only.
- Worker/internal routes: never published.
Required adapter capabilities:
- consume `api/openapi.yaml` as the action contract.
- map job creation to idempotent form submissions.
- render job status as polling-friendly pages.
- hide unavailable generators when no worker advertises the required capability.
- preserve the ledger and payment invariants of the upstream app.
## Design constraints learned from the challenge apps
- Public route discovery must start deny-first.
- OpenAPI is useful, but not sufficient; route tiers and privacy intent must be explicit.
- Admin and worker surfaces are separate sites or route groups, not accidental subpaths.
- Gemini and Reticulum need curated actions, not automatic exposure of every POST route.
- Multi-tenant apps need generated protocol targets per tenant, with shared daemon adapters.
## Reusable checklist
- [ ] Classify every route group by interaction tier.
- [ ] Deny private/admin/internal routes before enabling protocols.
- [ ] Prefer OpenAPI or route manifests over HTML scraping for actions.
- [ ] Provide safe alternates for constrained transports.
- [ ] Verify no worker, webhook, payment callback, or admin route is publicly published.
+145
View File
@@ -0,0 +1,145 @@
# Wownero Integration
> Status: draft | Updated 2026-07-05 | Applies to: Wownero static site publishing
The Wownero integration exercises AMPG against a real public static site. The source is
the existing `wownero.org` website checked out next to this repository as
`../wownero.org-website`.
## Objective
Start with the existing clearnet site, preserve the rich web output, and generate
transport-specific variants with defaults:
- clearnet: faithful static site output.
- Tor: privacy-hardened static HTML.
- I2P: privacy-hardened static HTML.
- Gemini: text-first `.gmi` pages.
- Reticulum: compact Micron `.mu` pages.
## Source Adapter
The Wownero site is a static HTML/CSS/JS tree:
- top-level pages such as `index.html`, `mining.html`, `emission.html`, and
`wownero-wallet-generator.html`.
- local CSS, JavaScript, image, PDF, text, and icon assets.
- JavaScript-driven translation and UI behavior.
- an `onion-location` meta tag in `index.html`.
This makes `static-html` the right source adapter. Markdown migration is optional and
must not be required for AMPG adoption.
## Generated Outputs
```text
/var/www/ampg/wownero/
clearnet/
index.html
css/
js/
img/
tor/
index.html
mining.html
emission.html
i2p/
index.html
mining.html
emission.html
gemini/
index.gmi
mining.gmi
emission.gmi
reticulum/
index.mu
mining.mu
emission.mu
```
## Renderer Behavior
### Clearnet
Copy the source tree by default, excluding VCS/editor clutter, hidden private files, and
backup artifacts.
### Tor and I2P
Use `privacy-html`:
- remove JavaScript.
- remove inline event handlers.
- remove inline styles.
- keep local CSS only when configured.
- preserve local links to PDFs, text files, and reasonably sized images.
- preserve or generate onion/I2P location metadata only when configured.
### Gemini
Use `gemtext`:
- extract page title, headings, paragraphs, lists, and links.
- emit links near the paragraph that referenced them.
- convert large media to plain download links.
- skip repeated navigation noise.
### Reticulum
Use `micron`:
- prioritize short informational pages.
- omit heavy images by default.
- generate compact navigation.
- treat downloadable files as links with size hints.
## Daemon Policy
Recommended defaults:
```toml
[site.protocols.clearnet]
enabled = true
daemon_policy = "adopt"
[site.protocols.tor]
enabled = true
daemon_policy = "auto"
[site.protocols.i2p]
enabled = false
daemon_policy = "auto"
[site.protocols.gemini]
enabled = false
daemon_policy = "auto"
[site.protocols.reticulum]
enabled = false
daemon_policy = "auto"
```
## Acceptance Criteria
- `ampg plan` identifies the Wownero source tree and selected protocols.
- `ampg build` creates clearnet and Tor output without requiring Markdown.
- Tor output contains no `<script>` tags or inline event handlers.
- Generated Gemini output has readable headings, paragraphs, and links.
- Generated Micron output fits terminal-first browsing.
- `ampg plan` clearly says whether each selected daemon is adopted or managed.
## Local Commands
```sh
python3 -m ampg --config examples/wownero.gateway.toml plan
python3 -m ampg --config examples/wownero.gateway.toml build
```
## Reusable checklist
- [ ] Build from `../wownero.org-website` using `source.kind = "static-html"`.
- [ ] Preserve clearnet output first.
- [ ] Generate Tor `privacy-html` and verify active content is stripped.
- [ ] Add Gemini conversion fixtures.
- [ ] Add Reticulum/Micron conversion fixtures.
- [ ] Enable I2P and Reticulum daemon management only after static outputs are stable.