# 0025: GPUI's GPL dependency is patched out, not tolerated Status: accepted. Amends decision 0023, which chose the pinned Zed revision without noticing what came with it. Does not change that revision. ## The decision `ztracing` is redirected, by a `[patch]` table in the root manifest, at `crates/lumbridge-ztracing-shim` — a first-party, zero-dependency, no-op crate under Apache-2.0. Nothing else about decision 0023's pin changes. ## The problem Lumbridge is Apache-2.0, and `DISTRIBUTION.md` treats the licence closure of everything the product links as a hard gate. Decision 0023 replaced published `gpui` releases with a pinned revision of Zed's monorepo, and a monorepo revision does not bring only the crates you named. `crates/gpui/Cargo.toml` at `ce48461` carries: ```toml ztracing.workspace = true ``` Unconditional. Not optional. Not behind a feature. `ztracing` is **GPL-3.0-or-later**, and it pulls `zlog` and `ztracing_macro`, both also GPL-3.0-or-later. `sum_tree` asks for `ztracing` as well. The path is entirely inside the build that ships: ```text lumbridge -> gpui_platform -> gpui_linux -> gpui -> ztracing -> zlog -> ztracing_macro ``` This is not an `--all-features` artefact and not a dev-dependency. It is the ordinary Linux build. `cargo deny check licenses` failed on it, exit 4, three rejections, each `license is not explicitly allowed`. That is the second thing decision 0023 got wrong by reading manifests instead of resolving a graph. The first was believing there were two Zed Git sources when there are five. Both were caught by a gate that had never been run, and both argue the same point: the transitive closure is the only thing that answers a licensing question. ## What was rejected **Relax `deny.toml`.** Adding GPL-3.0-or-later to the allow list would trade the product's licence for a green build. The gate exists precisely to stop that being done quietly. **Turn the feature off.** There is no feature. `ztracing.workspace = true` has no `optional = true` beside it, and no `cfg` guards its use sites. **Drop GPUI.** That throws away decision 0023 and, until `lumbridge-toolkit` exists, the product's ability to draw a window. **Vendor and relicense.** Not available: GPL is GPL. ## What was chosen, and why it is small Every use of `ztracing` and `zlog` across the eighteen Zed packages in the resolved graph, found by grepping the vendored checkout rather than the manifests: - `gpui/src/svg_renderer.rs`, two sites: `#[ztracing::instrument(skip_all)]` - `sum_tree/src/sum_tree.rs` and `sum_tree/src/cursor.rs`: `use ztracing::instrument;`, then seven `#[instrument(skip_all)]` sites - `sum_tree/src/sum_tree.rs:1401`: `zlog::init_test()`, inside `#[cfg(test)]`, behind a dev-dependency Cargo never resolves for a non-workspace package — which is why no `zlog` shim is needed and why `zlog` leaves the lockfile entirely Nine attribute sites, all `skip_all`, and nothing else. So the shim is one attribute proc-macro that returns its input unchanged. Upstream's own crate compiles to almost exactly that whenever the `ztracing` cfg is off — which is every build that is not a Tracy profiling build — so no shipping behaviour is lost. Lumbridge ships no telemetry by default in any case. Because `zlog` and `ztracing_macro` were reachable only through `ztracing`, patching the one package removes all three: they no longer appear in `Cargo.lock`. ## How it is held `scripts/workspace-guard.sh` gained a third gate. It asserts, against `Cargo.lock` rather than the manifest, that no `ztracing`, `zlog` or `ztracing_macro` resolves to a Zed source, and that the `[patch]` table is still in `Cargo.toml`. `cargo deny` already checks this, so the duplication is deliberate. `scripts/ci.sh` downgrades a missing `cargo-deny` to a warning unless `LUMBRIDGE_CI_STRICT=1`, and that arrangement is how the licence closure went ungated once already — green on a runner that had never installed the tool. The guard needs no tool and runs in milliseconds. It is what makes deleting the patch a build failure rather than a silent relicensing of the product. A `[patch]` is an unusually quiet thing to lose: delete the table and everything still compiles, still passes every test, and is GPL again. ## The unrelated failure this exposed Removing the three GPL rejections left one behind that had been sitting beside them: `libbz2-rs-sys` under the `bzip2-1.0.6` licence, reached through `bzip2 -> compression-codecs -> async-compression -> http_client -> gpui`. It is BSD-style and permissive — retain the notice, do not misrepresent the origin, no warranty — with no copyleft and no source-disclosure term, and it is allowed in `deny.toml` with that reasoning written down. It is recorded here because it was never reported as a separate finding; it was simply the fourth line of a failure everyone read as being about GPL. ## What the next revision bump must check Whether upstream started using a `ztracing` symbol the shim does not provide. The shim is a proc-macro crate, which can export nothing except proc macros, so `ztracing::Span`, `ztracing::info_span!`, `ztracing::init()`, `ztracing::Level` and `ztracing::field` all fail to resolve at compile time and name this crate in the error. There is no silent fallback. The fix then is not to widen the shim by reflex. If the new use is another zero-cost annotation, add the matching no-op — which means splitting the shim into a library crate and a proc-macro crate, since one package cannot be both. If upstream has started routing real telemetry through `ztracing`, that is a decision record, because no telemetry is enabled by default here. And run `cargo deny check licenses sources` at the new revision before anything else. A monorepo pin can acquire a *different* GPL crate on a different path, and reading the manifests of the crates you added will not find it.