Download FreeMenu
release notes

what's new in labelpipe

Every version, newest first. To update, run the install command again.

1.0.0 2026-11-06

  • CI: Dependabot PRs no longer fail the image builds once SIXLABORS_LICENSE_KEY is also a Dependabot secret (the error now says so), never run on the self-hosted runner, and no longer propose Node major versions for the sign-up service. The website CI job builds on Node 24, the LTS the sign-up service ships with.
  • Upgrade gate with real data (QA, WP-J): before a beta can become stable, the upgrade test now seeds people, printers, a routing rule, an API client and printed jobs on the previous stable, and after the upgrade checks that every one is unchanged (including the stored PDFs and template layouts), that passwords still work, and that old jobs reprint and new ones print. Developer docs, Production deploy.
  • Our own release registry: betas and stable releases now come from registry.labelpipe.app, without a login: docker compose -f oci://registry.labelpipe.app/labelpipe-compose:latest up -d. GHCR stays private for the team’s edge builds. Every release is signed with cosign keyless, and a beta becomes stable only if its signatures verify (replaces the R-ATT waiver). Setup and operations: developer docs, Release registry.
  • CI: fewer GitHub Actions minutes. :edge is built for amd64 only, and a newer push to main cancels the running build; beta tags, and so every release, stay amd64 + arm64. The image build on PRs runs only when the PR touches the image (docker/, Composer and npm files, database/, config/, VERSION, the workflow); acceptance screenshots skip docs-only changes. The repository variable LABELPIPE_RUNNER moves the heavy test jobs to a self-hosted runner (developer docs, CI runners and Actions minutes).
  • Website: site/ builds www.labelpipe.app with Astro (static HTML, served by Caddy): home, features, Free vs Pro, download and install, docs (the user manual), release notes (this file), and draft legal pages (imprint, privacy, terms, Free licence). The Free limits and the version come from config/editions.php and VERSION. CI builds and checks it (job website); site/ never goes into the app image. See the developer docs, The public website.
    • Tell me when Pro launches: a double opt-in sign-up on the site, run by a small service on our own server (site/notify/), with no third party.
    • The website’s licence page (/eula) now shows the same text as the setup wizard, built from resources/legal/eula-free.md, with its version.
  • Licence agreement: labelpipe is proprietary and free of charge in the Free edition (composer.json says proprietary). The setup wizard has a new step 2, the licence agreement, with a required I accept. labelpipe records the version, the administrator and the time. When an update brings a new version, administrators are asked to accept it at their next sign-in (/admin/licence); other users keep working. The text still has placeholders for the company data and waits for a lawyer’s review.
  • Security: the production image sends X-Frame-Options: SAMEORIGIN and Content-Security-Policy: frame-ancestors 'self', so no other site can frame labelpipe and trick a signed-in admin into clicks. labelpipe’s own PDF previews (designer, import) still show. The Caddy example in the deploy guide adds the CSP line.
  • Security: in compose.prod.yaml the session idle timeout is fixed at 60 minutes (SESSION_LIFETIME from .env is ignored), so the cookie lifetime matches the sign-in policy. Before, an install without a .env value used 120.
  • Readability: muted text, small links, status lines and Delete in the label designer, and empty-value placeholders in tables (such as draft only), now meet 4.5:1 contrast in light and dark mode (QA M1-7 F1, F2), and so do the hints under condition inputs such as Empty — always true (F1b).
  • Fix (MariaDB): parallel print jobs no longer deadlock while reserving the daily quota. Under concurrent API calls some requests answered 500 instead of 201 or 429. A MariaDB race test job now runs in CI.
  • Search help: press Ctrl + / (⌘ + / on a Mac) or click Search help in the top bar to search the user manual as you type. Results show the chapter, the section and the matching text; Enter opens the section. The manual page’s filter box now lists matching sections instead of hiding chapters. Administrators also get developer-docs results.

0.8.1 2026-11-06

  • Security: someone who signs in only with Google and has no second step yet can add an authenticator app or e-mail codes only within 5 minutes of signing in (Security page). Otherwise the button is greyed out and asks them to sign in again. Forced set-up right after sign-in is unchanged.

0.8.0 2026-11-06

  • labelpipe free: up to 500 labels and documents a day, 1 store, 3 active users, 5 enabled printers, 1 integration client and 30 days of print job history. Every feature still works. See the manual, Editions and usage.
    • A job that would cross the daily limit is refused whole. The API answers 429 quota_exceeded with Retry-After, X-Labelpipe-Quota-Limit and X-Labelpipe-Quota-Remaining. Designer and ZPL editor previews don’t count; every label POST /api/v1/zpl/render returns does. ZPL counts what the printer prints (^PQ quantities, several labels per record; a label may have only one ^PQ); a ZPL print job that turns out bigger than what is left today fails with quota_exceeded before anything is sent. Reprints and retries count again, and a job that failed while being drawn gives its labels back.
    • At a limit, the New button for stores, users, printers or integration clients is greyed out and says why. Existing ones are kept. Only active users and enabled printers count: deactivate a leaver or disable a printer to free the place. Reactivating, enabling, or approving a Google sign-up counts like adding one. labelpipe:create-admin --deactivate=<e-mail> frees a place when nobody can sign in.
    • Finished print jobs older than 30 days are deleted every night (labelpipe:prune-jobs), with their files.
  • Setup → Usage (administrators) and a dashboard widget: today’s labels against the limit, when it resets, and the counted limits. API: new GET /api/v1/usage; GET /api/v1/ping gains usage.
  • Development: the demo data has one demo store (demo-main).

0.7.0 2026-11-06

  • First-run setup in the browser: on a new server the web container’s log prints a one-time link (docker compose logs web | grep "first-run setup"). It opens set up labelpipe: paste or follow the setup key, create the first administrator and turn on the authenticator app; you are then signed in. The link changes on every restart, expires after 24 hours and stops working once an administrator exists. labelpipe:create-admin still works; LABELPIPE_WEB_SETUP=false turns the web setup off.
  • The web container’s access log no longer records query strings (setup key, Google sign-in codes).

0.6.0 2026-11-06

  • Two-step sign-in: administrators and template managers must set up an authenticator app the next time they sign in (QR code, then 10 one-time recovery codes). Operators may use an app or e-mail codes; require for everyone is in Access → Security settings (default LABELPIPE_MFA_REQUIRE_ALL). No “remember me”; sessions end after 12 hours.
  • Sign in with Google (when GOOGLE_CLIENT_ID is set): for people who already have an account with the same verified e-mail, always followed by the labelpipe second step. Optional allowed domains and auto-created accounts that wait for an administrator’s approval.
  • Access → Users: Allow password sign-in, two-step and Google columns, Awaiting approval.
  • Access → Sign-in log: sign-ins, refusals, wrong codes, lockouts and Google links, kept 90 days.
  • Security page (user menu): change your password, link or unlink Google, manage your second step.
  • Confirm it’s you: sensitive changes (passwords, Google links, API tokens and secrets, roles, security and ZPL preview settings) ask for a fresh code, good for 5 minutes.
  • Reset two-step for someone who lost their phone (another administrator, with a reason; they are signed out and e-mailed). Users who still have to set up their second step are marked red in Access → Users.
  • Access → Security settings: Require two-step for everyone.
  • Sign-in screens: the code step shows no Sign in with Google button; setting up the second step after signing in does not ask for the password again and needs I saved these codes somewhere safe ticked; the set-up page has Sign out; recovery codes are typed as plain text.

0.5.1 2026-11-06

  • Fix: Duplicate in Setup → Label templates failed with “Error while loading page” for every template (ZPL and PDF). It now creates the copy and opens it in the designer.

0.5.0 2026-11-06

  • Starter gallery: administrators can add nine ready-made templates from Setup → Label templates → Install starter gallery: shelf labels (70 × 38 mm and an A4 sheet of 21), a price tag, a product sticker, 4 × 6 shipping labels in PDF and ZPL, and A4 picking slip, delivery note and invoice forms. You choose who sees them; installing again only adds what is missing (the dialog names them). Also labelpipe:install-gallery. New installs still start empty.

0.4.0 2026-11-05

  • ZPL preview without the internet: a bundled preview service (zpl-preview) draws ZPL labels on your own server. Previews from it are marked approximate: Zebra’s fonts are replaced by open fonts.
  • Setup → ZPL preview: administrators choose Local, Labelary or Off. Labelary’s public service is used only after an administrator confirms that label content is sent to labelary.com (name and time are recorded). LABELARY_ENABLED is gone; see LABELPIPE_ZPL_PREVIEW_URL and LABELPIPE_ZPL_PREVIEW_DEFAULT in .env.example.
  • Every preview says which service drew it. Previews are limited to 50 labels, 40 million dots and 60 a minute per person or API client; errors no longer quote the preview service’s answer.
  • API: /api/v1/zpl/render returns driver in JSON and X-Preview-Driver on png/pdf; 503 preview_disabled when previews are off, 429 preview_busy over the limits.
  • The ZPL editor no longer suggests commands that templates may not use (^IM, ^CC, ^CT, ^CD …).
  • Server installs: docker/compose.prod.yaml and compose.trial.yaml run the zpl-preview service (ghcr.io/plamenbv/labelpipe-zpl-preview) on an internal network next to the app; nothing to configure.
  • Security: line breaks inside a ZPL command or graphic no longer slip past the preview limits; at most 2 previews are drawn at once; the preview services’ redirects are not followed.
  • Development: ./dev up on a fresh clone runs the first-time setup; the dev API token is limited to printing and expires after 30 days. Building zpl-preview needs SIXLABORS_LICENSE_KEY in your shell (see Local development).

0.3.1 2026-11-06

  • Install with one command: docker compose -f oci://ghcr.io/plamenbv/labelpipe-compose:latest up -d.
    • The compose file is published to GHCR with the image’s tags, and every image is pinned by digest.
    • Alternatively, download docker/compose.prod.yaml and run docker compose -f compose.prod.yaml up -d.
    • Nothing has to be edited first. Optional settings go in a .env next to it (see docker/.env.prod.example).
    • Choose the version with the artifact tag: :X.Y.Z, :X.Y, :latest or :edge. With the OCI form, LABELPIPE_VERSION has no effect.
  • Production image ghcr.io/plamenbv/labelpipe for free and pro, amd64 and arm64:
    • one image runs web, worker and scheduler;
    • it runs as a non-root user with a read-only root filesystem;
    • it is scanned by Trivy and published with an SBOM and a provenance attestation.
  • Secrets are generated on first start:
    • The init service creates the app key and the database password in the new secrets volume.
    • The database container gets its copy through the new db-secret volume.
    • The MariaDB root password is random, and root can only log in from inside the database container.
    • An APP_KEY or DB_PASSWORD already in .env is kept and stored.
    • Back up the secrets volume together with dbdata and storage. Without the app key, encrypted data and sessions cannot be read.
  • The web port listens on 127.0.0.1 only. LABELPIPE_TRUSTED_PROXIES defaults to the compose network’s gateway, so a reverse proxy on the host works out of the box.
  • Labelary previews are off by default (ADR-004).
  • The image ships only the documentation the app shows (Help → Developer docs, API docs). Internal design documents and contributor files are left out (ADR-006).
  • Create the first administrator with labelpipe artisan labelpipe:create-admin. A first-run setup page follows in M2.

0.3.0 2026-11-05

  • Security:
    • ZPL templates and the dynamic ZPL API refuse prefix changes (^CC, ^CT, ^CD and their ~ forms) and commands that store, load or erase objects on the printer (~DG, ^DF, ^IM …). Use ^GF for graphics. A line break or other control character inside a command no longer hides it, and the error names the command as you typed it.
    • After 20 failed API logins from one address in a minute, that address gets 429 for the rest of the minute.
    • API tokens expire: one year at most (LABELPIPE_API_TOKEN_LIFETIME_DAYS); Issue token asks for the date.
    • Allowed source IPs / CIDR on integration clients is enforced (403 from other addresses). Behind a reverse proxy, set LABELPIPE_TRUSTED_PROXIES.
    • The development CUPS server allows administration only to a local system administrator; a production configuration without the web interface is included.
    • Safer development defaults: APP_DEBUG=false, the app is reachable only from this computer (127.0.0.1:8080).
  • Queue: a print job running close to the 120-second limit is no longer handed to a second worker.
  • Organisations: more checks that forms accept only your own organisation’s records.

0.2.3 2026-11-05

  • Brand: headings that show a name you typed (template designer, edit and view pages, an import or import template) keep its case, e.g. “Design: Shelf A4 Promo”. Static page and section headings stay lowercase.

0.2.2 2026-11-05

  • Production setup: db:seed no longer creates the demo users, demo token or virtual printers unless APP_ENV is local or testing; DevelopmentSeeder refuses to run anywhere else. ./dev update seeds only the reference data.
  • New command php artisan labelpipe:create-admin creates the first administrator (password asked with a hidden prompt, at least 12 characters).
  • Docs: production deploy guide for a single server (Caddy, Tailscale, Cloudflare Tunnel, host CUPS, backups, updates): docs/developer/15-production-deploy.md.

0.2.1 2026-11-05

  • Organisations: forms accept only stores, printers, users and import templates of your own organisation, and the import page accepts only files uploaded through it. Background maintenance (stuck-job checks, pruning) also covers switched-off organisations.

0.2.0 2026-11-05

  • Organisations (tenancy-ready schema): every row now belongs to an organisation. An install has one, the default organisation, created by the database migration. Codes (stores, printers, templates, fields, images) are unique per organisation. A user or integration client of an inactive organisation cannot sign in or call the API. Files are stored under the organisation’s folder. Install fresh with ./dev setup (0.x schemas are not migrated).
  • Product data: origin, warranty, manufacturer and importer are back as plain fields (API, import mapping, label fields {{manufacturer}} …), for EU product labelling.
  • Price engine: the focus and sale thresholds are settings (LABELPIPE_PRICING_*, defaults 1.9 % and 14.9 %).
  • Client IDs now start with lp_.
  • Removed the unused Publish settings action on label templates and an old per-store setting.
  • Brand: the labelpipe theme. Logo and favicons, Deep Charcoal dark mode as the default (light mode in the user menu), Electric Cyan as the primary colour, Neon Mint for success, Vivid Amethyst for info and template fields. Self-hosted fonts: Inter (interface), Geologica (headings), JetBrains Mono (code, ZPL, rule inputs). Every text and button colour pair meets WCAG AA in both modes (docs/design/theme-spec.md).
  • Sign-in page with the stacked logo and the brand glow, the API documentation page with the charcoal brand bar, the manual with brand headings and a logo on printouts. Label and document output is unchanged: print colours stay whatever the template says.