@serve.zone/coremail
CoreMail is the authenticated mail persistence and delivery-orchestration service for serve.zone workloads. End-to-end platform integration is not released yet: dcrouter still needs the gateway handlers, and Coreflow still needs to provision and reconcile bindings without proxying message traffic.
Installation
pnpm add @serve.zone/coremail
CoreMail installs on Linux only. Its SMTP submission listener is built on
@push.rocks/smartmta, which declares os: linux and ships the prebuilt Rust
mailer-bin for linux-x64 and linux-arm64 — CoreMail's own runtime target.
Installing on macOS or Windows fails at the dependency, by design; develop
against a Linux container or host.
The package exports the service lifecycle and its strict configuration reader:
import { CoreMail, readCoreMailConfig } from '@serve.zone/coremail';
const coreMail = new CoreMail(readCoreMailConfig());
await coreMail.start();
process.once('SIGTERM', () => {
void coreMail.stop();
});
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
Architecture
The integration architecture is:
workload
└─ @serve.zone/platformclient
└─ authenticated TypedSocket + grant-authorized HTTPS transfers
└─ CoreMail
├─ SmartData: bindings, grants, submissions, delivery state
├─ SmartBucket: message parts and immutable MIME objects
└─ authenticated TypedSocket ── dcrouter mail gateway
dcrouter ── grant-authorized HTTPS transfers ── CoreMail transfer origin
Cloudly desired state ── Coreflow reconciliation ── CoreMail (required integration)
CoreMail enforces these boundaries:
- Workload, tenant, binding, credential version, binding revision, and desired state epoch are server-owned session authority.
- Active and draining bindings derive their exact permitted operation set from the shared contract; disabled bindings cannot authenticate.
- Every reconnect requires a new Argon2id-authenticated handshake.
- TypedSocket tags are routing metadata, never authentication.
- Message bytes never travel as JSON, base64 RPC payloads, or VirtualStreams.
One-time grants authorize bounded HTTP
PUTorGETtransfers. - Only grant-token SHA-256 digests are persisted. Plaintext bearer and credential material is never stored or logged.
- SmartData owns all structured persistence, indexes, cursor pagination, fixed-window quotas, pending-inbound gauges, compare-and-set transitions, and worker leases.
- SmartBucket owns all message parts and immutable serialized MIME objects, with exact length and SHA-256 reconciliation.
- The service has no filesystem persistence path and no raw MongoDB access.
Runtime surfaces
One strict hostname surface is exposed:
GET /livereports process liveness.GET /readyreports database, exact object-storage, desired-state, authenticated gateway, and SMTP submission listener readiness.GET|PUT /transfers/:grantIdconsumes one-time transfer capabilities.GET /socketupgrades to the authenticated TypedSocket RPC transport.
When the desired state enables it, an SMTP submission listener (MSA) runs on
its own port. It offers STARTTLS and accepts AUTH only on an encrypted
session — the username is a bindingId and the password any accepted
credential secret of that binding. Accepted messages go straight to the durable
outbound pipeline as exact bytes; the embedded SMTP stack stores, queues and
forwards nothing. A listener whose certificate or private key material does not
resolve stays down and is reported unavailable.
HTTP TypedRequest and built-in routes are disabled. WebSocket messages are limited to 64 KiB, unauthenticated connections have five seconds to complete their first authentication request, and HTTP connection/header/request deadlines are enforced by SmartServe.
Configuration
CoreMail requires Coreflow and the deployment secret foundation to provide
runtime configuration. For Interfaces v23 secret material, the workload must be
launched through workloadinit protocol v1. The platform integration must write
the verified map and secret files; workloadinit injects their exact values into
the process environment immediately before executing CoreMail. CoreMail does not
fetch, decrypt, or persist runtime secret material itself. Until the dcrouter
and Coreflow integrations are released, a platform CoreMail deployment is not
ready. Malformed startup configuration terminates
startup. Missing desired-state secret references keep the affected gateway or
cursor operation unavailable.
The SMTP submission listener is configured entirely through desired state
(smtp): enabled, port, hostname, and tls.certificatePemSecretKey /
tls.privateKeyPemSecretKey, which name runtime secret keys holding PEM text —
never the PEM values themselves. An omitted or disabled smtp section keeps the
API-only surface; an enabled one whose secret keys do not resolve leaves the
listener down. Changing any of these values restarts the listener in place.
/opt/serve.zone/runtime-assets/workloadinit/v1/workloadinit run \
--map /run/serve.zone/workloadinit-map-v1.json -- node cli.js
| Variable | Purpose |
|---|---|
COREMAIL_PORT |
Listener port; defaults to 3000 |
COREMAIL_HOSTNAMES |
Comma-separated canonical strict-surface hostnames; defaults to coremail.serve.zone |
COREMAIL_SERVICE_ID |
CoreMail service identity |
COREMAIL_TASK_ID |
Current immutable workload task identity |
COREMAIL_ROLLOUT_ID |
Current rollout identity |
COREMAIL_ROLLOUT_GENERATION |
Current rollout generation |
COREMAIL_IMAGE_DIGEST |
Current immutable sha256: image digest |
COREMAIL_MONGODB_URL |
MongoDB descriptor URL consumed only by SmartData |
COREMAIL_MONGODB_NAME |
SmartData database name |
COREMAIL_MONGODB_MAX_POOL_SIZE |
Bounded SmartData connection pool; defaults to 50 |
COREMAIL_STORAGE_DESCRIPTOR |
SmartBucket descriptor JSON |
COREMAIL_BUCKET_NAME |
SmartBucket bucket name |
COREMAIL_CONTROL_BOOTSTRAP |
Verifier-only Coreflow bootstrap contract JSON |
${gateway.credentialSecretKey} |
Runtime-only dcrouter peer credential referenced by desired state |
${cursorKeys[].secretKey} |
Runtime-only HMAC keys referenced by current/retiring desired-state cursor keys |
COREMAIL_CONTROL_BOOTSTRAP contains verifier material only. The matching
plaintext control credential is delivered only to Coreflow. Desired state
contains key references for gateway and rotating cursor credentials, never
their plaintext values. gateway.endpointUrl is the dcrouter TypedSocket
endpoint. gateway.coreMailTransferOrigin is CoreMail's canonical HTTPS origin;
dcrouter must return that exact origin during authentication before it can use
CoreMail-issued path-only transfer grants.
Persistence and delivery behavior
Outbound submission preparation is idempotent per authenticated binding.
The first durable insert consumes one atomic fixed-UTC minute and day quota
unit; exact replays consume none.
Every part has a unique immutable object key and exact declared integrity.
Finalization reads verified parts, produces deterministic MIME with no Bcc
header, publishes that MIME exactly once, and queues a lease-fenced worker.
The downstream transport identity is the CoreMail submission ID and remains
stable across ambiguous responses and retries.
Every outbound submission records how it entered CoreMail. API submissions are composed from declared parts as described above. An SMTP submission is accepted as exact RFC822 bytes: it has no part descriptors, its bytes become its immutable MIME unchanged, and it enters the same lease-fenced worker in the same state a finalized API submission does. It is subject to the same binding authority, sender authorization, recipient validation, serialized-MIME byte budget, and minute and day quota. Records written before this discriminator existed are read as API submissions.
Inbound SMTP recipient resolution returns short-lived opaque handles. The
gateway uploads one immutable MIME object, after which CoreMail resumes a
SmartData saga that consumes handles and creates one delivery per binding.
Only active, inbound-capable bindings claim their configured recipients.
Draining, disabled, and otherwise unowned recipients return unhandled, which
allows the gateway to continue its next configured resolver instead of issuing
an SMTP rejection.
Pending, fetching, and fetched deliveries consume the binding's pending-inbound
quota until the first successful acknowledgement.
Workloads list deliveries through a bounded cursor, fetch MIME through a
one-time grant, and may acknowledge only after the exact fetch completes.
Cursor signatures rotate through current and bounded retiring desired-state
keys without exposing runtime secret material.
Every gateway-facing handler answers with the same privacy-safe typed error
envelope the workload handlers use, so the transport can tell a retryable
QUOTA_EXCEEDED or STATE_CONFLICT from a permanent refusal without ever
receiving a cause string.
Inbound deliveries carry the Message-ID and Subject read from a bounded
prefix of the stored message. The gateway message descriptor cannot carry
either, and a header scan that fails never costs a delivery — the fields simply
stay absent.
Per-binding counters are kept for each UTC day: submittedApi and
submittedSmtp when a submission is published to the worker, delivered,
deferred, failed and deadLettered on outbound transitions, and received,
acknowledgedProcessed and acknowledgedDiscarded on inbound ones. Each
increment commits in the same transaction as the durable transition it counts,
so a replayed transition — a repeated finalization, a re-applied gateway status,
a replayed handoff completion or acknowledgement — counts nothing. Counter rows
are retained for 90 days.
Desired-state activation uses immutable snapshots and a strictly increasing
configEpoch compare-and-set pointer. Replayed or stale configurations cannot
replace newer authority.
Terminal outbound submissions and acknowledged inbound deliveries retain their records and owned objects for 30 days. Abandoned outbound preparations and handoff/idempotency receipts also expire after 30 days. Expired transfer grants and recipient handles retain their records for another 24 hours. Pending, fetching, and fetched inbound deliveries are never age-purged; their MIME stays stored until acknowledgement and the acknowledged-delivery retention period have elapsed.
Development
pnpm install
pnpm run build
pnpm test
tsbuild check 'test/**/*'
The production image is built natively for linux/amd64 and linux/arm64:
pnpm run build:docker
pnpm run release:docker
License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license.md file.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read and understood these terms. If you do not agree with them, you must not use the repository.