@mika/undercurrent (1.0.0)

Published 2026-05-19 06:50:50 +00:00 by mika

Installation

@mika:registry=
npm install @mika/undercurrent@1.0.0
"@mika/undercurrent": "1.0.0"

About this package

Undercurrent

Undercurrent is the reference server implementation for the server side of Blackcurrant.

It helps an Express application expose selected Postgres-backed resources through the Blackcurrant sync, reconciliation, mutation, and server-manifest protocol. The app still owns authentication, domain rules, non-synced tables, and server-side Postgres migrations.

Undercurrent is not the authoritative source for the Blackcurrant protocol. When protocol behavior is in question, use ../../blackcurrant/main.

Protocol References

Read these first when wire behavior is in question:

  • ../../blackcurrant/main/README.md: Blackcurrant client runtime overview.
  • ../../blackcurrant/main/WIRE.md: authoritative HTTP and SSE wire contract.
  • ../../blackcurrant/main/SERVER.md: server implementation guide.
  • ../../blackcurrant/main/requirements/: client-side requirements that exercise the server-facing contract.

Undercurrent documentation should link to those files instead of duplicating Blackcurrant protocol rules.

What It Solves

Undercurrent gives apps a conventional way to:

  • serve GET /sync/<visibility>/<seq>?version=<runtime-version>
  • serve POST /reconciliation/<seq>?version=<runtime-version>
  • generate the Blackcurrant server manifest for the current app version
  • expose resource mutation routes
  • write managed Postgres rows and journal entries in one transaction
  • build compact sync frames from a durable journal
  • reconcile complete visible object sets
  • track principal visibility versions
  • coordinate open sync streams with app auth routes
  • export OpenAPI fragments for managed routes

Postgres remains the application database. Undercurrent only manages resources registered with it.

Sketch

import express from "express"
import postgres from "postgres"
import { Undercurrent } from "undercurrent"

const app = express()
const sql = postgres(process.env.DATABASE_URL)

const undercurrent = Undercurrent({
  app,
  sql,
  version: "2026.05.13",
  clientMigrations,
  principal: async (req) => req.user ? `user:${req.user.id}` : "anonymous",
})

const users = undercurrent.resource("User", {
  optimistic: true,
  fields: {
    fullName: "text",
    phone: "text",
    hasPassword: "boolean",
  },
  privateFields: {
    passwordHash: "text",
    createdFromIp: "text",
  },
  visible: ({ sql, principal }) => sql`
    select "id"
    from "Users"
    where ...
  `,
})

users.modify(async (object, ctx) => {
  if (ctx.principal !== "superadmin1337") {
    throw ctx.forbidden("I don't want you to do that.")
  }

  return {
    ...object,
    fullName: object.fullName.trim(),
  }
})

await undercurrent.ready()

This is a v1 design sketch. See API.md for the proposed API surface.

HTTP Paths

The summaries here are orientation only. Use ../../blackcurrant/main/WIRE.md for exact request and response contracts.

Path Purpose
GET /sync/<visibility>/<seq>?version=<runtime-version> Opens the Blackcurrant SSE stream. The first data message is terminal versionRequired or accepted manifest; accepted streams then establish hello and send compact frames or reconciliation.
POST /reconciliation/<seq>?version=<runtime-version> Repairs the client's complete visible object set from retained authoritative ids and returns the new frontier as streamed NDJSON.
POST <resource-path> Accepts a full-object add mutation for one explicitly enabled resource create operation.
PUT <resource-path>/<id> Accepts a full-object modify mutation for one explicitly enabled resource modify operation.
DELETE <resource-path>/<id> Accepts a delete mutation for one explicitly enabled resource delete operation.

Login, logout, session management, uploads, and other application-specific endpoints belong to the host application. They can still use undercurrent.write(...) when they need to mutate managed resources.

Documents

Path Purpose
ARCHITECTURE.md V1 architecture, component responsibilities, and data flow.
API.md Proposed Undercurrent application API.
SCHEMA.md Postgres, resource, manifest, and serialization schema contract.
UPGRADING-2X.md Initial migration guidance for Kotte/Blackcurrant 2.x-style servers.
AGENTS.md Agent-specific repository instructions.
WORKFLOW.md Staged change workflow for requirement-bearing work.
VERIFICATION.md Local verification model, requirement domains, and proof rules.
DECISIONS.md Durable project decisions.
requirements/ Undercurrent requirements, once behavior is specified.
changes/ Per-change staged workflow artifacts.
test/ Canonical executable proof, once implementation work begins.

../../kotte contains a production server for an earlier Blackcurrant 2.x-style sync protocol. It is useful migration context, especially for journal-backed sync, route/model separation, Postgres notifications, and visibility repair operations. It is not authoritative for Blackcurrant 3 behavior.

Dependencies

Dependencies

ID Version
express ^5.2.1
postgres ^3.4.9
yaml ^2.9.0
Details
npm
2026-05-19 06:50:50 +00:00
29
mikabytes
UNLICENSED
134 KiB
Assets (1)
Versions (2) View all
1.0.1 2026-05-25
1.0.0 2026-05-19