
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Zobox is a Zo-native, open-source inbox + sorter + router engine. It accepts arbitrary structured JSON messages with optional file attachments, stores them durably, and routes them according to configurable sorters.
POST /messages with multipart or JSON supportinbox/, attachments in files/, indexed by SQLitezobox.config.tomlGET /messages/next for building distributed subscribers{channel}/{date}/{eventId}/{filename} patternsGet Zobox running locally in under 5 minutes:
bun install
Or with npm:
npm install
export ZOBOX_ADMIN_API_KEY="dev-admin-key"
export ZOBOX_READ_API_KEY="dev-read-key"
ZOBOX_ADMIN_API_KEY="dev-admin-key" bunx zobox init --base-dir /home/workspace/Inbox
This command:
inbox/, files/, db/, logs/)Server listens on http://localhost:8787 by default.
curl -X POST "http://localhost:8787/messages" \
-H "content-type: application/json" \
-H "x-api-key: $ZOBOX_ADMIN_API_KEY" \
-d '{
"type": "update",
"payload": { "text": "First idea" }
}'
curl "http://localhost:8787/messages?limit=20" \
-H "x-api-key: $ZOBOX_READ_API_KEY"
You should see your item in the response!
# Install dependencies
bun install
# Copy example config
cp config/zobox.config.example.toml /home/workspace/Inbox/zobox.config.toml
# Set environment variables
export ZOBOX_ADMIN_API_KEY="dev-admin-key"
export ZOBOX_READ_API_KEY="dev-read-key"
export ZOBOX_BASE_DIR="/home/workspace/Inbox"
# Development mode (with hot reload)
bun run dev
# Production mode
bun run start
# Or directly
bun run src/server.ts
# Initialize directory structure, copy configs, run migrations, and start server
bunx zobox init [--base-dir PATH] [--port PORT]
# Start server only (assumes init already done)
bunx zobox serve [--base-dir PATH] [--port PORT]
# Run migrations only
bunx zobox migrate [--base-dir PATH]
# Help
bunx zobox help
Note: The
--base-dirflag always takes precedence overZOBOX_BASE_DIRenvironment variable and anybase_dirvalue in the config file.
# Run tests
bun run test
# Run tests in watch mode
bun run test:watch
# Lint and check code
bun run lint
# Lint and auto-fix issues
bun run check
This project uses Lefthook for automated pre-commit and pre-push checks:
Pre-commit hooks (run in parallel):
tsc --noEmitPre-push hooks:
Hooks are installed automatically via the prepare script when you run bun install.
To customize hooks for your local environment, copy the example:
cp .lefthook-local.yml.example .lefthook-local.yml
Then edit .lefthook-local.yml to skip expensive checks during fast iteration:
# Skip type checking and tests on commit (faster iteration)
pre-commit:
commands:
types:
skip: true
test-related:
skip: true
Your local customizations won't be committed (.lefthook-local.yml is in .gitignore).
zobox/
bin/
zobox.ts # CLI entrypoint
src/
types.ts # TypeScript type definitions
config.ts # TOML config loader
storage.ts # SQLite + filesystem storage
sorters.ts # sorter and routing logic
server.ts # Hono HTTP server
config/
zobox.config.example.toml
routes.example.json
db/
migrations/
001_init.sql
docs/
API.md # API reference
CONFIGURATION.md # Configuration guide
Deploy Zobox as a Zo User Service:
ZOBOX_ADMIN_API_KEY="your-admin-key" bunx zobox init --base-dir /home/workspace/Inbox
This creates the directory structure, copies config files, and runs migrations. You can stop the server after initialization (Ctrl+C).
Configure in Zo:
zoboxhttp8787bunx zobox serve/home/workspace/InboxAdd to your Zo service configuration:
ZOBOX_ADMIN_API_KEY (required)ZOBOX_READ_API_KEY (optional, recommended)Your Zobox service will start automatically with Zo.
See docs/API.md for complete documentation.
POST /messages: Ingest messages (JSON or multipart with attachments)GET /messages: List messages with filtering and cursor pagination (response key: items)GET /messages/next: Worker polling for unclaimed messagesPOST /messages/:id/ack: Acknowledge item processingGET /health: Health check# Admin key (full access)
x-api-key: YOUR_ADMIN_KEY
# Read key (read-only)
x-api-key: YOUR_READ_KEY
# Or Bearer token
authorization: Bearer YOUR_KEY
Configure in zobox.config.toml:
[auth]
admin_api_key_env_var = "ZOBOX_ADMIN_API_KEY"
read_api_key_env_var = "ZOBOX_READ_API_KEY"
required = true
JSON only:
curl -X POST "http://localhost:8787/messages" \
-H "content-type: application/json" \
-H "x-api-key: YOUR_ADMIN_KEY" \
-d '{"type":"update","payload":{"text":"Hello"}}'
JSON + base64 attachments:
curl -X POST "http://localhost:8787/messages" \
-H "content-type: application/json" \
-H "x-api-key: YOUR_ADMIN_KEY" \
-d '{
"type":"post",
"payload":{"title":"My post"},
"attachments":[{"filename":"photo.jpg","mimeType":"image/jpeg","base64":"..."}]
}'
Multipart with files:
curl -X POST "http://localhost:8787/messages" \
-H "x-api-key: YOUR_ADMIN_KEY" \
-F 'event={"type":"post","payload":{"title":"My post"}}' \
-F 'photo=@photo.jpg'
See docs/CONFIGURATION.md for complete guide.
Define types in zobox.config.toml:
[types.update]
description = "Generic status update"
channel = "Updates"
[sorters.updates]
type = "update"
files_path_template = "{baseFilesDir}/Updates/{date}/{eventId}/{filename}"
append_to_file = "/home/workspace/Inbox/updates.md"
destination = "store_only"
Control where attachments are stored using tokens:
{baseFilesDir}: Base files directory{channel}: Item channel{date}: ISO date (YYYY-MM-DD){eventId}: Item UUID{timestamp}: Sanitized timestamp{filename}: Final filenameExample: {baseFilesDir}/{channel}/{date}/{eventId}/{filename}
Renders: /home/workspace/Inbox/files/Updates/2025-11-22/550e8400.../photo.jpg
original: Keep original filenametimestampPrefix: Prefix with 20251122T123456_eventIdPrefix: Prefix with item UUIDuuid: Replace filename with new UUIDDefine routing in routes.json:
{
"destinations": {
"store_only": {
"kind": "noop"
},
"publish_to_worker": {
"kind": "http",
"url": "http://localhost:9000/zobox/messages",
"method": "POST",
"enabled": true
}
}
}
Reference in sorter:
[sorters.posts]
type = "post"
destination = "publish_to_worker"
Given base_dir = "/home/workspace/Inbox":
/home/workspace/Inbox/
zobox.config.toml
routes.json
inbox/
YYYY-MM-DD/
<message-id>.json # Message envelopes
files/
<channel>/
YYYY-MM-DD/
<item-id>/
<filename> # Attachments
db/
zobox.db # SQLite index
migrations/
001_init.sql
logs/ # Reserved for future use
Table messages:
id, type, channel, created_atfile_path, file_dirattachments_count, has_attachmentssubscribed_by, subscribed_atsummary (reserved for future previews)tags (JSON string)Indexes on created_at, type, channel, has_attachments, tags for fast queries.
FAQs
Zo-native inbox + sorter + router engine.
We found that zobox demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.