first commit

This commit is contained in:
Raven Scott
2026-07-30 23:02:00 -04:00
commit fd537ed47e
48 changed files with 3059 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
# ADR-NNNN: Title
- **Status:** Proposed | Accepted | Deprecated | Superseded by ADR-XXXX
- **Date:** YYYY-MM-DD
- **Deciders:** (optional)
## Context
What is the issue? What forces are at play?
## Decision
What did we decide?
## Consequences
### Positive
-
### Negative / tradeoffs
-
### Follow-ups
- [ ] Doc updates
- [ ] Implementation tasks
- [ ] Open questions
## References
- Related ADRs
- External links / code paths
@@ -0,0 +1,33 @@
# ADR-0001: Record architecture decisions
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Flying Jib combines Minecraft server embedding, Holepunch P2P, Electron, and mesh federation. Without a durable decision log, agents and humans will re-litigate stack choices and silently diverge from mesh-native constraints.
## Decision
Use Architecture Decision Records in `agent/ADRs/`:
- Sequential numbering (`0001`, `0002`, …)
- Template at `0000-template.md`
- Required before architecture, protocol, process-model, or security-model changes land
- Status: Proposed → Accepted (or Deprecated/Superseded)
## Consequences
### Positive
- Traceable “why” for every major choice
- Onboarding and AI agents share the same decision surface
### Negative / tradeoffs
- Small process overhead per change
### Follow-ups
- [x] Template and first ADRs for Phase 0
- [ ] Keep index via directory listing / ROADMAP links
@@ -0,0 +1,41 @@
# ADR-0002: Choose Flying Squid as server core
- **Status:** Accepted (amended by [ADR-0013](./0013-bare-pear-only-runtime-and-distribution.md))
- **Date:** 2026-07-30
- **Amended:** 2026-07-30
## Context
We need an embeddable Java Editioncompatible server that runs locally inside our app lifecycle, supports plugins, Anvil worlds, and modern protocol versions — without operating a central host. Production runtime must be **Bare/Pear only** (no app-level Node.js).
## Decision
Use **[Flying Squid](https://github.com/PrismarineJS/flying-squid)** (`flying-squid` npm) as an **embedded library** via `createMCServer`, running **inside Bare** (in-process or Bare worker) via **`bare-node-runtime`** compatibility imports — **not** as a Node.js child process.
- Plugins: `module.exports.server` / `player` / `entity`
- Worlds: Anvil via `worldFolder` / prismarine-provider-anvil
- Default product target version: latest Squid-tested (e.g. 1.21.4), configurable
- Bind: always `127.0.0.1` ([ADR-0005](./0005-local-only-bind-invariant.md))
We will **not** fork Squid initially; prefer plugins, thin lifecycle wrapper, and Bare `imports` maps. Compatibility gaps → shims/patches, not Node spawn ([ADR-0013](./0013-bare-pear-only-runtime-and-distribution.md)).
## Consequences
### Positive
- JS/Prismarine ecosystem retained under Bare via holepunch compat layers
- Plugin surface for border detection, chat bridge, bind guard
- Broad version support (1.8.81.21.4 tested upstream)
- Fits single Bare executable / Pear OTA story
### Negative / tradeoffs
- Gameplay parity ≠ full vanilla Paper/Spigot
- Heavy dependency graph; Bare packaging + imports maps required
- Squid is Node-authored — Bare load is a critical spike (not free)
### Follow-ups
- [ ] Phase 1 Bare Squid manager + bind force under bare-node-runtime
- [ ] Document imports map for Prismarine stack
- [ ] Plugins `fj-bind-guard`, later mesh plugins
@@ -0,0 +1,43 @@
# ADR-0003: Choose Holepunch P2P stack
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Connectivity must be pure peer-to-peer with E2E encryption, topic discovery, multi-writer metadata, and multiplexed app protocols — without app-operated servers.
## Decision
Adopt the Holepunch stack:
| Layer | Packages |
|-------|----------|
| Discovery / links | `hyperswarm`, `hyperdht` |
| Streams | `@hyperswarm/secret-stream` (via swarm) |
| Multiplex / RPC | `protomux`, `protomux-rpc` |
| Codecs | `compact-encoding`, `hyperschema` |
| Storage | `corestore`, `hypercore`, `hyperbee`, `hyperdrive` |
| Multi-writer | `autobase` (mesh registry) |
| Capabilities | `hyperswarm-capability` |
| App shell | `pear-runtime`, `pear-electron` |
Versions pinned from local mirror investigation (see `developer_docs/MODULES.md`).
## Consequences
### Positive
- Battle-tested mesh primitives
- Matches peardock/hello-pear patterns already used by the team
- Encryption and holepunching “for free”
### Negative / tradeoffs
- Learning curve for Autobase writer admission
- DHT bootstrap nodes are third-party infrastructure (acceptable; not app masters)
### Follow-ups
- [ ] Wire worker swarm in Phase 2+
- [ ] Schema freeze for invites/channels
@@ -0,0 +1,40 @@
# ADR-0004: Process model — Electron + Bare worker + Squid child
- **Status:** Superseded by [ADR-0013](./0013-bare-pear-only-runtime-and-distribution.md)
- **Date:** 2026-07-30
- **Superseded:** 2026-07-30
## Context
We need a polished desktop GUI, a P2P runtime with OTA hooks, and a Node-compatible Minecraft server. One process cannot optimally host all three.
## Decision
| Process | Runtime | Responsibility |
|---------|---------|----------------|
| Main | Electron (Node) | Window, Squid lifecycle, ports, IPC hub |
| Renderer | Chromium | GUI only |
| Worker | Bare via `pear-runtime` | Hyperswarm, HyperDHT tunnels, Autobase, Protomux |
| Squid | Node child | Authoritative MC sim, Anvil I/O |
IPC: Electron ↔ Bare via `framed-stream`; Main ↔ Squid via child_process (stdio/JSON or control socket).
Template: `hello-pear-electron`.
## Consequences
### Positive
- Crash isolation for Squid
- P2P off the UI thread
- OTA patterns from Pear
### Negative / tradeoffs
- Multi-process complexity
- Packaging must include Node-compatible Squid deps beside Electron
### Follow-ups
- [ ] Phase 1 implement managers
- [ ] Decide exact Squid IPC schema
@@ -0,0 +1,33 @@
# ADR-0005: Local-only bind invariant
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
`minecraft-protocol` `createServer` defaults `host` to `undefined`, which listens on **all interfaces**. Accidental WAN exposure of Squid would violate the product security model and user expectations (“P2P app, not open server”).
## Decision
1. Every Squid start **must** pass `host: '127.0.0.1'`.
2. Post-listen verification asserts loopback.
3. Automated tests cover the config writer and bind guard.
4. No product feature may enable public MC TCP listen.
Remote access is only via encrypted HyperDHT tunnels to that loopback port.
## Consequences
### Positive
- Clear security boundary
- Java clients remain simple (always localhost)
### Negative / tradeoffs
- LAN-only play without the app tunnel requires using the tunnel or a future explicit advanced mode (not planned as open bind)
### Follow-ups
- [ ] Phase 1 bind-guard test
- [ ] Document in SECURITY.md (done)
@@ -0,0 +1,38 @@
# ADR-0006: Private world transport via HyperDHT TCP tunnel
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Guests must reach a host Squid without public port forwards. Holesail implements this pattern but is **AGPL-3.0**. Re-encoding the full Minecraft protocol over Protomux is version-fragile.
## Decision
Implement an **in-house Apache-2.0 HyperDHT byte pipe**:
- Host: `dht.createServer` + pipe each connection to `127.0.0.1:squidPort`
- Guest: local loopback accept + `dht.connect(worldKey)` + pipe
- Opaque TCP bytes (no MC packet parse on the tunnel)
Do **not** hard-depend on `holesail`.
Optional: capability proof on stream open (`hyperswarm-capability`).
## Consequences
### Positive
- Works for any Squid-supported protocol version
- License-safe
- Matches peardock “data plane” concept without AGPL
### Negative / tradeoffs
- One pipe per client connection (resource management needed)
- Latency = P2P RTT (not LAN)
### Follow-ups
- [ ] Phase 2 `lib/world-tunnel`
- [ ] Concurrency limits and backpressure
@@ -0,0 +1,33 @@
# ADR-0007: Mesh region registry via Autobase + Hyperbee
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Mesh enrollment needs a multi-writer, eventually consistent registry of regions (bounds, tunnel keys, metadata) without a central database.
## Decision
- Use **Autobase** for multi-writer linearization of registry operations.
- Maintain a **Hyperbee view** (via Autobase `open`/`apply`) keyed by region id and spatial cells.
- Mesh discovery topic derived from mesh root key; replicate over Hyperswarm.
- Defer **autobee** until stable (experimental).
Writer admission is capability-gated (details in Phase 4; OPEN_QUESTIONS Q4).
## Consequences
### Positive
- Holepunch-native multi-writer
- Sparse replication of registry only (not block data)
### Negative / tradeoffs
- Autobase complexity (reordering, indexers)
- Need clear UX for offline regions
### Follow-ups
- [ ] Phase 4 apply function + writer policy ADR amendment if needed
@@ -0,0 +1,41 @@
# ADR-0008: Border strategy — session migration / portals
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
A single global authoritative Minecraft simulation across many peers is unrealistic at scale (tick rate, redstone, entity AI, bandwidth). Full chunk CRDTs are also impractical for real-time play.
## Decision
**Coordinate-space federation** with **session migration**:
1. Each peer owns a region with bounds/offset.
2. Near border: plugin triggers portal or auto-migrate.
3. Serialize player state; Protomux `flying-jib/migrate` handoff.
4. Guest switches HyperDHT tunnel to neighbor `worldKey` and reconnects Java to localhost.
5. Spawn at mapped coordinates.
**Not in v1:** streaming foreign chunks into the local Squid world or dual-sim entity forwarding.
Later phases may add interest-based border sync without abandoning local authority.
## Consequences
### Positive
- Feasible engineering path
- Clear failure mode when neighbor offline
- Preserves Squid as sole authority per region
### Negative / tradeoffs
- Reconnect hitch at borders
- Inventory race risks (must two-phase commit — Q6)
- Not perfectly seamless vanilla continuous terrain
### Follow-ups
- [ ] Phase 4 plugins + migrate state machine
- [ ] Resolve Q6 with tests
@@ -0,0 +1,39 @@
# ADR-0009: Invite capability format `fj1.`
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Users need a single copy-pasteable secret to join private worlds, similar to peardock `pd1.` invites, without accounts or central invite servers.
## Decision
Invite envelope:
```text
fj1.<encoded-payload>
```
Payload (logical) includes protocol version, type (`private-world` | `mesh`), `worldKey`, shared `cap`, optional name/mcVersion/expires.
Phase 2 encoding: JSON → z32 (debug-friendly). May migrate to compact-encoding later (Q13).
Bearer capability model: possession grants join attempt; host enforces proof and may rotate keys.
## Consequences
### Positive
- Offline-friendly, self-contained
- Familiar UX (paste string / QR later)
### Negative / tradeoffs
- Leak = unauthorized join until rotation
- Long strings if JSON grows
### Follow-ups
- [ ] Phase 2 mint/parse library
- [ ] Phase 5 TTL/revoke/roles
+36
View File
@@ -0,0 +1,36 @@
# ADR-0010: Documentation as code
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Long-lived multi-agent development drifts when docs lag. The project requires three audience-specific trees plus agent governance from day one.
## Decision
Maintain from the first commit:
- `living_docs/` — current truth
- `developer_docs/` — contributor technical docs
- `user_docs/` — end-user docs
- `agent/` — rules, workflow, ADRs, security
Policy: same PR as code; session incomplete without living_docs updates. See `agent/DOCUMENTATION_POLICY.md`.
## Consequences
### Positive
- Continuous onboarding
- ADRs + living status reduce rework
### Negative / tradeoffs
- Doc volume to maintain
- Discipline required from AI agents
### Follow-ups
- [x] Phase 0 scaffold
- [ ] Enforce via PR checklist / review
@@ -0,0 +1,32 @@
# ADR-0011: Build and release via hello-pear-electron patterns
- **Status:** Superseded in primary path by [ADR-0013](./0013-bare-pear-only-runtime-and-distribution.md) (Bare/Pear standalone + pear stage)
- **Date:** 2026-07-30
- **Superseded:** 2026-07-30
## Context
Distribution must support multi-platform installs and P2P OTA updates without central app stores as a hard requirement. Originally Electron Forge was assumed.
## Decision (historical)
Copy **hello-pear-electron** patterns (Electron Forge makers, make-pear-app, etc.).
## Supersession
**Primary product distribution is now Bare/Pear-only** per [ADR-0013](./0013-bare-pear-only-runtime-and-distribution.md):
- `hello-pear-bare` + `bare-build --standalone` for single executables
- pear stage → seed → provision → multisig for OTA drives
- Electron Forge is **not** the default CI release path
Pear deploy layers (stage/provision/multisig) and `upgrade` pear links remain valid; only the **shell and binary packing** change.
## Consequences
See ADR-0013.
### Follow-ups
- [ ] Phase 5: bare-build matrix + pear stage (not Electron makers as primary)
@@ -0,0 +1,32 @@
# ADR-0012: Apache-2.0 license; no AGPL hard dependencies
- **Status:** Accepted
- **Date:** 2026-07-30
## Context
Holesail (ideal TCP tunnel) is AGPL-3.0. PearDock aligns AGPL with Holesail. Flying Jib targets Holepunch-friendly **Apache-2.0** distribution and contribution.
## Decision
1. Project license: **Apache-2.0**.
2. Do **not** add AGPL packages (including `holesail`) as runtime hard dependencies.
3. Reimplement needed tunnel behavior with HyperDHT under Apache-2.0 (ADR-0006).
4. Any future AGPL exception requires a superseding ADR and explicit owner approval.
## Consequences
### Positive
- Clear contribution and redistribution story
- Aligns with most Holepunch modules
### Negative / tradeoffs
- Cannot drop in holesail; must maintain thin tunnel code
- Must watch transitive licenses (Prismarine is generally permissive — verify on install)
### Follow-ups
- [ ] Phase 5 optional license CI check
- [ ] SBOM note when packaging
@@ -0,0 +1,117 @@
# ADR-0013: Bare/Pear-only runtime and single-executable distribution
- **Status:** Accepted
- **Date:** 2026-07-30
- **Supersedes:** [ADR-0004](./0004-process-model-electron-bare-squid.md) (process model)
- **Amends:** [ADR-0002](./0002-choose-flying-squid-as-server-core.md) (no Node child), [ADR-0011](./0011-build-release-hello-pear-electron.md) (release path)
## Context
Phase 0 assumed a hybrid process model: Electron (Node) main + Bare worker + **Node child** for Flying Squid, with CI/release patterns from `hello-pear-electron` (Electron Forge multi-maker packages).
That model has serious product and distribution problems for Flying Jib:
1. **End users / CI artifacts must not require a system Node.js install.** Spawning `node` for Squid reintroduces Node as an app-level runtime.
2. **We want single distributable executables** as Pear/Bare apps (`bare-build --standalone`, pear stage/seed/OTA) — one binary (or app bundle) per platform/arch, not “install Node + run our app.”
3. Holepunchs first-class path for this is **Bare + pear-runtime + bare-build / pear deploy**, exemplified by `hello-pear-bare` and peardocks Bare standalone server packing (`bare-pack` + `bare-node-runtime` + `bare-runtime` prebuilds).
4. Hybrid Electron+Node+Bare triples packaging surface area (asar, prune prebuilds, Node child next to Electron, two update stories).
GUI remains desirable later, but **runtime authority and release shape must be Bare/Pear-first**. Any UI shell must not reintroduce a Node.js requirement for Squid or core logic.
## Decision
### 1. Runtime: Bare only (no app-level Node.js)
- **All production application code** (control plane, Hyperswarm/HyperDHT, tunnels, Autobase mesh, Flying Squid lifecycle, invites) runs on **Bare**.
- **Do not** spawn a system or bundled `node` process for Squid or any other core component.
- **Do not** require end users to install Node.js.
- Dev machines may use Node **only** as a host tooling aid (npm install scripts, optional CI helpers) where Holepunch templates still use Node to *invoke* `bare-build` — that is build-time, not runtime.
### 2. Flying Squid on Bare
- Keep Flying Squid as the server core ([ADR-0002](./0002-choose-flying-squid-as-server-core.md)), but load it **inside Bare** using Holepunch Node-compat patterns:
- [`bare-node-runtime`](https://github.com/holepunchto/bare-node-runtime) (`bare-node-runtime/global` + `imports`) so Node builtins map to Bare modules (`bare-net`, `bare-fs`, …)
- Package `imports` maps as used by peardock Bare standalone packing
- Squid runs **in-process** (or as a **Bare worker thread** via `PearRuntime.run` / Bare workers) — never as `child_process.spawn('node', …)`.
- If a Prismarine dependency is incompatible with Bare after the compatibility spike, fix with thin shims, upstream PRs, or a documented fork — **do not** fall back to Node child without a superseding ADR.
### 3. Process model (replacement for ADR-0004)
| Role | Runtime | Notes |
|------|---------|--------|
| Main app entry | **Bare** | CLI / headless / future UI host entry (`bin.mjs` style) |
| P2P + OTA worker | **Bare** (`pear-runtime` worker pattern from hello-pear-bare) | Hyperswarm, tunnels, Autobase, updater |
| Minecraft authority | **Bare** (same process or Bare worker) | Flying Squid via bare-node-runtime |
| Optional GUI | Pear-compatible UI that does **not** own Squid on Node | Prefer Bare UI/TUI first; any desktop GUI must call into Bare-only backend. Electron is **not** the default shell. |
```text
┌─────────────────────────────────────────────────────────┐
│ Single Bare executable / Pear app │
│ ┌──────────────┐ framed IPC ┌────────────────┐ │
│ │ Main (Bare) │◄─────────────────►│ Worker (Bare) │ │
│ │ UI or CLI │ │ pear-runtime │ │
│ │ Squid mgr │ │ swarm/tunnel │ │
│ │ or in-worker │ │ Autobase │ │
│ └──────┬───────┘ └───────┬────────┘ │
│ │ createMCServer (Bare+compat) │ │
│ ▼ ▼ │
│ Squid listens 127.0.0.1 only HyperDHT world tunnel │
└─────────────────────────────────────────────────────────┘
│ Java Edition → localhost only
```
### 4. Distribution: Pear apps + bare-build standalone executables
**Primary release artifacts:**
1. **Standalone Bare executables** per host via [`bare-build --standalone`](https://github.com/holepunchto/bare-build) (ELF / Mach-O / PE with self-extracting natives) — mirrors `hello-pear-bare` `make:*` scripts.
2. **Pear application drive** deployment: stage → seed → provision → multisig; `package.json` / app `upgrade` pear link for **P2P OTA** via `pear-runtime`.
**CI goals:**
- Matrix of hosts (at minimum): `darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`, `win32-x64` (and `win32-arm64` when practical).
- Each job produces a **single runnable artifact** (standalone binary or platform app bundle from bare-build), plus optional pear stage of the app drive for OTA.
- Template reference shifts from `hello-pear-electron`**`hello-pear-bare`** (+ peardock `bare-standalone` packing lessons for Node-compat deps).
**Explicitly not required for v1 product:**
- Electron Forge makers as the primary distribution path
- System Node.js on the players machine
- “Install Node, then `npm start`” as the supported end-user path
### 5. Local bind and mesh invariants unchanged
[ADR-0005](./0005-local-only-bind-invariant.md), no master servers, HyperDHT tunnels, Autobase mesh — all still apply. Only the **host runtime** for those pieces is Bare.
## Consequences
### Positive
- One runtime story: Bare everywhere in production
- Single-file (or single-app) CI distributables via `bare-build --standalone`
- Pear OTA without a second “Node sidecar” story
- Aligns with Holepunch peardock Bare server packing and hello-pear-bare
### Negative / tradeoffs
- Flying Squid + Prismarine were written for Node; **Bare compatibility is a critical path spike** (OPEN_QUESTIONS Q15)
- Some npm packages may need `imports` maps, stubs, or patches
- Polished multi-window GUI may lag if we deprioritize Electron; CLI/TUI or thin UI first is acceptable
- Crash isolation: no OS process boundary between Squid and P2P unless we use Bare workers carefully
### Follow-ups
- [ ] Spike: load `flying-squid` under Bare + `bare-node-runtime` (listen 127.0.0.1, one join)
- [ ] Scaffold app from `hello-pear-bare` (not hello-pear-electron)
- [ ] Document `imports` map for Squid/Prismarine
- [ ] CI: bare-build standalone matrix + pear stage
- [ ] Update ADR-0002/0004/0011 status links (this ADR)
- [ ] Mark Q7 (Electron packaging) reduced priority; add Bare pack risks
## References
- `hello-pear-bare` — Bare CLI + pear-runtime worker + bare-build standalone
- `bare-build`, `bare-pack`, `bare-node-runtime`, `bare-runtime`
- peardock `scripts/bare-standalone.cjs` — packing Node-shaped servers for Bare
- ADR-0005 local bind; ADR-0006 HyperDHT tunnel; ADR-0012 Apache-2.0