Skip to content

Changelog

Grouped by what shipped rather than by commit. Fixes say what was broken and what it had been doing, because an entry that only says improvements cannot tell you whether the thing that affected you is the thing that changed.

Sign-up, the consent screen, and a console you can see traffic in

Three surfaces that existed as backends with no way to reach them, and seven migrations that had never been applied to the database anyone was using.

  • Added

    Create an account with a password

    Name, email, a unique username and a password. Verification links last 12 hours and reset links one hour, both single use. Signing in before confirming leads to a page that can send another link rather than to a dead end.

  • Fixed

    The OAuth consent screen did not exist

    The API had been redirecting people to it since MCP authorization was built, so every attempt to connect Claude, Cursor or ChatGPT ended on a 404 at the moment of granting access. Four other advertised URLs were in the same state, including the two the OAuth metadata publishes as its policy documents.

  • Fixed

    Seven migrations had never been applied

    Including the two observability tables and the four the MCP OAuth flow writes to. CI proved them against a throwaway container on every commit and nothing ever compared them against production. The API now reports schema drift on startup and on the admin overview.

  • Fixed

    Observability recorded nothing at all

    Two independent causes with one symptom: the tables did not exist, and the repository was declared on the runtime and never constructed. An empty dashboard and a quiet service look identical.

  • Added

    A traffic dashboard, per surface

    Requests, error rate, mean and p95 for the API, the MCP server and the worker separately, with breakdowns by country, device and method, and an expandable log carrying address, city, network operator and TLS details. Counts are exact; the log is sampled, and the page says which is which.

  • Added

    A mail hub that can reply and forward

    Conversations with bodies, attachments up to 8 MB, and inbound replies filed onto the thread they answer. Replies take no recipient: it is read off the message, so the endpoint cannot become a way to send mail from this domain to anywhere.

  • Added

    Fifteen pages of documentation and comparison

    Comparisons against mem0, LangChain memory and vector databases, four use cases, three tutorials, an architecture page, and a Telegram connector guide.

  • Changed

    The admin console has a shell

    Sidebar navigation, the signed-in identity on every page, and empty, error and pending states throughout rather than only the successful one.

Two errors that reported themselves as crashes

Both were correct behaviour arriving at the client in the wrong shape.

  • Fixed

    A short password answered 500

    The policy error carried a code and a message and no status, so the mapper that duck-types on status classified a deliberate rejection as an unhandled crash. Somebody choosing an eight-character password was told something went wrong.

  • Fixed

    The MCP server passed TRUST_PROXY to Express unparsed

    A value of `private` reached Express as a literal address and it refused to start with `invalid IP address: private`. The parser moved into the auth package so both services read the setting the same way.

Deployment, the Telegram bot, and MCP over OAuth

The day the images actually reached production, after several attempts that reported success without shipping anything.

  • Added

    MCP over OAuth 2.1

    Dynamic client registration, PKCE with S256 pinned, resource indicators per RFC 8707, and the RFC 9728 challenge on an unauthenticated request. No API key in any config file.

  • Added

    A Telegram bot

    Forward a message, send a voice note or photograph a receipt. A chat binds to exactly one account, enforced by a unique index rather than by a read followed by a write.

  • Added

    Five images, five workflows

    API, worker, MCP, web and admin, each rebuilt only when its own paths change, pushed to GHCR and deployed by hook.

  • Fixed

    The baked configuration was one line long

    A multi-line secret passed through the wrong BuildKit input was truncated to its first line, and the build reported success. The build now prints how many variables it baked, so the next silent truncation is visible in the log.

  • Fixed

    The HTTP transport required a configured user

    Eleven MCP tools read the user from configuration rather than from the session, which on a multi-user server is a cross-tenant read. The runtime is now per user.

  • Added

    Model providers rotate across accounts

    Round-robin at both levels, keys and vendors, interleaved so one vendor being unavailable does not burn two consecutive attempts.

The pipeline end to end

Ingestion, extraction, consolidation and recall, and the first deployment that ran against real infrastructure rather than a test double.

  • Added

    OCR and transcription on hosted providers

    The Python service was removed. Images and scanned PDFs are read, audio is transcribed, and neither the handler nor the queue knows which vendor did it.

  • Added

    Conflicts are kept, not resolved

    A new fact that disagrees with a stored one supersedes it rather than overwriting it, and both keep their sources and dates.

  • Added

    Connectors for mail, Drive, Slack, Teams and meetings

    Each carries the authorisation it read with, through extraction and consolidation, so recall cannot widen what the source allowed.

Several of these have a post explaining what went wrong and why nothing caught it.

Read the engineering posts