retrospool

your AS/400 reports, as PDFs, over the web

The old world

Business reports on IBM i (née AS/400) land in output queues (OUTQ), where a Windows box running an ACS printer session has to "claim" a device and drain them onto paper — or into a folder, if someone rigged it. The trick: the host queues spool files in *READY whether or not any printer is alive. The session was never actually required.

retrospool is a self-hosted web application built to replace that whole ritual: it reads spool bytes directly via JTOpen — no TN5250E negotiation, no device-name juggling, no port 992 — and turns them into PDFs. The capture-and-render core and credentialed operator console are built; the queue poller that drains a live OUTQ on a schedule, and export fan-out to S3 / SFTP / FTPS, are the next phases (see status).

The pipeline

IBM i OUTQ ──▶ poll (JTOpen) ──▶ sniff format ──▶ split concatenated PCL
              [poller: planned]                       │
                       ┌───────────────────────────────┤
                       ▼                               ▼
              store original bytes              render PCL ─▶ PDF
              (.pcl / .pdf / .bin)            (GhostPDL sidecar)
                       │                               │
                       └───────────┬───────────────────┘
                                   ▼
                   tenant-scoped capture (dedup by sha256)
                                   │
                                   ▼
              export fan-out: S3 / SFTP / FTPS  [planned]

The shaded middle band — sniff → split → store → render → capture — is built and covered by end-to-end tests today. The queue poller that feeds it, and the export fan-out that drains it, are the next phases.

What works today v0.2.0 · verified

The backend is exercised by unit + Testcontainers integration tests against real Postgres, MinIO, and the actual gpcl6 sidecar. The production frontend bundle is browser-driven to generate the product views below, with console and page errors treated as failures.

See it work

These are screenshots of the actual production-built admin console, not hand-drawn mockups. A Playwright harness launches the app and supplies deterministic API fixtures; all company names, hosts, IDs, and report details shown here are invented demo data.

Operator dashboard — a shift-at-a-glance view of active tenants, pending approvals, captured reports, configured queues, and the next useful actions.
Human approval gate — inspect parsed settings and write-only secret references before explicitly promoting a pending submission into a tenant.
Tenant-scoped captures — browse original spool artifacts and their rendered PDF siblings without crossing company boundaries.
Ephemeral connection test — exercise the real JTOpen sign-on path and report a useful result while never persisting the submitted password.
Responsive by default — the same console works from a phone-sized viewport when an operator needs a quick status check away from a desk.

Stack

Spring Boot 3 · Java 21 (Temurin) · JTOpen · PostgreSQL 16 + Flyway · PDFBox · AWS SDK v2 · GhostPDL (sidecar only) · React 18 · Vite · TypeScript · TanStack Query · Tailwind · Testcontainers (real Postgres, MinIO, and the actual gpcl6 sidecar in CI-style integration tests) · Docker end-to-end — the dev machine needs no JDK.

Every architectural decision — including the ones later reversed, and why — lives in an append-only decision log. Docs drift is treated as a bug.

Status

v0.2.0 — pre-1.0 and honest about it. The capture-and-render core, authenticated admin API, React operator console, and the public HOD/WS submission intake are delivered. Live queue polling and export fan-out remain next — both gated on a real IBM i host, which is also what 1.0.0 waits on.

The full phased plan and an append-only decision log live in docs/.