OPPA is the Open Printer Proxy Agent, a local Tauri desktop
utility backed by a shell-independent Rust runtime. OpenPrinter is the
generic protocol and server SDK ecosystem in the @openprinter/* npm
scope.
Keep product-specific concepts such as restaurant, branch, kitchen, billing, menu, order, tenant routing, and hosted dashboards out of this repository's generic protocol and agent layers.
apps/oppa: React interface and narrow Tauri hostapps/www: Fumadocs landing and documentation sitecrates/oppa-agent: top-level Rust orchestrationcrates/oppa-*: focused domain and infrastructure boundariespackages/protocol: canonical TypeBox protocol schemas, codecs, and typespackages/server: framework-neutral authenticated WebSocket SDKprotocol: generated JSON Schema and cross-language fixturesexamples/node-server: development-only end-to-end integrationproducts: compile-time branded product definitions and assets
Do not add a crate, package, application, or service unless its
responsibility cannot be represented cleanly by an existing unit and
is required by PLAN.md.
apps/oppa hosts oppa-agent; it does not own agent business logic.
oppa-agent coordinates authentication, transport, storage,
discovery, rendering, spoolers, platform services, and the lower-level
domain crates. Low-level crates must not depend on Tauri, frontend
code, or oppa-agent. Avoid circular dependencies.
Rendering and printer submission are separate. Credentials use
oppa-platform secure storage and must never enter SQLite. The server
SDK never owns durable server-side jobs.
The TypeBox schema in packages/protocol is canonical. Its
deterministic generator writes
protocol/schema/openprinter.schema.json. Rust and TypeScript
validate the same committed fixtures.
A protocol change must:
- update the canonical schema and inferred types;
- regenerate the JSON Schema;
- update valid and invalid fixtures;
- pass both Rust and TypeScript compatibility tests;
- document delivery and error semantics.
Use stable discriminators and serialized names. Prefer received,
submitted, and failed; do not claim universal physical printed
completion.
OPPA_PRODUCT_DIR selects a versioned product.json and assets at
compile time. Runtime code uses the validated embedded definition and
never trusts an editable product file. Product configuration may
disable a compiled capability but cannot enable code absent from the
binary.
- no arbitrary shell commands, scripts, plugin execution, or generic proxying
- no unrestricted frontend filesystem, SQL, shell, or network capability
- discovery and pairing accept plain HTTP only on loopback; production service and gateway endpoints require TLS
- private Ed25519 keys remain behind
oppa-platformsecure storage; only public keys cross the network - gateway challenges are unpredictable, socket-bound, single-use, and expire before normal protocol traffic is accepted
- credentials stay in operating-system secure storage and out of logs and diagnostics
- validate message, document, image, queue, and diagnostic limits
- validate a remote printer ID against the enabled local registry
- apply explicit timeouts to all printer and network operations
- sanitize errors and never log full print documents by default
Use TypeScript strict mode and typed error surfaces. Avoid any,
unchecked parsing, hidden global state, giant files, and speculative
abstractions. Rust public APIs need useful Rustdoc; TypeScript public
APIs need JSDoc. Recoverable failures return structured errors and
must not panic.
Every crate, package, application, and example needs a professional README describing purpose, responsibilities, non-responsibilities, APIs, dependency role, commands, and current status.
CLAUDE.md files only contain @AGENTS.md; do not duplicate guidance
between them.
pnpm install
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm protocol:generateTargeted Rust checks:
cargo fmt --all --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspacePhysical printers are not required in tests. Use virtual printers and mocks. Keep static/build validation distinct from a real Tauri launch or physical printer acceptance test.
A server or dashboard can direct a user to pair OPPA by opening a
custom URL. The full spec lives at
apps/www/content/docs/deep-link-pairing.mdx; the short form is:
oppa://pair?server=<base64url-server-url>&key=<pairing-code>
server is the server base URL encoded as Base64URL without
padding. key is a one-time pairing code created by the server.
Node.js: Buffer.from(serverUrl).toString('base64url')
Browser:
btoa(serverUrl)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');Use POST /development/pairing-code on the example server to generate
a code for testing. The dev UI at /dev builds and shows the link
automatically. Pairing codes may be logged in development but must
never be placed in a URL query parameter or stored in a log
aggregator.
Do not add a hosted OpenPrinter cloud, built-in Redis or database server, browser printing, remote desktop, arbitrary runtime provider switching, mobile application, business fleet dashboard, full QZ Tray compatibility, or speculative hardware protocols.