Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Shipping management system with multi-carrier API integration and local printing
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
PolyBag is a barcode-driven shipping workstation for picking, packing, buying
postage, printing labels, and tracking fulfillment work. Operators work from a
browser connected to a local scale and printers.
Built with Laravel 13, Filament 5, Livewire 4, Tailwind CSS 4, MySQL, and Redis.
PolyBag is source-available under the Business Source License 1.1. Production
commercial use requires a commercial licence until the applicable change date.
See Licence.查看完整 README ↗PolyBag is a barcode-driven shipping workstation for picking, packing, buying postage, printing labels, and tracking fulfillment work. Operators work from a browser connected to a local scale and printers.
Built with Laravel 13, Filament 5, Livewire 4, Tailwind CSS 4, MySQL, and Redis.
PolyBag is source-available under the Business Source License 1.1. Production commercial use requires a commercial license until the applicable change date. See License.
QZ Tray runs on each workstation and sends jobs to local label and document printers. Labels have two printer slots — one for PDF, PNG, or GIF labels through the driver, and one for raw ZPL — which can be the same printer; a raw-only workstation can be a plain "Generic / Text Only" queue on Windows. Pack slips use 4×6 stock on the image label printer; the document printer handles pick lists, manifests, and separate customs forms. Printer, preferred purchase format, DPI, and scale preferences are stored in that browser and managed from Workstation Settings.
Printed status records that QZ accepted the job, or that an operator marked a viewed pack slip printed. It does not confirm that paper physically came out of the printer.
Generate a self-signed QZ certificate for development or a private deployment:
php artisan app:generate-qz-cert shipping.example.com
The private key must stay secret. Each workstation must trust the matching public certificate before silent printing will work. See QZ Tray provisioning for the complete setup.
Chrome and Edge use WebHID when available. QZ Tray provides the fallback backend. WebHID requires HTTPS or localhost; a paired scale reconnects on later visits.
The supported self-hosted deployment is a standalone Docker stack with its own MySQL 8.4, Redis, and Gotenberg containers.
Requirements: Docker Engine, the Docker Compose plugin, and a Linux host.
git clone https://github.com/niolson/polybag.git
cd polybag
./scripts/install-onprem.sh
After installation, create the first administrator:
docker compose --profile standalone \
-f docker-compose.yml -f docker-compose.onprem.yml \
exec -it app php artisan app:create-user
Open the URL reported by the installer. The first administrator is sent through the Setup Wizard to configure the warehouse, carriers, box sizes, shipping methods, and an optional import source.
The Compose override publishes HTTP on APP_PORT (80 by default). For an HTTPS URL,
configure TLS at a reverse proxy; the installer does not provision it.
PolyBag can run without any service operated by POLYBAG.APP LLC. Self-hosters bring their own carrier, marketplace, mail, address-validation, and SSO credentials. See Self-hosting for the credential and callback-URL map.
After pulling updates, rebuild and restart the stack so image changes take effect:
docker compose --profile standalone \
-f docker-compose.yml -f docker-compose.onprem.yml \
up -d --build
The app exposes /up for liveness and /api/health for MySQL and Redis readiness.
Restrict the readiness endpoint to your monitoring system at the reverse proxy.
Startup runs migrations, synchronizes reference data, attempts MySQL table encryption, and caches the application configuration. The installer also verifies encryption. Keep database backups together with the MySQL keyring needed to decrypt them; see MySQL encryption setup.
Requirements: PHP 8.4, Composer, Node.js 22.12+, MySQL 8.4, and Redis.
Create a database, copy .env.example to .env, and set the local database and
Redis connection values. Then run:
composer run setup
php artisan app:sync-reference-data
php artisan app:create-user
composer run dev
composer run dev starts the Laravel server, default/low queue worker, dedicated import
worker, scheduler, and Vite development server.
PDF generation also needs a reachable Gotenberg service configured with GOTENBERG_URL.
The standalone Docker stack includes it; composer run dev does not start it.
Use composer run setup for initial setup: it generates a new application key.
For local end-to-end work without carrier credentials or billable API requests, set:
FAKE_CARRIERS=true
The fake adapters cover rating, labels, and address validation.
Infrastructure and base URLs live in .env; operational configuration lives in
the application database.
| Configuration | Location |
|---|---|
| Company, warehouse, feature flags, authentication, retention | App Settings |
| USPS, FedEx, and UPS credentials and Location/Client routing scopes | Carrier Accounts |
| Database, Shopify, and Amazon credentials, schedules, and marketplace postage | Connections |
| Carrier services, service classes, packaging, and shipping rules | Carriers / Shipping Setup |
| Amazon observed-service mapping | Integrations → Map Amazon Services |
| Allowed postage sources, services, and Amazon offer requirements for automation | Shipping Methods |
| Per-client return address, branding, label reference, and customs policy | Clients (App Settings for the default client in single-client mode) |
| Image-label, raw-label, and document printers; format, DPI, and scale | Workstation Settings in each browser |
| Database, Redis, mail, SSO, Google validation, Gotenberg | .env |
Connections have separate switches for being active and importing orders. A Connection can sell postage or receive tracking without importing. Its Sells Postage switch decides whether Shopify or Amazon postage is bought on its account at all.
Amazon-specific screens appear when an Amazon Connection is active or Amazon features is enabled in App Settings. Enable that setting manually for Amazon orders imported from a database. Pack slips and picking have their own feature switches.
Secrets on Carrier Account and Connection records are encrypted. Never commit
.env, carrier credentials, OAuth tokens, database connection strings, or QZ private
keys.
Run php artisan list to discover all commands. Self-hosters should know these:
| Command | Purpose |
|---|---|
app:reencrypt-secrets | Complete an APP_KEY rotation; see note below |
data:purge | Apply audit-log, rate-quote, shipping-offer, and notification retention |
shipments:purge-pii | Apply recipient PII retention, with a dry-run option |
db:encrypt-tables | Enable or verify MySQL table encryption |
app:generate-ssh-key | Create keys for database import tunnels |
app:verify-label-integrity | Report any mismatch between Packages and their active Label records |
app:sync-reference-data | Sync carrier/service catalogs, mappings, and carrier packaging |
exchange-rates:fetch | Fetch reference rates used for seller tax registration thresholds |
packages:sync-shopify-label-costs | Recover identifiable USD label costs from Shopify order events |
address-validation:report | Report validator results against later parcel outcomes |
When rotating APP_KEY, keep the old key in APP_PREVIOUS_KEYS. Remove it only
after app:reencrypt-secrets succeeds without undecryptable values.
The scheduler runs configured imports, exports and address validation, tracking refreshes,
Shopify fulfillment and label-cost synchronization, exchange-rate fetching, shipping
statistics, retention and archival tasks, abandoned Manual Ship draft cleanup, and a
daily label-integrity check. Keep the scheduler and both queue workers running in
production. Schedules live in routes/console.php and bootstrap/app.php.
composer run dev # App, queues, scheduler, and Vite
composer run test # Unit and feature tests
composer run test:serial # Same suite in one process
composer run test:external # Explicit live carrier/reference tests
composer run test:fedex-reference # FedEx reference cases only
npm run build # Production frontend assets
composer run format # Rector, PHPStan, and Pint
The default suite runs Unit and Feature tests in parallel, capped at 16 processes, with a separate in-memory SQLite database per worker. Browser tests use Pest 4 and Playwright and must be run explicitly:
npx playwright install chromium
php artisan test tests/Browser/
CI also runs browser tests, the mysql test group against MySQL 8.4, Pint, Rector,
and PHPStan. Coverage is collected on pushes to main.
A Shipment is an order to fulfil. A Package is the physical parcel produced from it. A Package Draft is an unshipped Package that has been prepared but has not completed label purchase. A Label is one purchased instance of outbound postage for a Package. A Package has at most one active Label; voiding it preserves the Label as history and returns the Package to an unshipped state. These terms are intentionally distinct.
Manual Ship creates a Draft Shipment to show rates before purchase. It stays out of operational lists until a Label is bought; abandoned drafts with no Label history are deleted after 24 hours without changes. This is separate from a resumable Package Draft saved while packing an existing Shipment.
The carrier of record is the company physically moving the parcel. The postage source is where the Label was bought: one of PolyBag's direct Carrier Accounts or a Shopify/Amazon Connection. Tracking, voiding, and manifest eligibility follow the postage source, so marketplace-bought postage is never treated as if it came from one of the merchant's direct carrier accounts. Direct-label tracking and voids use the account recorded at purchase, even if routing scopes later change.
An Offer is a package-specific quoted rate backed by short-lived purchase authority held on the server. Shopify Shipping is a blind purchase whose final carrier is learned after purchase and whose purchase response reports no price or service. PolyBag can later recover an identifiable USD cost from Shopify's order timeline and infer service from label evidence; either may remain unknown. A packer buys one only after confirming it. Automation buys one only when a shipping rule names it, or when Shopify is the shipping method's sole eligible source and offers exactly one purchase. Shopify Shipping labels must be voided in the Shopify admin; the scheduled fulfillment sync detects the void and returns the Package to an unshipped state.
A packer may buy any Offer shown on the Ship page. Auto-ship, batch shipping, and shipping rules buy only within the shipping method's allowance: the postage sources the method permits, and the services it lists. For Amazon Buy Shipping, an administrator can widen this to any service Amazon offers. A Connection that does not sell postage is never asked, by a packer or by automation. A Shipment needs a shipping method before any Label is bought.
Amazon's Shipping v2 API distinguishes Amazon orders (channelType: AMAZON) from orders
from other channels (channelType: EXTERNAL). An Amazon order is quoted through Amazon Buy
Shipping and can receive Amazon Shipping, USPS, UPS, FedEx, OnTrac, or another carrier that
Amazon returns. Amazon may offer services PolyBag has never seen. An administrator maps
these to the carrier-service catalog on Map Amazon Services; until then, only a packer,
or a method allowing any service, can buy them. A Shipment from Shopify, a database
source, or Manual Ship can be sold Amazon Shipping directly, like any other carrier. The
seller's Amazon Connection is the account, and a Carrier Account Scope chooses which
Connection sells for each Location and Client.
For international postage that accepts PolyBag's customs terms, the Shipment's duties choice overrides its Client's destination policy. An EU destination needs an explicit choice; incompatible rates are excluded and customs readiness is checked before purchase. Labels retain a snapshot of the declared terms. Amazon and Shopify purchases use source-decided terms; automation currently holds these purchases for customs crossings into the EU, UK, Norway, and Australia, while attended purchase remains available.
PolyBag-printed barcodes use a % prefix, such as %S216 for a Shipment or %CSHIP
for the Ship command. Order references, SKUs, UPCs, and tracking numbers remain external
identifiers.
The main scopes are Location for a warehouse and Client for a 3PL brand or retailer. Carrier Account Scopes select credentials from the Location and Client.
See CONTEXT.md for the glossary and architecture decisions for structural context.
PolyBag is source-available, not open source. It is licensed under the Business Source License 1.1.
The license permits reading, modifying, redistributing, and running the code for personal, educational, non-commercial, internal evaluation, and development use. It does not permit production use intended to generate revenue or commercial advantage.
On March 11, 2030—or four years after a particular version was first published,
whichever comes first—that version converts to Apache License 2.0. The PolyBag name,
logo, and polybag.app branding remain unlicensed trademarks after conversion.
For commercial terms, contact [email protected].
See CONTRIBUTING.md for the development loop and contributor agreement. Report vulnerabilities privately as described in SECURITY.md.