Initial commit: Greenfield vs MIT comparison document with strong recommendation
This commit is contained in:
commit
45c8b72d8e
3 files changed
+560
No files matched your search
+24
@@ -0,0 +1,24 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
.venv/
|
||||
venv/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Editor
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Build
|
||||
node_modules/
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
@@ -0,0 +1,525 @@
|
||||
# Greenfield (AGPL) vs MIT-Licensed Custom Compositor — Final Comparison & Recommendation
|
||||
|
||||
> **Executive summary.** This document compares two approaches to building
|
||||
> a Wayland-to-HTML5 compositor for the Odoo 20 fork:
|
||||
>
|
||||
> 1. **Option A — Use Greenfield as-is** (AGPL-3.0): faster time-to-market,
|
||||
> battle-tested codebase, but **AGPL contamination forces the entire
|
||||
> Odoo fork to be open-sourced** under AGPL-3.0. **NOT COMPATIBLE with
|
||||
> the user's proprietary goal.**
|
||||
>
|
||||
> 2. **Option B — Build a fully MIT-licensed custom compositor** (this
|
||||
> bundle): reuse Greenfield's 7 MIT libs as building blocks, replace
|
||||
> the 4 AGPL packages with clean-room reimplementations in TypeScript
|
||||
> (browser) and Python (host). **Fully proprietary, but ~6-9 months
|
||||
> of engineering effort.**
|
||||
>
|
||||
> **Final recommendation: Option B (MIT-licensed custom compositor)**.
|
||||
> The user's #1 priority is license purity for a proprietary Odoo fork —
|
||||
> this rules out Option A. With 2 senior engineers in parallel, Option B
|
||||
> is achievable in ~5-6 months to MVP, ~8-9 months to production.
|
||||
|
||||
## TL;DR — Decision matrix
|
||||
|
||||
| Dimension | Option A: Greenfield (AGPL) | Option B: MIT Custom Compositor |
|
||||
|---|---|---|
|
||||
| **License purity** | ❌ **AGPL-3.0 contamination** — entire Odoo fork must be open-sourced | ✅ **Fully proprietary** — MIT/Apache/BSD/LGPL only, with 3 substitutions |
|
||||
| **Time to MVP** | ✅ 1-2 weeks (run as-is in dev) | ❌ ~32 weeks (with 2 engineers in parallel) |
|
||||
| **Time to production** | ⚠️ Never (AGPL blocks shipping) | ❌ ~38 weeks (with 2 engineers) |
|
||||
| **Performance** | ✅ Battle-tested, optimised | ✅ Modern stack (WebGL2 + WebCodecs HW + OffscreenCanvas), should match or exceed Greenfield |
|
||||
| **Maintainability** | ⚠️ Forked from rc1, must track upstream | ✅ Full control, no upstream dependency |
|
||||
| **Sandboxing** | ❌ Zero (apps have full host access) | ✅ bubblewrap + seccomp + systemd-run from day 1 |
|
||||
| **Multi-tenancy** | ❌ Single-user single-session | ✅ Per-Odoo-DB isolation, JWT-scoped sessions |
|
||||
| **Odoo integration** | ⚠️ Custom shell needed (Preact → Odoo OWL) | ✅ Native Odoo 20 OWL shell + backend addon |
|
||||
| **Vendor lock-in** | ❌ Locked to Greenfield's architecture + upstream churn | ✅ Swap any component (e.g. replace pywayland with Smithay Rust) |
|
||||
| **Clean-room legal risk** | N/A (using AGPL code directly) | ⚠️ Must maintain SPEC.md + CLEAN_ROOM_LOG.md as legal defense |
|
||||
| **Total effort** | ~1-2 weeks to dev MVP, **never shippable** | ~32-38 weeks to production MVP |
|
||||
| **Recommendation** | ❌ **REJECT** (license incompatible) | ✅ **ADOPT** (the only viable path) |
|
||||
|
||||
## Detailed comparison
|
||||
|
||||
### 1. License purity (user's #1 priority)
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
**Critical problem**: The 4 user-facing packages are AGPL-3.0:
|
||||
- `@gfld/compositor` (browser compositor library)
|
||||
- `@gfld/compositor-proxy` (native proxy)
|
||||
- `@gfld/compositor-proxy-cli` (proxy CLI)
|
||||
- `@gfld/compositor-shell` (Preact shell — out of scope, user replaces with Odoo)
|
||||
|
||||
**AGPL §13 network-use clause**: "If you modify the Program, your modified
|
||||
version must prominently offer all users interacting with it remotely
|
||||
through a computer network, an opportunity to obtain the source code of
|
||||
your modified version."
|
||||
|
||||
**Impact on Odoo fork**: The Odoo fork is a network service (users access
|
||||
it via browser). If the compositor is AGPL-derivative, the entire Odoo
|
||||
fork must be open-sourced to all users. This **destroys the proprietary
|
||||
value** of the Odoo fork.
|
||||
|
||||
**Additional GPL contaminants found in Greenfield** (Agent T audit):
|
||||
- `@gfld/compositor-ffmpeg-h264` — declared Apache-2.0 but actually
|
||||
GPL-3.0 (FFmpeg built with `--enable-gpl --enable-version3 --enable-nonfree`)
|
||||
- `x264enc` GStreamer plugin — GPL-2.0+ (no dynamic-linking exception)
|
||||
- `gstreamer1.0-libav` on Debian — LGPL source but GPL binary (libavcodec
|
||||
built with `--enable-gpl` and links `libx264.so.164` + `libx265.so.215`)
|
||||
|
||||
**Verdict**: ❌ **NOT VIABLE** for a proprietary product.
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
**License stack** (verified clean by Agent T):
|
||||
|
||||
| Component | License | Compatible? |
|
||||
|---|---|---|
|
||||
| @gfld/common, @gfld/client-protocol, @gfld/compositor-protocol | MIT | ✅ |
|
||||
| @gfld/compositor-wasm (pixman + xkbcommon) | MIT | ✅ |
|
||||
| @gfld/xtsb (optional, XWayland) | MIT | ✅ |
|
||||
| @gfld/client-generator, @gfld/compositor-generator | MIT | ✅ |
|
||||
| pywayland | Apache-2.0 | ✅ |
|
||||
| python-xkbcommon | MIT | ✅ |
|
||||
| PyGObject + GStreamer | LGPL-2.1+ (dynamic linking) | ✅ |
|
||||
| gst-vaapi (vaapih264enc) | LGPL + MIT (libva) | ✅ |
|
||||
| gst-plugins-bad (nvh264enc, openh264enc) | BSD subset | ✅ |
|
||||
| libwayland, libdrm, mesa | MIT | ✅ |
|
||||
| aiohttp | Apache-2.0 | ✅ |
|
||||
| kcp (PyPI) | MIT | ✅ |
|
||||
| PyJWT | MIT | ✅ |
|
||||
| bubblewrap | LGPL-2.0+ (dynamic linking) | ✅ |
|
||||
| libseccomp | LGPL-2.1 | ✅ |
|
||||
| Odoo 20 Community | LGPL-3.0 (separate process) | ✅ |
|
||||
| WebCodecs, WebGL2, OffscreenCanvas | W3C standards | ✅ |
|
||||
| OpenH264 (BSD fallback decoder) | BSD-2-Clause | ✅ |
|
||||
| Custom browser compositor (your code) | PROPRIETARY (clean-room) | ✅ |
|
||||
| Custom Python proxy (your code) | PROPRIETARY | ✅ |
|
||||
| Custom Odoo 20 addon (your code) | PROPRIETARY | ✅ |
|
||||
|
||||
**3 mandatory substitutions** (to avoid GPL contamination):
|
||||
1. **WebCodecs API** replaces `@gfld/compositor-ffmpeg-h264` (GPL)
|
||||
2. **vaapih264enc / nvh264enc / openh264enc** replaces `x264enc` (GPL)
|
||||
3. **Don't install `gstreamer1.0-libav`** (GPL binary on Debian)
|
||||
|
||||
**Clean-room requirement**: The custom browser compositor MUST be
|
||||
written clean-room — Person A writes spec (may read AGPL), Person B
|
||||
implements (must NOT read AGPL). Maintain `SPEC.md` +
|
||||
`CLEAN_ROOM_LOG.md` as legal-defensibility artifacts.
|
||||
|
||||
**Verdict**: ✅ **FULLY PROPRIETARY VIABLE** with 3 substitutions + clean-room discipline.
|
||||
|
||||
### 2. Time to MVP
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
- **Week 1-2**: Run Greenfield's compositor-proxy-cli in Docker, embed
|
||||
the compositor-shell in an Odoo iframe, launch `gtk4-demo`, see it
|
||||
render.
|
||||
- **Week 3-4**: Replace compositor-shell with minimal Odoo OWL component.
|
||||
- **Week 5-6**: Integrate with Odoo auth, add app launcher.
|
||||
|
||||
**Total to dev MVP**: ~4-6 weeks.
|
||||
|
||||
**But**: This is dev-only. You cannot ship this without open-sourcing
|
||||
your Odoo fork. So time-to-MVP is irrelevant — the option is non-viable.
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
| Phase | Weeks (1 dev) | Weeks (2 devs parallel) |
|
||||
|---|---|---|
|
||||
| Phase 0: Spike (validate libwayland ↔ asyncio) | 1 | 1 |
|
||||
| Phase 1: Browser compositor MVP (clean-room TS) | 25 | 15 (one on compositor, one on transport+input) |
|
||||
| Phase 2: Python proxy MVP (aiohttp + pywayland + GStreamer) | 3.5 | 3.5 (parallel with Phase 1) |
|
||||
| Phase 3: Odoo integration (OWL shell + backend addon + JWT) | 3.5 | 3.5 (parallel with Phase 1) |
|
||||
| Phase 4: Sandboxing v1 (bubblewrap + seccomp) | 1.5 | 1.5 |
|
||||
| Phase 5: Polish & testing | 3 | 3 |
|
||||
| **TOTAL to MVP** | **~37.5 weeks (~9 months)** | **~24 weeks (~6 months)** |
|
||||
| Phase 6 (optional): XWayland + multi-tenant + portal | +9 | +6 |
|
||||
|
||||
**Critical path**: Browser compositor (Phase 1) is the bottleneck.
|
||||
With 2 senior engineers (one on compositor core + roles, one on
|
||||
transport + input + Python proxy + Odoo integration), MVP in ~6 months.
|
||||
|
||||
### 3. Performance
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
- WebGL1 (no OffscreenCanvas, no WebGL2)
|
||||
- Main-thread WebGL (jank on heavy frames)
|
||||
- WebCodecs with hardware decode **disabled** (FIXME: "frame offset is wrong")
|
||||
- FFmpeg Wasm fallback (GPL — can't ship anyway)
|
||||
- H.264 encoding: x264 software (GPL — can't ship anyway)
|
||||
- No adaptive bitrate (EncoderFeedback data produced but not consumed)
|
||||
- Single-threaded JS compositor
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
- **WebGL2** (uniform buffer objects, simplified shaders)
|
||||
- **OffscreenCanvas + Web Workers** (render in worker, never block main thread)
|
||||
- **WebCodecs with hardware decode enabled** (fix Greenfield's FIXME)
|
||||
- **OpenH264 BSD Wasm fallback** (replaces Greenfield's GPL FFmpeg Wasm)
|
||||
- **Hardware-accelerated encoding by default** (vaapih264 on Intel/AMD, nvh264 on NVIDIA)
|
||||
- **Adaptive bitrate** (consumes EncoderFeedback data Greenfield ignores)
|
||||
- Multi-threaded (render worker + decode worker)
|
||||
|
||||
**Expected performance**: Should match or exceed Greenfield. Hardware
|
||||
decode + hardware encoding + worker offload should give 2-3× improvement
|
||||
on heavy content.
|
||||
|
||||
### 4. Maintainability
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
- Forked from `1.0.0-rc1` — must track upstream commits manually
|
||||
- 3 native Node addons (`.node` files, Linux-x64 only, ABI-locked to Node major)
|
||||
- Heavy build toolchain (Yarn 4 + CMake + Ninja + Meson + pkg-config + 2 Emscripten versions)
|
||||
- Solo maintainer (Erik De Rijcke) — single point of failure
|
||||
- No CHANGELOG, no SECURITY.md, no CONTRIBUTING.md
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
- Full control over the codebase
|
||||
- No native Node addons (pure Python + TypeScript)
|
||||
- Standard build toolchain (npm/pnpm + pip + standard tsc/aiohttp)
|
||||
- Python team can maintain Python parts; TS team can maintain browser parts
|
||||
- No upstream churn to track
|
||||
|
||||
### 5. Sandboxing & security
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
**Zero sandboxing** (Agent S analysis, pitfall M):
|
||||
- Plain `child_process.spawn()` with no isolation
|
||||
- Apps have full host filesystem access
|
||||
- Apps share the proxy's env (could leak DB passwords, Odoo session cookies)
|
||||
- No network isolation
|
||||
- No resource limits
|
||||
- Basic Auth (single replayable credential)
|
||||
- Client-generated `compositorSessionId` (spoofable)
|
||||
|
||||
**Verdict**: ❌ **Cannot ship in production** without major security work.
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
**Sandboxing from day 1** (Agent S analysis):
|
||||
- `bubblewrap --unshare-all --clearenv --seccomp <memfd>`
|
||||
- `--ro-bind /usr /usr`, minimal `/etc` whitelist, `$HOME` overlay
|
||||
- `--dev-bind /dev/dri/renderD128` (single GPU render node)
|
||||
- `--ro-bind $HOST_XDG/wayland-N /run/user/<UID>/wayland-N` (single socket only)
|
||||
- `--uid 100000-165535` per-app (UID remap via `/etc/subuid`)
|
||||
- `--unshare-net` by default (most apps don't need network)
|
||||
- `systemd-run --scope -p MemoryMax=1G -p CPUQuota=200% -p TasksMax=256`
|
||||
- JWT auth (HS256, 15-min expiry, signed by Odoo backend)
|
||||
- Server-generated `compositor_session_id` (UUID, not client-generated)
|
||||
|
||||
**Effort**: ~7-9 dev-days for v1 (shippable), +4-9 days for v2 (XWayland sandbox + veth networking).
|
||||
|
||||
**Verdict**: ✅ **Production-grade sandboxing** out of the box.
|
||||
|
||||
### 6. Multi-tenancy
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
Single-user single-session. No multi-tenant isolation. Each Odoo
|
||||
database would need its own proxy instance, manually configured.
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
- One compositor proxy per Odoo database (Docker container per tenant)
|
||||
- JWT `db` claim scopes every WS to one Odoo database
|
||||
- Per-session wayland socket (`$XDG_RUNTIME_DIR/wayland-N`)
|
||||
- Per-session forked worker process
|
||||
- Per-app UID remap (100000-165535)
|
||||
- Per-app cgroup limits (MemoryMax, CPUQuota, TasksMax)
|
||||
- Optional: per-tenant Docker container with `--cpus` and `--memory` limits
|
||||
|
||||
### 7. Odoo integration depth
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
- Custom shell needed: replace Preact compositor-shell with Odoo OWL component
|
||||
- Auth bridging: Greenfield's Basic Auth → Odoo session (fragile)
|
||||
- No audit log integration
|
||||
- No multi-tenancy
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
- **Native Odoo 20 OWL shell** (ir.actions.client with target=fullscreen)
|
||||
- **JWT auth** issued by Odoo backend (HS256, 15-min expiry)
|
||||
- **Audit log** model (`compositor.audit.log`, append-only) — every app
|
||||
launch/terminate/crash logged with user, timestamp, app, duration
|
||||
- **App catalog** model (`compositor.app`) — per-user allowed apps list,
|
||||
filtered by `res.groups`
|
||||
- **Session model** (`compositor.session`) — mail.thread mixin for
|
||||
tracking
|
||||
- **Nginx reverse proxy** for single-origin HTTPS (eliminates CORS)
|
||||
- **Docker Compose** with GPU passthrough
|
||||
|
||||
### 8. Vendor lock-in
|
||||
|
||||
#### Option A — Greenfield (AGPL)
|
||||
|
||||
- Locked to Greenfield's architecture (browser compositor + Node proxy)
|
||||
- Locked to Node.js (N-API addons ABI-locked to Node major)
|
||||
- Locked to Linux-x64 (no ARM64)
|
||||
- Locked to Greenfield's wire protocol (no schema versioning)
|
||||
- Must track upstream rc1 → 1.0 transitions
|
||||
|
||||
#### Option B — MIT Custom Compositor
|
||||
|
||||
- Swap any component:
|
||||
- Replace pywayland with Smithay (Rust) if Python doesn't work out
|
||||
- Replace aiohttp with FastAPI if needed
|
||||
- Replace GStreamer with PyAV (FFmpeg Python bindings) if needed
|
||||
- Replace WebGL2 with WebGPU when browser support is widespread
|
||||
- No Node.js dependency (pure Python + TypeScript)
|
||||
- Linux-x64 + ARM64 (pywayland ships ARM64 wheels)
|
||||
- Can version your own wire protocol from commit #1
|
||||
|
||||
## Effort estimates (detailed, person-weeks)
|
||||
|
||||
### Option A — Greenfield (AGPL)
|
||||
|
||||
| Phase | Person-weeks | Notes |
|
||||
|---|---|---|
|
||||
| Dev MVP (run as-is in Docker) | 1-2 | Cannot ship — AGPL |
|
||||
| Replace shell with Odoo OWL | 2 | Cannot ship — AGPL |
|
||||
| Auth integration | 1 | Cannot ship — AGPL |
|
||||
| Sandboxing (NEW, not in Greenfield) | 1.5 | Cannot ship — AGPL |
|
||||
| Multi-tenancy | 1.5 | Cannot ship — AGPL |
|
||||
| **TOTAL** | **~7-8 weeks** | **All wasted — cannot ship** |
|
||||
|
||||
### Option B — MIT Custom Compositor
|
||||
|
||||
#### Single engineer, sequential
|
||||
|
||||
| Phase | Weeks | Deliverable |
|
||||
|---|---|---|
|
||||
| Phase 0: Spike | 1 | Validate libwayland ↔ asyncio integration (5-line cffi shim) |
|
||||
| Phase 1: Browser compositor MVP | 25 | Clean-room TypeScript, ~13,400 LOC |
|
||||
| Phase 1a: Surface state stack | 3 | Surface.ts, SurfaceRole.ts, Subsurface.ts (1,200 LOC) |
|
||||
| Phase 1b: Rendering pipeline | 3 | Renderer.ts, Scene.ts, View.ts, Output.ts, shaders (1,800 LOC, WebGL2) |
|
||||
| Phase 1c: Buffers | 1.5 | Shm.ts, BufferContents.ts, ImageBitmapBuffer.ts (600 LOC) |
|
||||
| Phase 1d: Transport + decoders | 4 | Channel.ts, kcp.ts, ReconnectingWebSocket.ts, WebCodecsFrameDecoder.ts, OpenH264FrameDecoder.ts (3,500 LOC + 500 LOC) |
|
||||
| Phase 1e: Input | 3 | Seat.ts, Keyboard.ts, Pointer.ts, Touch.ts, Xkb.ts (2,500 LOC) |
|
||||
| Phase 1f: Roles (xdg-shell) | 3 | XdgWmBase.ts, XdgSurface.ts, XdgToplevel.ts, XdgPopup.ts, XdgPositioner.ts (1,800 LOC, HIGH RISK) |
|
||||
| Phase 1g: Data device + clipboard + DnD | 1.5 | DataDeviceManager.ts, DataSource.ts, DataOffer.ts, PrimarySelectionDeviceManager.ts (NEW) (600 LOC) |
|
||||
| Phase 1h: Desktop policy | 1.5 | Desktop.ts, FloatingDesktopSurface.ts (800 LOC) |
|
||||
| Phase 1i: Math | 0.5 | Mat4.ts, Vec4.ts, Point.ts, Size.ts, Rect.ts (500 LOC) |
|
||||
| Phase 1j: UserShellApi | 0.5 | UserShellApi.ts (120 LOC) |
|
||||
| Phase 1k: Browser glue | 2 | input.ts, pointer.ts, touch.ts (NEW), dnd.ts, selection.ts (750 LOC) |
|
||||
| Phase 1l: Core | 0.5 | Session.ts, Globals.ts (200 LOC) |
|
||||
| Phase 2: Python proxy MVP | 3.5 (~17 dev-days) | aiohttp + pywayland + GStreamer, ~2,880 LOC Python |
|
||||
| Phase 2a: aiohttp WS server (9 endpoints) | 3 days | /signal, /channel, /mkfifo, /mkstemp-mmap, /read-fd, etc. |
|
||||
| Phase 2b: Channel/ARQChannel/SimpleChannel port | 1.5 days | Clean-room from spec |
|
||||
| Phase 2c: kcp PyPI package integration | 0.5 days | RealistikDash/kcp.py |
|
||||
| Phase 2d: NativeAppContext (signaling, escalation) | 2 days | 10-min SIGHUP grace, SIGTERM escalation |
|
||||
| Phase 2e: ProxyInputOutput (FD workaround) | 2 days | os.pipe(), os.memfd_create(), asyncio streams |
|
||||
| Phase 2f: libwayland event-loop integration | 1 day | 5-line cffi shim for wl_event_loop_get_fd |
|
||||
| Phase 2g: Multiprocessing + FD passing | 1.5 days | multiprocessing.reduction.send_handle |
|
||||
| Phase 2h: GStreamer encoder thread + marshalling | 2 days | GLib MainLoop in separate thread, asyncio.run_coroutine_threadsafe |
|
||||
| Phase 2i: Reconnection & lifecycle | 1 day | |
|
||||
| Phase 2j: Tests | 3 days | pytest + pytest-asyncio |
|
||||
| Phase 3: Odoo integration | 3.5 (~18 dev-days) | OWL shell + backend addon + JWT + Nginx + Docker |
|
||||
| Phase 3a: Odoo addon skeleton | 2 days | Models + controllers + views + security |
|
||||
| Phase 3b: JWT issuance + audit log | 1.5 days | HS256, 15-min expiry, pyjwt |
|
||||
| Phase 3c: OWL 3 fullscreen client action | 2.5 days | ir.actions.client, target=fullscreen, **must use proxy() not useState()** |
|
||||
| Phase 3d: Browser compositor integration | 2 days | userShell.actions.initScene |
|
||||
| Phase 3e: JWT middleware + WS handshake | 1.5 days | |
|
||||
| Phase 3f: Audit POSTback + Nginx + Docker + GPU | 2 days | |
|
||||
| Phase 3g: Multi-tenant | 1.5 days | Per-DB proxy spawning + db claim |
|
||||
| Phase 3h: Tests | 2 days | HttpCase + TransactionCase |
|
||||
| Phase 3i: Documentation + buffer | 3 days | |
|
||||
| Phase 4: Sandboxing v1 | 1.5 (~7-9 dev-days) | bubblewrap + seccomp + systemd-run |
|
||||
| Phase 4a: bwrap integration | 2-3 days | |
|
||||
| Phase 4b: seccomp profile + compile | 1-2 days | Docker default profile + CLONE_NEWUSER allow |
|
||||
| Phase 4c: systemd-run cgroup wrapper | 1 day | MemoryMax=1G, CPUQuota=200%, TasksMax=256 |
|
||||
| Phase 4d: Wayland socket ownership fix | 0.5 days | chmod 0660 + sandbox group |
|
||||
| Phase 4e: GPU passthrough testing | 1 day | /dev/dri/renderD128 only |
|
||||
| Phase 4f: Schema + docs | 1 day | |
|
||||
| Phase 5: Polish & testing | 3 | Tests, hardening, docs |
|
||||
| **MVP TOTAL** | **~37.5 weeks** | Single-tenant, single-app, fully proprietary, sandboxed |
|
||||
| Phase 6 (optional): XWayland | +8 | ~5,000 LOC TS, uses @gfld/xtsb (MIT) |
|
||||
| Phase 6 (optional): Multi-tenant portal | +2 | XDG Desktop Portal (FileChooser/Secret) |
|
||||
| Phase 6 (optional): Per-tenant veth networking | +2 | nftables filter |
|
||||
| **GRAND TOTAL (with Phase 6)** | **~49.5 weeks** | Production-ready |
|
||||
|
||||
#### Two engineers in parallel
|
||||
|
||||
| Phase | Weeks | Notes |
|
||||
|---|---|---|
|
||||
| Phase 0: Spike | 1 | Both engineers validate together |
|
||||
| Phase 1 (Eng A: compositor core + roles) + Phase 2+3 (Eng B: transport + Python + Odoo) | 25 (Eng A is critical path) | Parallel |
|
||||
| Phase 4 (Eng B: sandboxing) + Phase 5 (Eng A: tests) | 3 | Parallel |
|
||||
| **MVP TOTAL** | **~29 weeks (~7 months)** | |
|
||||
| Phase 6 (optional): XWayland (Eng A) + multi-tenant (Eng B) | +6 | Parallel |
|
||||
| **GRAND TOTAL (with Phase 6)** | **~35 weeks (~9 months)** | |
|
||||
|
||||
#### Three engineers in parallel (aggressive)
|
||||
|
||||
| Phase | Weeks | Notes |
|
||||
|---|---|---|
|
||||
| Phase 0: Spike | 1 | All three validate together |
|
||||
| Phase 1 (Eng A: compositor + roles) + Phase 2 (Eng B: Python proxy) + Phase 3 (Eng C: Odoo integration) | 25 (Eng A is critical path) | Fully parallel |
|
||||
| Phase 4 (Eng B: sandboxing) + Phase 5 (Eng A + C: tests) | 2 | Parallel |
|
||||
| **MVP TOTAL** | **~28 weeks (~7 months)** | |
|
||||
| Phase 6 (optional): XWayland (Eng A) + portal (Eng B) + veth (Eng C) | +5 | Parallel |
|
||||
| **GRAND TOTAL (with Phase 6)** | **~33 weeks (~8 months)** | |
|
||||
|
||||
## Final recommendation
|
||||
|
||||
### Strong recommendation: Option B (MIT Custom Compositor)
|
||||
|
||||
**The user's #1 priority is license purity for a proprietary Odoo
|
||||
fork.** This single requirement rules out Option A entirely — AGPL §13
|
||||
would force the entire Odoo fork to be open-sourced, destroying the
|
||||
proprietary value.
|
||||
|
||||
**Option B is the only viable path.** With 3 mandatory substitutions
|
||||
(no GPL x264, no GPL FFmpeg Wasm, no Debian gst-libav) + clean-room
|
||||
discipline for the browser compositor, the entire stack is
|
||||
MIT/Apache/BSD/LGPL — fully proprietary-compatible.
|
||||
|
||||
### Effort justification
|
||||
|
||||
The user is essentially building a Wayland compositor from scratch.
|
||||
This is a significant engineering effort (~25-30 dev-weeks for the
|
||||
browser compositor alone), but:
|
||||
|
||||
1. **It's a one-time cost.** Once built, the compositor is yours to
|
||||
maintain and extend indefinitely.
|
||||
2. **The browser compositor is the bulk of the work** (~60% of total
|
||||
effort). The Python proxy + Odoo integration + sandboxing are
|
||||
relatively quick (~8.5 weeks total).
|
||||
3. **The clean-room approach is legally defensible.** With proper
|
||||
SPEC.md + CLEAN_ROOM_LOG.md artifacts, the user can demonstrate
|
||||
non-infringement even if Greenfield's maintainer alleges
|
||||
derivative-work infringement.
|
||||
4. **The modernized stack is better than Greenfield** — WebGL2,
|
||||
WebCodecs HW decode, OffscreenCanvas + Workers, adaptive bitrate,
|
||||
sandboxing, multi-tenancy, Odoo integration. The user gets a
|
||||
better product, not just a license-clean one.
|
||||
|
||||
### Phased rollout recommendation
|
||||
|
||||
To minimize risk and validate assumptions early:
|
||||
|
||||
**Phase 0 (Week 1): Spike**
|
||||
- Validate libwayland ↔ asyncio integration (5-line cffi shim)
|
||||
- Validate `kcp` PyPI package works with aiohttp WebSocket
|
||||
- Validate WebCodecs `prefer-hardware` decode works on target hardware
|
||||
- If any of these fail, reassess before committing to the full plan
|
||||
|
||||
**Phase 1 (Weeks 2-15, 2 engineers): Browser compositor MVP**
|
||||
- Eng A: Surface + Roles (xdg-shell state machine)
|
||||
- Eng B: Transport + Input + Decoders
|
||||
- Target: A single Linux app renders in a `<canvas>` via the custom compositor
|
||||
|
||||
**Phase 2 (Weeks 2-6, parallel with Phase 1): Python proxy MVP**
|
||||
- Eng C: aiohttp + pywayland + GStreamer + bubblewrap sandboxing
|
||||
- Target: Python proxy can spawn a sandboxed Linux app and stream its
|
||||
surface to the browser compositor
|
||||
|
||||
**Phase 3 (Weeks 7-10, after Phase 2): Odoo integration**
|
||||
- Eng C: OWL shell + backend addon + JWT + Nginx + Docker
|
||||
- Target: End-to-end: user clicks app in Odoo, app launches sandboxed,
|
||||
renders in Odoo canvas
|
||||
|
||||
**Phase 4 (Weeks 11-13): Polish & testing**
|
||||
- All engineers: tests, hardening, docs
|
||||
- Target: Production-ready MVP
|
||||
|
||||
**Phase 5 (Weeks 14+, optional): XWayland + multi-tenant + portal**
|
||||
- Add X11 app support, per-tenant isolation, XDG Desktop Portal
|
||||
|
||||
### Critical success factors
|
||||
|
||||
1. **Hire 2-3 senior engineers** with Wayland + WebGL + TypeScript +
|
||||
Python expertise. The browser compositor is the critical path —
|
||||
don't understaff it.
|
||||
|
||||
2. **Set up clean-room discipline from day 1.** Designate Person A
|
||||
(spec author, may read AGPL) and Person B (implementer, must NOT
|
||||
read AGPL). Maintain `SPEC.md` + `CLEAN_ROOM_LOG.md`.
|
||||
|
||||
3. **Add CI/CD license hygiene gates from day 1.** Docker image audit,
|
||||
npm license-checker, pip-licenses, gst-inspect check. Catch GPL
|
||||
contamination early.
|
||||
|
||||
4. **Engage legal counsel** before starting the clean-room process.
|
||||
This bundle is engineering analysis, not legal advice.
|
||||
|
||||
5. **Test with real Linux apps early.** Don't wait until Phase 4 to
|
||||
test with GTK4/Qt6 apps. Bugs in the xdg-shell state machine are
|
||||
subtle and need real apps to surface.
|
||||
|
||||
6. **Skip XWayland in MVP.** Most modern GTK4/Qt6 apps are
|
||||
Wayland-native. Add XWayland only if a specific X11-only app is
|
||||
needed.
|
||||
|
||||
7. **Use the kcp PyPI package.** Don't port Greenfield's TS KCP to
|
||||
Python — the Cython wrapper is faster and battle-tested.
|
||||
|
||||
8. **Reuse Greenfield's MIT C files** (westfield-egl.c, wlr_drm.c,
|
||||
wlr_linux_dmabuf_v1.c, etc.) via cffi. ~3,374 lines of MIT C
|
||||
reused verbatim — significant effort savings.
|
||||
|
||||
9. **Use vendored ReconnectingWebSocket** (Pedro Ladaria, MIT, 514
|
||||
lines TS). Don't reinvent.
|
||||
|
||||
10. **Plan for 6-9 months**, not 3. The browser compositor is a
|
||||
significant piece of engineering. Underestimating it is the most
|
||||
common failure mode for Wayland compositor projects.
|
||||
|
||||
## What's at stake
|
||||
|
||||
**If the user chooses Option A (AGPL)**:
|
||||
- They cannot ship a proprietary product.
|
||||
- They must open-source their entire Odoo fork.
|
||||
- Their investment in Odoo customizations becomes a gift to competitors.
|
||||
- The product is non-viable as a commercial offering.
|
||||
|
||||
**If the user chooses Option B (MIT)**:
|
||||
- They invest ~6-9 months of engineering effort.
|
||||
- They get a fully proprietary Wayland-to-HTML5 compositor.
|
||||
- They get a modernized stack (WebGL2, WebCodecs HW, OffscreenCanvas,
|
||||
sandboxing, multi-tenancy, Odoo integration).
|
||||
- They have full control over their IP and roadmap.
|
||||
- The product is viable as a commercial offering.
|
||||
|
||||
**The choice is clear: Option B.**
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Quick reference cards
|
||||
|
||||
### Option A — Greenfield (AGPL) quick reference
|
||||
|
||||
| Aspect | Detail |
|
||||
|---|---|
|
||||
| Repo | https://github.com/udevbe/greenfield |
|
||||
| Version | 1.0.0-rc1 |
|
||||
| License | AGPL-3.0 (4 packages) + MIT (7 libs) + GPL (compositor-ffmpeg-h264, hidden) |
|
||||
| Browser stack | WebGL1, main-thread, FFmpeg Wasm (GPL), WebCodecs HW disabled |
|
||||
| Backend | Node.js + 3 C N-API addons (Linux-x64 only) |
|
||||
| Sandboxing | None |
|
||||
| Multi-tenancy | None |
|
||||
| Odoo integration | Custom shell needed, Basic Auth |
|
||||
| Time to dev MVP | 4-6 weeks |
|
||||
| Time to production | **Never** (AGPL blocks shipping) |
|
||||
| Verdict | ❌ **REJECT** |
|
||||
|
||||
### Option B — MIT Custom Compositor quick reference
|
||||
|
||||
| Aspect | Detail |
|
||||
|---|---|
|
||||
| Browser stack | WebGL2 + OffscreenCanvas + Web Workers + WebCodecs (HW enabled) + OpenH264 BSD Wasm fallback |
|
||||
| Backend | Python (aiohttp + pywayland + PyGObject/GStreamer + bubblewrap + seccomp) |
|
||||
| License | MIT/Apache/BSD/LGPL only, fully proprietary-compatible |
|
||||
| Sandboxing | bubblewrap + seccomp + systemd-run + cgroups v2, from day 1 |
|
||||
| Multi-tenancy | Per-Odoo-DB Docker container, JWT-scoped sessions |
|
||||
| Odoo integration | Native OWL shell + backend addon + JWT (HS256) + Nginx + Docker Compose |
|
||||
| Effort (2 engineers) | ~6 months to MVP, ~9 months to production |
|
||||
| Effort (3 engineers) | ~7 months to MVP, ~8 months to production |
|
||||
| Clean-room requirement | Mandatory (SPEC.md + CLEAN_ROOM_LOG.md) |
|
||||
| GPL contaminants to avoid | 3 (FFmpeg Wasm, x264enc, gst-libav) |
|
||||
| Verdict | ✅ **ADOPT** |
|
||||
@@ -0,0 +1,11 @@
|
||||
# Greenfield (AGPL) vs MIT-Licensed Custom Compositor — Comparison
|
||||
|
||||
This repo holds the head-to-head decision matrix comparing:
|
||||
1. **Option A — Use Greenfield as-is** (AGPL-3.0): faster time-to-market, but AGPL contamination forces the entire Odoo fork to be open-sourced.
|
||||
2. **Option B — Build a fully MIT-licensed custom compositor** (this bundle's recommended path).
|
||||
|
||||
**Final recommendation: Option B**. See `Greenfield-vs-MIT-Comparison.md` for the full analysis with person-week estimates per phase.
|
||||
|
||||
## Related repos
|
||||
- `one-os-dev-wayland-html5-compositor-greenfield-analysis` — deep analysis of Greenfield (the reference implementation)
|
||||
- `one-os-dev-wayland-html5-compositor-mit-compositor-analysis` — architecture & build plan for our MIT-licensed alternative
|
||||
Reference in new issue
Block a user