# Design ## Context See proposal.md. We need a Podman container that runs CUPS for the Brother HL-4150CDN network printer and shares it over IPP/AirPrint. Facts established while exploring the device at `192.168.100.7`: - The printer is a Brother HL-4150CDN (`Ver.1.22`) with PCL6 and **BR-Script3 (PostScript 3)** emulation — `@PJL INFO CONFIG` lists `POSTSCRIPT`. - Open services: `:9100` (raw/AppSocket), `:515` (LPR/LPD), `:631` (IPP/IPPS) and `:80` (Brother web UI). It has one paper cassette plus the MP tray. - A raw PostScript job sent to `:9100` is interpreted by the printer, and a full CUPS job with `Duplex=DuplexNoTumble BRPrintQuality=Color` printed correctly (duplex, colour). An earlier iteration used Brother's Linux packages. That vendor CUPS chain is broken in `debian:bookworm-slim`: `filterhl4150cdn` needs `file` (and `a2ps` as a fallback), which are absent, so the filter exits 1 and emits zero bytes. That chain also rasterises locally (Ghostscript → `ppmraw` → `brhl4150cdnfilter`) and stores per-queue options in a single global file (`brhl4150cdnrc`), which is heavy and racy. The packages have since been removed from the repository. Crucially, the Brother **vendor** PPD (`brhl4150cdn.ppd`) cannot be used for direct PostScript because its option values are blank (`" "`); all option handling lives in the vendor filter. Brother's **BR-Script3 PPD**, in contrast, encodes every option as PostScript `setpagedevice`. ## Goals / Non-Goals **Goals:** - Build a working CUPS image for Podman with no 32-bit dependencies. - Drive the printer with its native PostScript (BR-Script3) interpreter. - Preserve the hardware options the user cares about: paper tray, duplex and colour/mono (plus the other options the PPD exposes). - Share the queue over IPP and advertise it via AirPrint. - Keep the printer address/name runtime-configurable. **Non-Goals:** - Managing multiple printers. - Sharing via SMB/Samba (Windows uses a client-side Brother driver). - Persisting CUPS spool/state beyond the container lifecycle. - TLS for the CUPS web interface. ## Decisions ### Base image and packages Use `debian:bookworm-slim` with `cups`, `cups-client`, `cups-filters`, `avahi-daemon`, `avahi-utils`, `libnss-mdns`, `dbus`, `ghostscript` and `poppler-utils`. No `dpkg --add-architecture i386` and no Brother `.deb` packages: the job is converted to PostScript in CUPS and interpreted by the printer, so no vendor binary is needed. _Alternative considered:_ keep Brother's Linux CUPS wrapper + LPR filter. It provides the same options but requires 32-bit libraries, Ghostscript rasterisation and the missing `file`/`a2ps` tools, and it writes options to a single global config file. Rejected. ### Print path: direct PostScript via the BR-Script3 PPD Install Brother's official BR-Script3 PPD as `/usr/share/cups/model/BR4150_2.PPD` (committed at `assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`, extracted from the vendor Windows driver) and create the queue with it. CUPS's `pstops` filter reads the PPD and injects the selected option code (e.g. `/BRFeeder`, `/Duplex`, `/BRProcessColor`, `/MediaType`) into the job; the PPD's `*JCLBegin`, `*JCLToPSInterpreter` and `*JCLEnd` entries wrap it in PJL. The result is forwarded unchanged to the printer. A stock PostScript PPD (like CUPS's own `generic.ppd`) has no `*cupsFilter` either, and CUPS accepts such PPDs — the printer's native format is `application/vnd.cups-postscript`. ### Device URI Use raw AppSocket as the default: `socket://:9100`. `lpd:///binary_p1` and `ipp://…` remain available through `PRINTER_PROTOCOL`/`PRINTER_URI`. ### Client support - macOS / iOS / iPadOS: AirPrint → CUPS. The queue advertises `image/urf`, `image/pwg-raster`, `application/pdf` and `application/postscript`, with `urf-supported = V1.4,CP1,W8,PQ4,SRGB24,RS600,DM1,FN3`, `sides-supported` (one-sided/two-sided long/short edge) and `color-supported = true`. - Linux: IPP / IPP Everywhere, or plain IPP with PDF/PostScript. - Windows: client-side Brother BR-Script3 Windows driver, pointed at the printer directly or at the shared queue. ### Runtime configuration The printer endpoint and advertised name come from environment variables (`PRINTER_IP`, `PRINTER_PROTOCOL`, `PRINTER_URI`, `PRINTER_NAME`, `PRINTER_DESCRIPTION`, `PPD_FILE`) rather than being baked into the image. The entrypoint derives the URI and runs `lpadmin` on startup, then shares the queue. ## Risks / Trade-offs - [Risk] The AirPrint path (URF → PDF → PostScript) relies on cups-filters' `rastertopdf`; it was not exercised with a real URF job during exploration. macOS/iOS printing should be verified end to end. - [Risk] Colour handling now relies on the printer's PostScript RIP rather than Brother's host-side colour tables; output may differ slightly from the vendor raster driver. - [Risk] The committed PPD is a Windows PPD and contains no CUPS-specific keys. CUPS accepts it as a PostScript PPD (verified for this CUPS version), but this should be re-checked on CUPS upgrades. - [Risk] Avahi needs host networking (or equivalent) to advertise mDNS. - [Risk] CUPS state is not persisted; the queue is recreated on every start.