Initial commit: Greenfield vs MIT comparison document with strong recommendation

This commit is contained in:
1b-agent committed 2026-10-08 08:48:30 +00:00
commit 45c8b72d8e
3 files changed
+560

No files matched your search

+24
View File
@@ -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/
+525
View File
@@ -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** |
+11
View File
@@ -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