One entry per @corbits/* module: mount it on an Interchange host and prove it
works. Each entry is a runnable program that asserts its own behaviour against a
real Postgres and exits non-zero if anything fails.
These are minimal integration proofs, not solutions. They answer "does this
module mount, and does it behave?" — nothing more. For an example of a module
being useful to an agent, see solutions/.
| Module example | What it proves |
|---|---|
| mailbox-inbox | @corbits/mailbox-core: deliver → list → read → mark-read, dedupe on retry, cross-principal isolation |
| artifact-library | @corbits/artifact-core: create → version → download, over both ContentStore backends |
| analytics-rollups | @corbits/analytics-core: ingest native events → rollups → rebuild-from-scratch equivalence |
| multi-core-host | All three on one host. Migration coexistence, one identity decision, no route collisions |
| shared-schema-host | Two cores in a schema of your choosing. One search_path, no tables in public |
Every entry mounts under /api — the prefix Interchange serves its own
routes under (app.route("/api/me", …), app.route("/api/tenants", …)). There
is no /v1 segment and no vendor prefix. The cores register their routes
root-relative and take no base path, so the host nests them:
const api = new Hono<AppEnv>();
mountMailbox(api, { db, bus, resolvePrincipal });
app.route("/api", api);which serves /api/me/inbox*. Artifacts serve /api/artifacts*, analytics
/api/analytics/*. One consequence worth knowing before you copy this: a core
inherits whatever the host already declared for the prefix it lands on.
Interchange declares app.use("/api/me/*", requireAuth), so the mailbox is
gated by the host and a signed-out caller gets a 401 that never reaches the
core — multi-core-host asserts exactly that, alongside artifacts and analytics
answering their own empty 200 on prefixes this host has not gated.
bun install # from the repo root — also builds the three cores
bun run modules # from the repo root — runs all fiveEach entry also runs on its own from its directory:
bun run start # drives the app in-process and asserts, then exits
bun run serve # binds the same app to a port so you can curl it
# PORT=3101 bun run serveThey need one. Any Postgres works; the default URL is
postgres://postgres:postgres@localhost:5459/ex_<name>, and every entry takes
EXAMPLES_DATABASE_URL to point somewhere else.
docker run -d --name corbits-examples-pg \
-e POSTGRES_PASSWORD=postgres -p 5459:5432 postgres:16
for db in ex_mailbox ex_artifacts ex_analytics ex_multicore ex_shared_schema; do
docker exec corbits-examples-pg psql -U postgres -c "CREATE DATABASE $db"
doneEach entry truncates its own tables on startup so it is re-runnable, so give it a database you do not mind it owning.
None of these need inference — they exercise the module, not an agent.
@corbits/mailbox-core, @corbits/artifact-core and @corbits/analytics-core
are not on npm yet. Until they are, this repo vendors their repositories as git
submodules under cores/ and resolves them as bun workspace members. The
@intx/* packages they peer-depend on come from npm at 0.2.2, pinned in the
root package.json catalog.
cores/mailbox -> corbitsdev-mailbox
cores/artifacts -> corbitsdev-artifacts
cores/analytics -> corbitsdev-analytics
They resolve through each package's normal exports map to its built dist.
dist/ is gitignored inside each core, so
the root postinstall builds all three; if you check out a core at a new
commit, re-run bun install (or bun run build:cores) before running an
example.
Every @corbits/* README says "mount it onto any Interchange host" and shows a
two-line mountX(app, opts) call. None of them says what producing that app
takes: a session reader, a sidecar router, an event-collector registry, and a
SessionService whose every verb throws because these hosts run no agent
sessions.
That is the same in every example, so it lives once in
@corbits/example-kit — along with the assertion
helpers and the environment-driven inference resolver. What is not shared is
the mount: each entry keeps its own src/app.ts with the mountX call, the
seams that host supplies, and the reasons it supplies them. That file is the
lesson; the kit is the scaffolding around it.