# printserver/cups Specification ## Purpose Provide a containerized CUPS print server that shares the Brother HL-4150CDN network printer as an AirPrint/IPP printer and prints by sending PostScript directly to the printer, so clients can print without a server-side vendor driver. ## Requirements ### Requirement: Container image builds with required dependencies The container SHALL include CUPS, cups-filters, Avahi/mDNS, D-Bus and the conversion tools needed to turn client documents into PostScript, and SHALL NOT require any 32-bit runtime libraries. #### Scenario: Image contains CUPS - **WHEN** the image is built - **THEN** CUPS is installed and available at /usr/sbin/cupsd #### Scenario: No 32-bit runtime required - **WHEN** the image is built - **THEN** the image contains no i386 multiarch libraries and no Brother vendor binaries ### Requirement: Brother BR-Script3 PPD is installed The container SHALL install Brother's official HL-4150CDN BR-Script3 PPD from the committed asset so CUPS can emit device options as PostScript. #### Scenario: PPD present - **WHEN** the image is built - **THEN** the BR-Script3 PPD is present in the CUPS model directory #### Scenario: CUPS recognises the model - **WHEN** the queue is created with the PPD - **THEN** CUPS reports the printer make and model as "Brother HL-4150CDN BR-Script3" ### Requirement: Hardware options are sent to the printer The system SHALL translate the PPD's device options into PostScript `setpagedevice` instructions so the printer's own hardware options are used. #### Scenario: Paper source - **WHEN** a job selects an input slot (auto select, a tray or the MP tray) - **THEN** the emitted PostScript selects the corresponding paper source on the printer #### Scenario: Duplex - **WHEN** a job selects long-edge or short-edge two-sided printing - **THEN** the emitted PostScript sets `/Duplex` and `/Tumble` accordingly #### Scenario: Colour or mono - **WHEN** a job selects colour or mono - **THEN** the emitted PostScript sets the corresponding colour/mono device parameters ### Requirement: Jobs are printed via direct PostScript The container SHALL forward the converted job as PostScript to the printer without a server-side vendor filter or host-side rasterisation. #### Scenario: Default device URI - **WHEN** the container is started with a printer IP and no explicit URI - **THEN** the queue is created with a raw AppSocket URI (`socket://:9100`) #### Scenario: A job is printed - **WHEN** a print job is submitted to the queue - **THEN** the job is delivered to the printer as PostScript and printed by the printer's PostScript interpreter ### Requirement: Printer is shared and discoverable The system SHALL share the queue over IPP and advertise it via AirPrint (mDNS/DNS-SD). #### Scenario: IPP printer is shared - **WHEN** CUPS runs in the container - **THEN** the printer is shared via IPP for network clients #### Scenario: AirPrint discovery - **WHEN** Avahi runs alongside CUPS - **THEN** the printer is advertised via AirPrint with URF, sides and colour capabilities so macOS and iOS/iPadOS clients can discover it without a driver ### Requirement: Supported client platforms The shared printer SHALL be usable from macOS, iOS/iPadOS, Linux and Windows. #### Scenario: macOS and iOS/iPadOS - **WHEN** a macOS or iOS/iPadOS client prints via AirPrint - **THEN** the job is converted to PostScript and printed #### Scenario: Linux - **WHEN** a Linux client prints over IPP - **THEN** the job is converted to PostScript and printed #### Scenario: Windows - **WHEN** a Windows client prints - **THEN** it uses a client-side BR-Script3 driver against the printer or the shared queue ### Requirement: Runtime configuration is exposed The container SHALL expose CUPS on port 631 and mDNS on UDP port 5353. #### Scenario: CUPS port exposed - **WHEN** the container runs - **THEN** port 631 is available for CUPS administration and IPP #### Scenario: mDNS port exposed - **WHEN** the container runs - **THEN** UDP port 5353 is available for AirPrint discovery ### Requirement: Printer endpoint and advertised name are configurable at runtime The container SHALL accept the network printer address and the advertised printer name through environment variables so the same image can target a different printer or name without rebuilding. #### Scenario: Printer IP is provided - **WHEN** the container is started with `PRINTER_IP` set - **THEN** a device URI is derived from that address and the Brother HL-4150CDN queue is created pointing at it #### Scenario: Printer protocol is selected - **WHEN** the container is started with `PRINTER_IP` and `PRINTER_PROTOCOL` - **THEN** the device URI uses that protocol (socket, lpd or ipp), defaulting to socket #### Scenario: Full URI override - **WHEN** `PRINTER_URI` is set - **THEN** it is used as the device URI and `PRINTER_IP` is ignored #### Scenario: Custom advertised name - **WHEN** the container is started with `PRINTER_NAME` - **THEN** the CUPS queue uses that name and it is the name advertised via AirPrint/DNS-SD #### Scenario: Custom CUPS description - **WHEN** the container is started with `PRINTER_DESCRIPTION` - **THEN** the queue's CUPS Description (Info) is set to that value