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