postmq v0.14.16

What's new in PostMQ

Updated 2026-11-01.

v0.14.00 through v0.14.16

No user-visible changes — internal reliability, security and tooling.

An owner can release a resource that will never get a clean check

Some resources can never get a receipt that says they are clean: the host is gone, or its provider cannot reach that verdict at all. The workspace owner can now release one from the Resources page on their own word. PostMQ records it as exactly that, never as a clean receipt.

What's new for you

  • On the Resources page, the owner can release a reconciling or quarantined resource with Release without a clean check. The panel first shows the claim the resource is waiting on, when that claim ended, the report the release would override and when an adapter was last seen. For a quarantined resource, that report is the one that quarantined it.
  • The owner gives a reason of up to 500 characters and types the resource's name to confirm. The release writes no receipt and is never a verified_clean.
  • A resource that is not withdrawn goes back in service, and the first claim in its queue is granted, as on any other return to service. A withdrawn resource stays withdrawn; the release only ends its wait for a clean check.
  • Every member then sees Released by the owner on the resource, and anyone who can see it reads owner_released_at, until a later receipt that counts says verified_clean. The owner also sees their reason there, and the page counts owner releases beside denied claims and stale-fence refusals.
  • No agent call can release a resource this way, including one made with the owner's own credentials.

Under the hood

  • Each release is recorded on the workspace's tamper-evident audit chain, with the owner as the actor, the reason, the claim and the report it overrode. Nothing is written to the claim that ended.
  • The panel stays tied to the claim it was opened for. If the resource starts waiting on a different claim while the panel is open, the button is disabled and the panel says the claim changed.

An agent can stop an advisory repeating once it has told you

An agent that has passed an advisory on to you can now say so, and that advisory stops being counted for that agent. Only for that agent: you still see it, and your other agents still hear about it.

What's new for you

  • Once it has reported an advisory, an agent calls mark_advisory_reported over MCP, or POST /v1/advisories/{id}/mark-reported over REST, with the revision it read. It needs a credential and no scope, because it changes only that agent's own view.
  • For that agent, the advisory then drops out of list_advisories, the X-PostMQ-Advisories header, the one-line count on tool results and the advisories field of get_policies, until a new revision is published. list_advisories counts it under not_shown.reported, and include_dismissed=true returns it, marked.
  • It is not a dismissal. The dashboard's banner and Advisories page are unchanged, and a critical advisory stays on your banner until you acknowledge it. Marking a critical one stops it repeating to that agent only.
  • A repeated mark is harmless. A mark for a revision that has since moved on is refused, and the response names the current revision.
  • PostMQ's server instructions now tell an agent to mark an advisory once it has reported it. That reaches clients that show those instructions to the model, such as Claude Code. The kit's session skills do not call it yet.

Under the hood

  • Each first mark is recorded on the workspace's tamper-evident audit chain, with the agent as the actor.

v0.13.96 through v0.13.99

No user-visible changes — internal reliability, security and tooling.

The dashboard shows its version, and postmq.com links the release notes

The dashboard's version now sits beside the PostMQ logo, and it links to these notes. postmq.com's footer links them too.

What's new for you

  • On screens 640px wide and up, the dashboard's top bar shows the version beside the logo, whether or not you are signed in. It links to /release-notes. On a narrower screen the version stays in the page footer, which links to the same page.
  • postmq.com's footer has a Release notes link in its Docs & company column. It opens the same page, which needs no sign-in.

v0.13.70 through v0.13.95

No user-visible changes — internal reliability, security and tooling.

An owner's withdrawal holds, and adapters can bring their own hardware

The claim sidecar is now a small SDK. An adapter for a machine PostMQ knows nothing about can supply what a job runs in and what its receipts can say, while the sidecar keeps the claim. And a resource the owner takes out of service now stays out until the owner returns it.

What's new for you

  • An adapter plugs its own provider into the sidecar with --provider path/to/file.py:factory. The provider supplies what the job runs in and what its receipts report; the sidecar keeps the lock, the journal, the claim, the renewals and the launch order. Every provider call has a time limit, and a call that overruns or fails never produces a verified_clean receipt.
  • postmq-claim.py serve registers a resource from what its provider declares, reports its health every 15 seconds, and reconciles it whenever it is reconciling or quarantined, until you stop it.
  • A withdrawal the owner makes from the Resources page now holds. An adapter registers its resource each time it starts, and that used to bring back a resource the owner had withdrawn. Registering again now returns only a withdrawal an adapter made, and the owner can take over an adapter's withdrawal to keep the resource out.
  • The Resources page has Return to service, which clears a withdrawal whoever made it. The claim holder and anyone watching the resource are told.
  • An adapter now sees which claim a reconciling resource is waiting on, so postmq-claim.py reconcile with no --claim reports on that claim even when this machine's journal never recorded it. Only the resource's owner and its adapters see it.

Under the hood

  • PostMQ still ships only the generic provider. A provider that can prove a GPU is clean is written for that hardware; this release adds the interface it plugs into, not a provider for any particular GPU.
  • Withdrawals made before this release were classified from the audit record of who made them. One with no record holds as the owner's, so it stays out until the owner returns it to service.
  • Kit 1.11.0 carries claim 1.2.0, and so does the postmq-claim Claude Code plugin.

PostMQ can tell your workspace about kit updates and incidents

PostMQ now has a channel for what a workspace should know: a kit update, a deprecation, an incident, a change to the terms. Your agents hear about an advisory when a session starts and pass it to you word for word, and the dashboard shows it too. An advisory is information. It never authorises an agent to do anything.

What's new for you

  • At the start of a session an agent calls list_advisories and tells you each advisory's severity, whether it applies to this project, and its text, quoted verbatim. It does not act on one: anything an advisory asks for comes to you first, and in an unattended run the agent reports it and carries on with its task.
  • Clients that never show the server's instructions still hear about advisories. While any are active, a tool result can carry a one-line PostMQ advisories: count, no more than once a session for a given set on each server. Over REST, GET /v1/advisories returns them, and responses to a bearer credential carry an X-PostMQ-Advisories header with the same counts.
  • The dashboard shows a banner while advisories are active, and an Advisories page. There the account owner or an owner-role member dismisses or acknowledges an advisory, confirms that a critical kit update is done, and sets the lowest severity your agents hear about. Critical advisories reach them at any setting.
  • The installer kit's session-start hook prints a count of this project's advisories, never their text. Each install's stamp now names its copy, and when your agent reads advisories or reports usage over MCP, PostMQ registers that copy, so an advisory about a kit update can say how many of your projects are behind. A copy you have deleted can be retired so it stops being counted.

Under the hood

  • A read over REST never registers a copy of the kit; only an agent calling over MCP does.
  • Dismissing, acknowledging, confirming, retiring a copy and changing the minimum severity are each recorded on the workspace's tamper-evident audit chain.

Agents can share a GPU host or a test gate without colliding

A resource is anything more than one agent might want at once: a GPU host, a CI gate, a licence seat. An agent now claims it through PostMQ, holds it exclusively while its job runs, and releases it with a receipt that says what the job left behind. Nobody else is granted the resource until that receipt, or an adapter's own look, says it is clean.

What's new for you

  • Existing credentials do not gain the new scopes. To claim or find resources an agent needs a new credential with claim and discover_resources. An agent that speaks for a resource, its adapter, also needs manage_resources.
  • An adapter registers a resource and reports its health and telemetry. A claimant claims it, and is granted it, queued for up to max_wait_seconds behind the current holder, or denied with a reason it can act on. Claims are exclusive: one holder at a time.
  • A granted claim carries a fence and must be admitted by one of the resource's adapters within five minutes by default, or it expires. While the job runs the holder renews at about a third of the claim's lifetime. A stale fence is refused, so a holder that lost its claim cannot act as if it still held it.
  • A resource is available again only on a verified_clean receipt from an account in its adapter set that names the resource's own provider and machine. Anything less leaves it reconciling, in front of the workspace owner. residue or cleanup_failed from anyone quarantines it. A claim cancelled before it was admitted frees the resource at once.
  • Changes to your claim arrive as resource_notice messages in your inbox. A notice is a prompt to re-read the claim, never the authority. PostMQ alone writes them, so send and validate refuse that template. An agent can describe what its claim is doing to another agent with the new resource_handoff template, which frees nothing.
  • The installer kit has a new Resource claims component, also a postmq-claim Claude Code plugin. postmq-claim.py runs one command under a claim. It claims the resource or queues for it, waits on the wake stream with a 30-second re-read and never reads your messages. It starts the command, keeps the claim alive, and releases it with a receipt. After a crash, reconcile reports what this machine's record of the last job shows. It runs on Linux and macOS, not yet on Windows. pmq claim run runs the same script, for those building the CLI from source.
  • The dashboard has a Resources page. Every member sees, for the resources they can reach, who holds each one and for how long, who is waiting, its health, the receipt that quarantined it and what happened to it recently. The owner chooses its adapters and how it is lent, and can revoke any claim or withdraw any resource.

Under the hood

  • The kit's sidecar is the generic adapter, and it says what it can see and no more. Its controls are advisory: a process that leaves the job's process group can survive, and a launch outside the sidecar is not prevented. Its receipts free only a resource registered to accept them, such as a unit-test gate. Adapters that can prove a GPU is clean are being built and are not in this release.
  • Before it starts a command, the sidecar takes a lock shared by every sidecar the same user runs on that machine. It records its intent in an append-only journal, and records the job's process group before the job starts. So a crash can never make a job that started look as if it never did.
  • Every claim transition and the notice it produces commit in one transaction, and each lands on the workspace's tamper-evident audit chain.
  • /docs/resources describes the roles, what a receipt proves, and the sidecar end to end.

Your installed kit can tell when it is out of date

A copy of the kit never updates itself, so until now nothing told you it was stale. Every install now records what it wrote, the session-start hook prints it, and the PostMQ server names the current versions, so an agent can tell you when the kit in your project is behind. It tells you; it never updates anything unasked.

What's new for you

  • Every install writes a small stamp, postmq-kit.json, beside the client's scripts. It names the kit release, the version of each component you installed and a hash of every file written. Each component has its own version, so a change to Wake does not mark a project that only installed the session-state kit as out of date.
  • At session start the kit's hook prints the installed versions in a == PostMQ kit == block. It makes no call to PostMQ, so it cannot know what is current.
  • The PostMQ server's instructions name the current version of every component. Where the client shows those instructions to the model, as Claude Code does, an agent whose kit is older opens its first reply with a one-line notice from PostMQ and offers to update. It updates nothing until you say so. Codex and ZCode do not show the server's instructions to the model, so there the start-session skill compares against postmq.com/kit/manifest.json instead.
  • Updating is installing again. Every file still matching the hash recorded at install is replaced; a file you edited is left for you to review. A kit from before 1.4.0 recorded no hashes, so its first update skips each changed file: review them, then pass --force once.
  • A re-install now adds a setting a newer kit gave an existing hook, such as the usage reporter's 30-second timeout on Claude Code, and keeps any value you set yourself.
  • On Claude Code, Wake is its own plugin, postmq-wake, so installing the session plugin no longer wires Wake's hook. A plugin install says it came from a plugin, and the update is yours to run through the marketplace: claude plugin marketplace update postmq, then claude plugin update for each PostMQ plugin, then a restart. The agent is told never to write kit files into the project over a plugin, which would wire every hook a second time.

Under the hood

  • Only the session plugin has a session-start script, so the Wake plugin's version is recorded in its own stamp but printed nowhere.

v0.13.54 through v0.13.69

No user-visible changes — internal reliability, security and tooling.

Wake reaches ZCode, and on Codex it needs no click

Wake shipped with what each client could do measured on paper. It has now been measured in real use on every client, and the kit follows what was observed.

What's new for you

  • Wake is offered on ZCode. The agent runs the receiver's wait as a background task, and ZCode starts a turn in the idle session when that task finishes. Measured on Windows: about 13 seconds from the receiver's exit to the new turn, in one run.
  • On Antigravity the agent runs wait, not listen, as a background task and starts it again after each wake. Antigravity resumes the idle session when the task finishes; listen's output does not.
  • On Codex, in the desktop app with the conversation open, a queued wake starts a turn by itself. An idle conversation started one 7.9 seconds after the wake was queued; a wake queued while the agent was mid-turn ran as its own turn when that turn ended. A conversation that is not open is not woken, and the wake stays queued in it. So the Codex agent ends its turn rather than waiting or polling inside one.
  • On Windows run one listener per machine. Notifications go to stderr or to a log in the receiver's state directory.
  • The usage reporter now finds its credential in the same places the wake receiver does, including a credential file, so one credential set up for the receiver serves both.

The session-state kit works as written on real clients

A review of the kit against a live server found the skills calling it in ways it did not accept, and the usage reporter running out of time on Claude Code. Both are fixed, with tests that make every written-out call for real.

What's new for you

  • The start-session skill's lookup for a session to resume works. It asked for build sessions in a form the server refused, so every resume lookup failed.
  • Session start no longer waits on GitHub. The hook's one network call is gh pr list for your open pull requests, with a two-second deadline.
  • The end-session skill blocks on any failing check, not only required ones, which mattered on a repository with no branch protection. It also leaves in place the working copy the session runs in, because the usage hook runs from it after the session ends.
  • On Claude Code the usage reporter's hook gets 30 seconds instead of the shared 1.5-second default. The whole run, reading and sending, has one 25-second deadline inside that.
  • A conversation that opened more than one build session is split between them on Claude Code, whose transcript records each turn's time. On the other clients the whole conversation goes to the latest build session.
  • A read that was partial, unreadable or empty is refused rather than reported, because a report replaces the counts already recorded and a short one would overwrite a correct row.

The installer kit keeps your credential to itself

The kit's two scripts that carry your credential, the usage reporter and the wake listener, now send it only to the address you configured and never print it. The wake listener also gains the pieces the Wake launch left for later.

What's new for you

  • A credential with a stray line break, space or control character is refused before anything is sent. The message names the file or variable it came from and never shows the value. A pasted line ending is trimmed rather than refused.
  • Neither script follows a redirect. A redirect is refused and reported with its status code; the address it points to is never contacted or shown. The fix is to configure the final address.
  • Both scripts refuse a plain http:// address unless it is this machine, and a request to this machine is never routed through a proxy.
  • The wake listener can run an unattended Antigravity agent. feed writes Antigravity's own input format, chosen from the agent command's name, or set with --shape. In our testing Antigravity took a turn on a wake in this format; a full acknowledgement round trip has not been observed yet.
  • The unattended Codex worker, listen --exec, now has the same hourly wake budget as the unattended Claude Code worker: twelve commands an hour by default, counted when each command starts.
  • Each listen line carries the notice to act on as prompt, and withholds the other agent's subject unless you ask for it with --peer-text.

Under the hood

  • Anything the server sends back is printed with your credential removed, including in desktop notifications and in the environment of an --exec command.
  • A notification that cannot reach the desktop is written to a log in the listener's state directory, never to output an agent reads.

v0.13.03 through v0.13.52

No user-visible changes — internal reliability, security and tooling.

PostMQ wakes your agents

A message used to wait in an agent's inbox until that agent next called get_pending, and an idle agent had no reason to call it. Wake closes that gap: a listening receiver hears about a message when it can be leased and wakes the agent where its client allows, and the dashboard now shows whether each agent is actually checking.

What's new for you

  • GET /v1/messages/events is a Server-Sent Events stream of your own inbox. When something there becomes leasable it sends a wake event with the count waiting and the newest message's sender, template, subject, priority and correlation id. It needs the get_pending scope, and opening one costs one get_pending rate-limit token.
  • A wake is a readiness signal, never a delivery: no payload, no lease. You still call get_pending and ack, so leases, redelivery, idempotency and at-least-once delivery are unchanged, and a duplicate wake costs one empty poll.
  • The connection is outbound, so it works from a laptop or a CI worker with no public address. Webhooks stay the push path for hosted services.
  • Reconnect with Last-Event-ID and the first event says whether anything changed while you were away, so a reconnect after nothing changed does not wake the agent again. Every connection starts with the whole inbox.
  • The installer kit has a new wake component: one standard-library Python file that does what each client allows. On Claude Code a Stop hook wakes an idle session by itself. On Codex no hook can start a turn, so the wake is queued into the session's own thread and raised to you as a desktop notification. On Antigravity the agent runs the listener as a background task. It is not offered on ZCode yet, because no wake path has been measured there.
  • A wake budget limits how often two agents can wake each other on your tokens: three wakes in a row without a human turn on Claude Code, twelve an hour for the headless Claude Code worker. Past it, the wake goes to you instead.
  • The AI accounts page has a Check-ins column, and each account a Check-ins card: whether a wake stream was open in the last 150 seconds, the last full check of the inbox, the last filtered check, the last ack, what is waiting and for how long, and what is in flight. An agent is marked Stalled when its oldest waiting message has waited 15 minutes with no full check since it arrived.

Under the hood

  • The server reads the listening inboxes in batched statements of up to a hundred per replica, about once a second, using the same visibility rules get_pending leases under. So a message that becomes leasable on its own — a nack's back-off running out, an expired lease returning it — wakes the agent too, and a wake never names a message those rules would keep from you, though the poll it prompts can still come back empty.
  • A lease or an ack can only drain the stream, so an agent's own ack never wakes it.
  • The stream re-checks its credential every 30 seconds, so revoking the credential or freezing the account ends it within about a minute.
  • The wake notice a Claude Code session receives, or that is queued into a Codex thread, carries none of the other agent's own words. The agent reads the message itself through get_pending, where it is plainly a message from another agent.

MCP clients that send arguments as text can hand off work

Some MCP clients send an object or a list argument as a JSON string. PostMQ refused those calls, so no structured handoff could be sent from such a client.

What's new for you

  • Where a tool's published schema says an argument is an object or a list, a string that parses as exactly that is now accepted as if it had been sent that way. Anything else is refused as before.
  • That covers send and validate payloads and the pull-request entries on a build session, from ZCode, the client that showed it.
  • The published tool schemas are unchanged.

Under load, PostMQ says when to try again

When PostMQ cannot take a request right now, it now says so on every endpoint and every messaging tool, with a retryable 503 and how long to wait, instead of an error with nothing to act on.

What's new for you

  • Every workspace's audit events are appended to its tamper-evident hash chain shortly after they are accepted. While a workspace's oldest unappended event is more than 10 seconds old, that workspace's sends and new leases are refused with a 503 service-unavailable error and a Retry-After header, or retry_after_seconds in MCP, until the chain catches up. Other workspaces are not affected.
  • Acknowledgements, nacks and lease extensions are never refused this way, so work already in hand finishes. Validation is not refused either.
  • Retrying an already accepted send with the same idempotency key can be answered with that 503 while its workspace is refused. The original send is never lost, and the retry never accepts it a second time.
  • A database that is momentarily at capacity now answers the same retryable 503 on every REST endpoint, where some paths answered a 500 with an empty body.
  • A genuine server fault answers 500 with a new internal-error code, listed in the error reference, a fixed message and the request id to quote when you report it.
  • In MCP, send, validate, get_pending, ack, nack and extend_lease answer the same retryable error in the tool's own result, instead of an opaque "An error occurred" message.

Under the hood

  • The worker that appends to the chain catches up faster. A pass costs what its batch costs rather than what the backlog costs, it keeps claiming while the queue is deep, and it appends a run of events in one step.
  • The check that looks for events which never reached the chain no longer re-reads all of history on every pass.
  • A refused workspace's repeated requests are answered without a database round trip, so refusals cannot slow the catch-up they are waiting for.

Revoking an account takes effect within one second

We changed a published guarantee and want to say so plainly. Revoking an AI account, freezing it, or deleting a workspace used to take effect on the very next request. It now takes effect within one second on every server.

What's new for you

  • Each server remembers an account's and a workspace's standing for at most one second, so for up to that second after a revoke, a freeze or a workspace deletion commits, a request can still be admitted.
  • Revoking the account is still the stronger way to cut off a credential you no longer trust. It takes effect within that second, where revoking a single credential can take up to 30 seconds to reach every server.
  • The documentation, the security page and the dashboard's revoke card now state this guarantee rather than the old one.

Under the hood

  • The memory exists so that a burst of requests from a refused workspace cannot exhaust the database it is waiting on. One second is a fixed ceiling: it can be lowered, never raised.

Every server screens sends against the current sanctions list

Every send screens the sender's and the recipient's workspace names against the US Treasury's OFAC sanctions list, and refuses the send if the list is not loaded. Three changes made that screen current, ready from the start, and cheap.

What's new for you

  • A newly started server loads the list before it accepts any request. It used to accept connections first and refuse sends with a retryable 503 for its first 12 to 15 seconds while the list downloaded, which happened on every deploy and every scale-up.
  • The MCP server now refreshes the list daily, as the REST API already did. Before, it screened against the list as it stood when it started.
  • Screening had been most of the cost of a send. It is now a small part of it, and every verdict is the same as before.

The privacy policy names everything it later clears

The privacy policy's list of what we collect now matches its list of what retention clears. Four fields you supply were named only in the sentence saying they get cleared.

What's new for you

  • The collection section now names message subjects, labels, extensions and the outcome summary an agent may attach when it acknowledges a message, alongside correlation ids.
  • That outcome summary is shown to members of the workspace in the dashboard, and is not returned by any API or MCP tool. The ack tool's description said the sender could see it. That was wrong in seven places, including this site, and every one now says what is true.
  • The privacy policy and terms remain v0.1 drafts that counsel has not reviewed, and each says so.

Under the hood

  • Retention itself is unchanged. It is available and enabled per environment.

Other changes in the v0.13 series

No user-visible changes — internal reliability, security and tooling.

The token for where your data lives no longer names a region

data_residency is returned by GET /v1/workspaces/me and in a data-subject export. It read us-east, and since 16 September the data has been in a different US region than that name suggests. The field now names the residency boundary it was always meant to promise.

What's new for you

  • The value is us, where it was us-east. Code that compares this field against a string needs updating before it will match what the API now returns.
  • The new value names the commitment itself — a single United States residency boundary, with no EU option — and deliberately says nothing about which region implements it, so moving regions can no longer make it wrong.
  • us-central was considered and rejected. It would have been accurate on the day and wrong again at the next move, for a second breaking change on a field that will have more readers by then.
  • The retired value is reserved. It will not be reissued with a different meaning.

Under the hood

  • The change shipped in two parts, because a schema change is applied while the previous build is still serving every request. The first part accepted both values and started writing the new one; the second, once the first was live, converted the remaining rows and stopped accepting the old one. Between them a reader could see either value.
  • The guarantee is per-environment, since it is a migration rather than a code change: until an environment has applied the second part, its database still accepts the old token. An export generated before the conversion still contains whatever was stored at the time.

More of what you write is destroyed when retention runs

Retention clears the content of an envelope and keeps the record that it existed. Two fields you supply were being kept: the outcome summary on an assessment, and the correlation id you set to group related messages.

What's new for you

  • outcome_summary and correlation_id are now cleared wherever envelope content is cleared — ordinary retention, an account's anonymisation, and a takedown.
  • Retention had also been forward-only: an envelope whose content was already cleared was stepped over, so any of these fields it still held stayed indefinitely. Those envelopes are now revisited and cleared.
  • What survives is unchanged: the envelope row, its timestamps, and the audit record that the content was destroyed. Retention removes content, not the evidence that it happened.

Under the hood

  • The set of columns to clear is written once and rendered into each path, so the three cannot drift apart. They had already been written separately.
  • These sweeps are available and enabled per environment. They are not on by default.

The audit chain is written after the commit, not inside it

Every workspace has a tamper-evident hash chain over its audit events. Appending to it must be serialised per workspace, which put a lock on the path that accepts your messages. The append now happens on a separate worker.

What's new for you

  • Accepting a message and appending it to the hash chain are no longer the same instant. There is a window between them. On our development environment that window measured 247 seconds under load.
  • Atomicity is unchanged, and this is the part worth reading carefully. The audit EVENT is still written inside the same transaction as the thing it records — as a chain row when that workspace has nothing queued, or as a queued row when it does — and if the transaction rolls back, both disappear. Only the hash-chain APPEND is deferred.
  • Ordering is preserved. An event cannot be chained ahead of an earlier one from the same workspace.

Under the hood

  • Sixteen published surfaces, including our data processing agreement and privacy policy, said the chain row was written in the same transaction. That stopped being true on 16 September and the wording stood for thirteen days. Every one of them now carries the same clause: the hash-chain append may follow the commit. We would rather say this plainly than leave it to be discovered.
  • The worker runs in its own process, so the request path no longer competes with it for CPU.
  • If a single event cannot be chained, that workspace's chaining stops rather than skipping it — an ordered chain cannot omit a row without breaking. Accepting messages continues; only chaining pauses, and it is cleared by hand.

Three failures that answered 500 and should not have

A 500 means we broke. Each of these was the system declining work it could not take right then, which is a different thing and already has its own answer in the wire contract.

What's new for you

  • A database capacity refusal now answers 503, with a Retry-After header, instead of 500. Measured on a load run: 69 of its 500s were the database's own worker-limit governor declining work, not a failure to do it.
  • A send that loses a database deadlock is retried rather than returned to you.
  • A transient lock conflict on the audit path no longer reaches you at all.
  • A 503 from these paths is a refusal you can retry, not a failure to report.

Other changes in the v0.12 series

No user-visible changes — internal reliability, security and tooling.

A new workspace opens on four steps

The first useful thing you can do in PostMQ needs three objects — a project, an agent, and a key scoped to that project — and they lived on three different pages. They are now one page, in order.

What's new for you

  • Signing up lands on a setup page rather than an empty overview. One card is open at a time: name a project, name an agent, issue an operational key scoped to that project, then connect.
  • The key's default scopes are read out as sentences. Individual scopes and an expiry are available behind Advanced, for the case where you want them.
  • The last step gives you the configuration to paste and a Check again button, so you can confirm the connection from the same page rather than guessing whether it worked.
  • Progress is worked out from your workspace rather than stored, so the page resumes at the first thing you have not done. Someone invited into a workspace that is already connected sees it as finished, because it is.
  • The previous two-track setup checklist is retired. Signing in still lands on the overview; it is signing up that now goes to the steps.

Dashboard buttons look like buttons again

A shared style rule that every button variant depended on was removed on 2026-09-01, by a change clearing rules that appeared to be unreachable. For sixteen days every button in the dashboard rendered with no padding, no corner radius, no pointer cursor and the browser's default font.

What's new for you

  • Buttons have their spacing, shape, cursor and font back, everywhere in the dashboard.

Under the hood

  • The existing stylesheet checks all stayed green through this, because each asked whether a class name was used somewhere rather than whether the rule it names still has a body. The new check asks for the declarations themselves, and separately refuses any selector list left dangling without one.

A form that expires now says what to do about it

A submission refused because its security token was missing or could not be verified used to say exactly that, which names no cause and offers no action.

What's new for you

  • The message now reads: "Your form could not be submitted because its security token was missing or could not be verified. Reload the page and try again."
  • It is deliberately cause-agnostic. There is more than one reason a token goes stale — a page left open a long time is the common one — and the remedy is the same for all of them.

Maintenance windows refuse writes instead of dropping the connection

An agent connected over MCP previously had no drain during a maintenance window: its calls kept succeeding until the revision went away, and then the connection dropped.

What's new for you

  • During a window, tools that write are refused with an error that says why, and read-only tools keep working.
  • The classification is per tool and explicit. A tool that has not been classified counts as writing, so a newly added one cannot write through an open window unnoticed — it is refused instead, which is both smaller and easier to notice.

A project restriction applies to every action, not just the page you loaded

Project scope was resolved once, when a page loaded. A restriction that changed while you were on that page did not take effect until you reloaded it.

What's new for you

  • Scope is resolved for each operation, so a project restriction applies from the moment it is set.

Other changes in the v0.11 series

No user-visible changes — internal reliability, security and tooling.

v0.10.93 through v0.11.01

No user-visible changes — internal reliability, security and tooling.

Administrative keys can no longer be limited to a project

A project limit scopes what a key can READ. It never constrained administrative actions, so a key a screen described as confined to one project could in fact manage the whole workspace. That combination is now refused everywhere it could be created or preserved.

What's new for you

  • Issuing an administrative key with a project is refused.
  • Editing an existing key to add a project is refused. This was the open gap: a key's tier cannot change on that path, but its project could, so a key issued without one could quietly acquire one and arrive at exactly the combination issuing refuses.
  • Rotating a key that already carries both is refused as a conflict, rather than copying the combination forward into a new key.
  • A consequence worth stating rather than leaving to be discovered: an issuer whose own key is restricted to a project can no longer issue an administrative key at all.

Under the hood

  • The three write paths share one rule rather than each carrying its own check, so they cannot disagree about what is allowed.

The dashboard says what it means

A pass over the screens where the wording asked you to already know the system.

What's new for you

  • Issuing a key is described in sentences rather than scope tokens, and the secret has a Copy button.
  • An agent's friendly name is the address other agents send to, and the form now says so instead of asking for a label with no stated purpose.
  • A newly created agent tells you it cannot be used yet, and links to the form that fixes it.
  • A key issued from a project page is operational only. The card promises the key reaches that project and nothing else, and that promise cannot be kept for administrative scopes, so the card can no longer offer them. The same combination is still reachable from the agent page, which makes no such promise and now carries a note explaining the limit.
  • A connection restricted to a project says which project, and a project's connection count links to the connections it counted.
  • A grant that cannot authenticate and cannot mint a token no longer renders as Live.
  • The "with access" figure on a project card no longer contradicts the access card beneath it.
  • The project page's header actions go where they say they go.

Bring your existing history with you

Sessions, decisions, backlog items, lessons and rules from an existing ledger can be exported and imported into a PostMQ workspace, keeping their original dates, statuses and links.

What's new for you

  • Export produces a SpecStepExport.v1 bundle. It is read-only, resumable, and refuses rather than writing a bundle smaller than the ledger it read.
  • Import runs in dependency order and offers a dry run first, so you see what would land before anything does.
  • Imported records keep the dates, statuses and cross-links they already had, rather than arriving as though they were created today.
  • Importing is gated on OWNING the workspace you are importing into. It was briefly reachable only by a platform operator, which is the tier for acting on other tenants' data and the wrong question to ask about your own history.

Purged content leaves nothing readable behind

Removing a message's content used to mean removing its payload. A subject line, labels and extensions are content too, and they were surviving the process meant to remove them.

What's new for you

  • A message whose content has been purged no longer returns its subject, labels or extensions on any read path.
  • The purge that acts on an adjudicated takedown covers the subject, labels and extensions as well as the payload. That purge ships disabled and is switched on deliberately per environment, so it is a capability an environment enables rather than something that happens on its own.
  • The record that a takedown happened survives it. What is destroyed is the content, not the decision or the notice.

Alerts arrive somewhere you can acknowledge them

Three families of alert were written to logs only. A log line cannot be acknowledged, so nobody could tell a handled alert from an unread one.

What's new for you

  • Those alerts now land in an inbox that records whether they have been acknowledged.
  • Enforcement alerts reach the person the alert is about, rather than the workspace owner.

The address for authorities is in the page itself

The contact addresses on the legal pages were being rewritten at the edge into a form only a browser running JavaScript could read. A person saw them; a reader without JavaScript, and anything machine-read, saw none — on the pages that carry the point of contact for authorities and the provider identification, where being directly reachable is the whole point.

What's new for you

  • Those addresses are now served as literal text on every page that carries them.

Under the hood

  • The generated pages fail to build rather than publish a page whose address has gone missing by any route, and a probe checks the served bytes, which is the only place this was ever visible.

Client setup instructions that actually work

A published setup step told a fresh user to run a command-line tool they had no way to obtain. It now points them at the routes that do work.

What's new for you

  • The setup instructions no longer assume a packaged CLI download that is not offered. They give the install routes that are actually available: an agent over MCP, the Claude Code plugin, building the CLI from source, or copying the files by hand.

Other changes in the v0.10 series

No user-visible changes — internal reliability, security and tooling.

Usage reporting speaks to every client it supports

The field that ties a usage report to a coding session was named for one client. The kit now supports four, so the field has a client-neutral name — and a report that arrives out of order can no longer shrink a count.

What's new for you

  • The usage report's session field is now client_session_id. The former claude_session_id is also accepted and echoed back unchanged, so nothing you have already built breaks.
  • A stale report that lands after a newer one is ignored rather than overwriting it, and the response tells you so.
  • Usage is measured in token counts, not dollars.

Under the hood

  • The MCP tool and the REST endpoint resolve the old and new field names through one shared path, so the two surfaces can never disagree about what a report means.

ZCode and Antigravity join the supported clients

The session-state kit and the usage reporter worked with Claude Code and Codex. They now install into two more clients — with one honest limit on the newest.

What's new for you

  • ZCode, Z.ai's GLM client, is supported for both the session-state kit and usage reporting. Because ZCode has no end-of-session event, usage is recorded per turn as you work.
  • Antigravity installs the kit and connects over MCP, and has its own step-by-step setup page.
  • Every install route — an agent over MCP, the Claude Code plugin, the offline CLI, or copying the files by hand — writes identical bytes.

Under the hood

  • On the version of Antigravity we tested, none of its editor hooks fire, so nothing there is captured automatically: the start-session and end-session skills do that work when you run them, and a session you never end records nothing. This limit is stated on the Antigravity setup page itself, not left for you to discover.

Build sessions record the pull requests they produce

A build session can now record its pull requests while it is still open, rather than only when it ends — so the record survives a session that never reaches its final step.

What's new for you

  • Record a build session's pull requests as they are opened; each one is resolved into its provider, number and repository for you.
  • An existing caller that sends only a URL at session close still gets that resolution, with no change on its side.
  • On the dashboard, a build session's pull requests now render as pull requests.

Under the hood

  • The new surfaces are record_build_session_prs (MCP) and PUT /v1/build-sessions/{id}/prs (REST). Sending both the new structured shape and the older flat list in one call is an error rather than letting one silently win.

See who reaches a project, and issue keys there

You can now ask who has access to a project — and the answer counts agents, not only people — and issue a scoped key without leaving the page.

What's new for you

  • A project page shows who reaches it: the people, and the agent credentials, including unscoped credentials that reach the whole workspace and therefore this project too.
  • Issue a key scoped to that project directly from the page, with the project already chosen.
  • Edit a saved credential's scopes and project, and the change takes effect immediately rather than only being saved.

Under the hood

  • Access is enforced per credential, not per person, so a page that listed only people would name the wrong half of the boundary. The workspace-wide figure is split by how a credential was minted, because an issued key is rotated on its agent while an OAuth connection is disconnected on the Connections screen.

Recover a webhook whose destination moved

A webhook whose delivery destination has moved can now be recovered, without loosening the rule that pins where it is allowed to send.

What's new for you

  • If a webhook's destination changes, it can be re-resolved and kept working, and the restriction on where it may deliver is preserved rather than weakened to make the recovery possible.

The Connections screen shows which agents are working now

Connections used to band everything into "seen in the last 24 hours" — true, and no help at all for telling whether an agent is alive right now. It can now say which agents are working.

What's new for you

  • Connections shows a tight, recent activity window, so you can tell an agent that is working this minute from one that was merely seen sometime today.
  • The window is honest for both ways an agent connects.

Under the hood

  • For an agent connected over OAuth, activity is now measured from the most recent access token it used, not only from when the connection was first authorized — so a continuously working OAuth agent is no longer shown as idle for up to 45 minutes.

A manager's view of your projects

The Projects screens gained an overview built for someone tracking several efforts at once: who is working on what, and what it costs in tokens.

What's new for you

  • The projects list shows a workspace rollup and, per project, its recent people, last activity, open and filed backlog, and token spend.
  • A project's own page shows summary tiles, a combined timeline of sessions and decisions, a contributor list naming both people and agents, its lessons and rules, and a banner for the one thing worth attention.

Under the hood

  • Token spend is counted in tokens, never dollars, and is never shown without the coverage figure that qualifies it. A zero is earned: a project with sessions but no reports reads "Not reported", while one with no sessions reads 0.

Leave cleanly after closing a workspace

Closing a workspace no longer locks its owner out before they can take their data with them. There is now a grace window for exactly that.

What's new for you

  • After you close a workspace, you can still sign in during a grace window — but only to export your data or to erase it yourself. Every other action is refused.
  • Once the window passes, the closed workspace is refused outright.

Under the hood

  • The window's deadline travels inside the session itself, so reaching a different page does not extend it.

Start a build session without naming a project

Starting a build session no longer requires you to name a project when there is only one it could mean.

What's new for you

  • start_build_session now treats the project as optional; when your credential already implies a single project, that project is used automatically.

Under the hood

  • The API reference and the quickstart were corrected to match, including a quickstart step that had pointed at a page that does not exist.

Other changes across the rest of the v0.09 series

No user-visible changes — internal reliability, security and tooling.

Report illegal content, and who to contact in the EU

Reporting something illegal used to mean posting JSON to an API. There is now a page a person can use, alongside the pages that say who operates PostMQ and where to reach us.

What's new for you

  • A form for reporting illegal or infringing content, with the fields the DSA asks a notice to carry, so you do not have to construct a request by hand.
  • A provider-identification page naming the operating company, its address, and how to contact it.
  • legal@postmq.com is the posted contact for Member State authorities, the Commission and the Board, and it accepts mail in English.
  • A public status view for a notice you have submitted.

Under the hood

  • Terms of Service and the Privacy Policy remain v0.1 drafts and carry a banner saying counsel has not reviewed them.
  • The pages name the addresses that work and say plainly which do not exist, rather than printing one that bounces.
  • Some published claims about these pages were wrong before this shipped, and were corrected with the pages themselves. A guard now fails the build if the documents and the addresses disagree.

v0.09.01 through v0.09.04

No user-visible changes — internal reliability, security and tooling.

Sign-up asks instead of assuming

Signing in with a work account used to fill in details PostMQ had not actually been told. It now asks, and says so when it cannot proceed.

What's new for you

  • Sign-up asks which country you are in rather than defaulting to one. That value is not decorative: it decides which regions the service is offered in and how a data request about you is handled, so inventing it was not acceptable.
  • The record of your sign-up stores which version of the terms you were shown when you accepted.
  • Signing in with a Microsoft account that has no mail address on file now explains the problem instead of failing with a bare error.
  • The consent screen shows the product's real name and links to the terms.

Under the hood

  • Two people from different Microsoft tenants can hold the same internal identifier. PostMQ records which tenant asserted your identity and refuses to treat the two as the same person.
  • Only Microsoft Entra ID single sign-on is enabled. Google and GitHub sign-in are scaffolded but not yet enabled.

v0.08.04 through v0.08.99

No user-visible changes — internal reliability, security and tooling.

The dashboard gets its edges finished

A run of small things that were each individually survivable and together made the dashboard feel unfinished.

What's new for you

  • Every list behaves the same way: consistent columns, sorting and paging across build sessions, decisions, projects and the rest.
  • Create forms collapse once there is something in the list, so a page you visit to read is not half taken up by a form.
  • Breadcrumbs on the two pages whose hierarchy is genuinely three levels deep.
  • The Candidates link carries how many are pending.
  • A backlog item shows the decisions related to it. The links were already in the data and were rendered nowhere.
  • Pull-request URLs are links rather than text.
  • The notice telling you your plan withheld older rows now looks like a notice. It had no stylesheet at all and read as body text.

Under the hood

  • Linking a URL that came from data is how stored cross-site scripting happens, which is why those links had been left as text. They are rendered through a check that the target is a real pull-request address.
  • Plan limits remain inert: every workspace is uncapped and there is no billing. The withheld-rows notice describes a limit that is not currently applied to anyone.

Follow a project through the dashboard

Opening a project told you about the project. It did not take you to its work.

What's new for you

  • A project page links into the build sessions, decisions, backlog, lessons and rules belonging to it, and those lists arrive already filtered to it.
  • The filter is in the address, so you can bookmark a project's backlog or send someone a link to exactly what you are looking at.
  • Page identities are copyable, so referring to a specific record does not mean transcribing an id.

The browser sign-in for agents can complete

Installing PostMQ into an agent through the browser could not finish. Our own content-security policy blocked the consent step's redirect.

What's new for you

  • The browser install flow completes: approve once in the dashboard and the agent is connected, with no secret pasted anywhere.

Under the hood

  • The failure was only visible in a real browser. The tests exercising this flow could not see a policy the browser enforces, so a real-browser check now covers the redirect.

Webhooks, end to end

Webhooks could be delivered but not managed, and the setting bounding how many go out at once was not connected to anything.

What's new for you

  • Create, inspect and manage webhooks from the dashboard, with the signing key shown once at creation.
  • max_concurrent_deliveries is now honoured. It previously had no enforcement point at all, so the value you set had no effect.
  • Delivery remains at-least-once: a receiver can see the same message twice and should key on the message id.

Under the hood

  • Records of exhausted deliveries are now bounded by database constraints rather than by the code that writes them, so a malformed one cannot be stored at all.

Revoking access says what it actually does

The dashboard told you a revoked credential stopped working immediately. It does not, and the sentence is read at the moment someone is containing a leak.

What's new for you

  • Revoking a credential now states the real bound: it stops being accepted within about 30 seconds across every replica, rather than instantly.
  • Revoking an AI account now also withdraws the connections approved for it. Previously the account was retired while its browser-approved grants still read as live.

Under the hood

  • The staleness of the check is measured against elapsed time rather than wall-clock time, so a clock adjustment cannot extend how long a revoked credential keeps working.

A refused data request says so

Some paths declined to act and told nobody. The declining was correct each time; the silence was not.

What's new for you

  • A deletion request that cannot complete now reports that it was blocked, instead of appearing to succeed and being retried forever.
  • A request for a copy of your data keeps working after a workspace is closed.

Under the hood

  • Robustness bought with silence is worse than a loud failure, because a loud failure gets fixed. Where declining was right, the fix was to say so rather than to act.

The contact form covers the whole request

What's new for you

  • A privacy request asks which right it concerns — a copy of your data, a correction, deletion, or taking it elsewhere — so it reaches the right place without a follow-up.
  • What the form stores about you, and for how long, is now named in the Privacy Policy's retention table. It was retained with no stated window before.

Form fields you can see the edges of

What's new for you

  • Input borders were 1.68:1 against their background, below the 3:1 minimum for non-text contrast. They are now above it, in both light and dark.

Under the hood

  • Automated accessibility checking covers part of a standard, not conformance with it. This particular failure is one such checks do catch, and it had been worked around in the application rather than fixed in the design tokens.

Limit a person to certain projects

A workspace member saw every project in it. The account owner can now limit someone to the projects they need, and that limit holds everywhere — in the dashboard, over the API, and for any agent credential they create.

What's new for you

  • On the People screen, choose whether someone sees every project or only the ones you pick. The column beside them names what they reach, so you can check it at a glance.
  • A new project is not granted to a limited person automatically. Add it when you want them in it.
  • A limited person's own agent credentials are bound to a project too — they cannot create one that reaches further than they do, and the issue form asks them which project it is for.
  • Connections they approved before you limited them are withdrawn if the new access no longer covers them.
  • A credential they had already created is not narrowed. The limit applies to what they create from then on, and to the connections they approved; a token they minted earlier keeps the reach it was issued with until you revoke it, which you can do from the AI account it belongs to.
  • Changing someone's access is recorded in the audit log, including which projects they hold afterwards and how many connections it withdrew.

Under the hood

  • A limit covers this workspace's project work — its build sessions, decisions, backlog, lessons and rules. It does not cover messages, AI accounts or webhooks: those belong to the workspace rather than to a project, so a limited person still sees all of them. The People screen says so where you make the choice.
  • The audit log stops being visible to a limited person entirely, on every surface. It records the whole workspace, and a version filtered down to one project would look complete while leaving things out.
  • Everyone is on "every project" until someone changes it, so nobody's access moved when this shipped.
  • Limiting someone is not a substitute for revoking a credential you did not mean them to have. The credential row does not carry who issued it, so limiting has nothing to select those on and cannot withdraw them. The audit log does record who issued each one, so you can find them there and revoke the ones you meant to.

v0.08.00 through v0.08.02

No user-visible changes — internal reliability, security and tooling.

Any Microsoft account can sign in

Signing in with Microsoft accepted only accounts in PostMQ's own directory, so a work account from any other organisation was turned away with a message about being added as an external user first. Any Microsoft work, school or personal account is now accepted.

What's new for you

  • Sign in or sign up with a Microsoft account from your own organisation.
  • Personal Microsoft accounts work too.

Under the hood

  • Google and GitHub sign-in are scaffolded but not yet enabled.

More than one person in a workspace

A workspace held exactly one human. It now holds a team: the account owner invites by email, the person accepts with their own PostMQ account, and they can be removed at any time.

What's new for you

  • Invite someone by email from the People screen. They need a PostMQ account on that address to accept — inviting does not create an account for them.
  • An invitation works once, only for someone signing in with the address it was sent to, and stops working after seven days.
  • A member sees the workspace's agents, messages and audit log and can act in it. Only the account owner can invite, remove, or change the workspace itself.
  • Removing someone ends their access on their next request, withdraws any invitation still outstanding to them, and disconnects the integrations they had approved.
  • Switch between workspaces you belong to from the dashboard.

Under the hood

  • The invitation link is shown once and is never stored, so it cannot be re-read later. If you lose it, revoke the invitation and send another.
  • An invitation admits only a human whose account email matches the address it was sent to. Note the limit of that check: PostMQ does not verify an email address at sign-up, so it proves the address was reachable by whoever registered it rather than that it belongs to them.

The session-state kit installs into Codex

What's new for you

  • Install the kit from Codex as well as Claude Code, from the same source.
  • The agent issues its own credential now, so the setup documentation no longer tells it to ask you for one.
  • A running-locally guide, because standing PostMQ up took seven secrets and a database and the list had never been written down.

Under the hood

  • A resumed Codex session was about to report its token usage as a smaller number than it had already recorded, which would have silently under-counted the session.

A support portal, and a way to reach us without an account

Getting help meant knowing an address. There is now one door at postmq.com/support, with the documentation first, because most questions are answered there before a person is needed.

What's new for you

  • Six routes covering the common reasons to get in touch, and a twelve-question FAQ that points at the page explaining each thing rather than restating it.
  • A contact form that does not require an account.
  • Security reports and content reports publish an address instead of a form — a researcher with a live finding should not have a form in the way.
  • If the form cannot verify your submission it says so and asks you to send it again, rather than accepting it and dropping it.

Agents connect over OAuth instead of a pasted credential

An MCP client can now ask for access and be approved on a consent screen, the way any other integration works. The credential it receives is an ordinary PostMQ credential, so everything that was already true of one — scopes, expiry, revocation — is true of this.

What's new for you

  • Connect a compatible MCP client by approving it, rather than issuing a credential and pasting it into a config file.
  • A consent screen names the agent, the client asking, and the scopes it is requesting.
  • Connections appear in the dashboard and can be withdrawn. Withdrawing one stops its tokens working rather than marking it withdrawn while it keeps running.
  • A client that presents no token is told where to get one, so a conformant client can discover it needs to connect at all.
  • An anonymous caller can no longer read the tool catalogue.

Under the hood

  • Clients can register themselves, either by publishing a document at their own identifier or through dynamic registration. Registrations that go unused are collected.
  • Consent is a grant, and the tokens it mints inherit what was consented to — including after a refresh.

A Pro tier, and free-tier limits you can actually reach

The pricing page now has four rungs, and the free tier's limits are set where a real workload meets them rather than far beyond any workload at all.

What's new for you

  • A Pro tier at $19 a month.
  • Developer, the free tier: 2 AI accounts, 1 project, 3,000 messages a month.
  • Team includes 100,000 messages a month, then $3 per 10,000.
  • Signed in, the pricing page marks the tier you already hold instead of presenting all four as choices.

Under the hood

  • Plan limits are inert: every workspace is uncapped, and there is no billing. The numbers say what a tier will include, not what is enforced today.
  • The included allowances were set against what a message measurably costs to serve, and against the heaviest real PostMQ workload that exists, rather than chosen to look generous.

Signing in works

Four separate defects stood between a person and a working session, and each of them reported success while failing. They are fixed.

What's new for you

  • The sign-in button completes the sign-in. A security header was blocking the redirect, so the button did nothing while the server recorded a successful sign-in.
  • A restart no longer signs everyone out or breaks forms mid-use.
  • "Sign in" from the marketing site takes an already-signed-in reader to their dashboard instead of asking them to sign in again.

Under the hood

  • Signing up through Microsoft recorded an acceptance of the terms that nobody had been shown, and wrote it into the audit chain. The acceptance is now the version you were actually shown, bound to the sign-up you completed, so a republication mid-sign-up cannot stamp a document you never saw. Terms and Privacy remain v0.1 drafts carrying a banner saying counsel has not reviewed them.

The site leads with handoffs, and the dashboard leads back

What's new for you

  • The home page opens on durable handoffs between agents — the half of the product nothing else does — with session state alongside it.
  • The dashboard links back to the site. It was a one-way door: the logo went nowhere useful and nothing on the app led home.
  • Body text no longer stops well short of the figure above it, on 19 pages rather than the one that was reported.

Every protocol call is rate-limited

Rate limiting recognised three kinds of call and let everything else through unmetered — which was 97 of the 100 MCP tools and every REST route without a category. All of it is now metered under a protocol bucket.

What's new for you

  • Session-state tool calls and uncategorised REST routes now count against a limit and return the standard rate-limit headers.
  • The limit is per credential, so one busy agent cannot consume the capacity of everything else.

Under the hood

  • This is an availability control first: one credential calling at a few hundred requests a minute could hold most of a database's capacity, and every other tenant felt it.

Release notes, and a version number

PostMQ now has a version and a public record of what shipped. The version in the app footer links here; clicking it is how you find out what changed.

What's new for you

  • A version number on every build, shown in the dashboard footer.
  • A release-notes page covering the whole history, not just recent work.
  • Entries say what changed for you; work with no user-visible effect is collapsed to one line rather than padded out.

Under the hood

  • The version is derived from the release history rather than maintained by hand, so it cannot drift from what actually shipped.

Sign-in and password-reset links point at the address you use

The dashboard was building its links from the wrong origin, so signing in could fail and the link in a password-reset email pointed somewhere you could not reach. Both now use the address you actually visit.

What's new for you

  • Signing in to the dashboard completes rather than failing part-way.
  • Password-reset links resolve to the dashboard you use.

A stale form no longer returns a server error

Leaving a dashboard form open long enough for its security token to expire produced a server error. It now returns a clear rejection with a body explaining what happened, so the page can tell you to reload rather than showing a failure.

What's new for you

  • An expired form returns a readable rejection instead of a server error.

The assessment template replaces test_run_result, and is no longer reply-only

The template that reported a test run is now assessment, and it covers any verdict an agent reaches — a design review, a launch-readiness call — not just a test result. Nothing in its required fields was ever test-specific, so the old name described one use and blocked the rest.

What's new for you

  • Send an assessment where you previously sent a test_run_result.
  • assessment_kind is new and required, and says what kind of verdict this is.
  • directive_message_id is removed. Use the envelope's own in_reply_to and thread_root_id, which already travel to the receiver and which the broker can actually check — a payload copy could not be verified and made the template a reply and only a reply.
  • The retired name is permanently reserved, so it can never be reused for a different shape.

v0.06.90 through v0.06.98

No user-visible changes — internal reliability, security and tooling.

v0.06.87 through v0.06.88

No user-visible changes — internal reliability, security and tooling.

The server offers its own installer

One kit — the session-start and session-end skills, a session hook, the settings snippets and the usage reporter — reachable four ways from a single source: as MCP resources any client can read, from the command line, from the website, and as a plugin marketplace. Ask your agent to set PostMQ up and it can fetch the kit itself.

What's new for you

  • Ask your agent to set PostMQ up and it can fetch the kit over MCP.
  • pmq kit list and pmq kit install work offline, with no credential.
  • The installer asks before writing, and skips a file whose content you have changed.
  • Every surface writes identical bytes, derived from one manifest.

Reference documentation derived from the running API

Quickstart, authentication, the MCP and REST guides, an error reference, rate limits, runnable samples and the installer kit — with the tool catalogue, the error reference and the navigation all derived from the code rather than retyped beside it.

What's new for you

  • Quickstart, auth, MCP and REST guides, plus error and rate-limit references.
  • The 86-tool catalogue and its argument tables come from the manifest.
  • An OpenAPI document at a stable path, for generating a client.
  • Runnable samples in shell, Python, TypeScript and C#.

Under the hood

  • There is no client SDK yet; the samples page says so rather than implying one.

Repeat-offender accounting

Substantiated findings accumulate against a salted, per-workspace identifier rather than a stored name. A daily pass applies enforcement once a published threshold is crossed.

What's new for you

  • Findings accumulate against a hashed identifier, not a stored name.
  • A published numeric threshold drives enforcement.
  • Per-workspace salt shredding makes the linkage unrecoverable on erasure.

A stopped background job no longer looks healthy

Background passes now report liveness even when they find nothing to do, so a job that has silently stopped stops measuring the same as one running clean. It matters most for the jobs that destroy data.

What's new for you

  • An idle pass says it is alive instead of saying nothing.
  • The first pass is never withheld, so a job that never started is visible immediately.

Signing in stops waiting on a cold start

The dashboard keeps a warm replica instead of scaling to zero, removing the cold start the first sign-in of the day used to pay for.

What's new for you

  • Signing in is fast on the first attempt of the day.

Revoking an agent anonymizes its payloads

Revoking an AI account schedules the payloads of its finished messages for anonymization, and a background pass now carries that schedule out rather than only recording it. The window is capped at the retention horizon, so the platform never reports a date it would not honour.

What's new for you

  • Revocation actually anonymizes the agent's message payloads.
  • The window cannot be set beyond the retention horizon.

Under the hood

  • This pass ships disabled and is switched on per environment. The anonymization is irreversible.

postmq.com, where every sentence cites its evidence

A marketing and documentation site under a strict content-security policy, where every page declares the verified claims it rests on and the build fails on anything we have decided not to say.

What's new for you

  • Product pages for messaging, session state, rules, lessons, backlog, decision log and usage.
  • Pricing, security, enterprise and comparison pages, each citing its sources.
  • Every claim is registered with a verdict and evidence, checked at build time.
  • The numbers on the page are generated rather than typed.

Push delivery over signed webhooks

Register an endpoint and PostMQ posts each matching message to it, signed, from a transactional outbox: the outbox row commits with the message itself, and a separate dispatcher is the only thing that ever calls out. Nothing is delivered for a transaction that rolled back.

What's new for you

  • Signed delivery with a signing key you can rotate.
  • Nothing is delivered for a transaction that rolled back.
  • Bounded retry, with an alert when a target stays down.
  • List your webhooks and their recent deliveries, and see dead ones flagged.
  • Create, update, delete and rotate under an idempotency key.

Close a workspace and mean it

An owner can close the whole workspace in one call: it is stamped closed and frozen in one transaction with its audit-chain row, then each AI account is retired, its credentials revoked and its payloads scheduled for anonymization.

What's new for you

  • One call closes the workspace and retires every agent identity in it.
  • The closure is on the tamper-evident chain.
  • An agent's own credential cannot close the workspace it lives in — human session and second factor only.

Counter-notice and put-back

A counter-notification endpoint records the statement, a recorded court action blocks restoration while proceedings are live, and a scheduler restores content once the window closes.

What's new for you

  • File a counter-notification through a public endpoint.
  • A recorded court action blocks restoration until the matter resolves.
  • Put-back is scheduled and executed rather than left for someone to remember.
  • A counter-notice against a copyright claim cannot restore content removed for a different reason.

Read your own audit trail

The tamper-evident chain gets a read surface: a REST endpoint, an MCP tool built for parity with it, and a dashboard viewer with filters and a chain-integrity view.

What's new for you

  • Browse your workspace audit log in the dashboard.
  • The same view over REST and as an MCP tool.
  • Filter by time, event type, message or actor.
  • A chain-integrity view showing whether the links verify.
  • Reading it needs its own scope, so an agent only gets it deliberately.

An opt-in public record of your audit chain

A workspace owner can opt in to a weekly signed publication of its audit-chain head, so a third party can check the record has not been rewritten. The signature is performed by the key vault, so the private key never reaches the application.

What's new for you

  • Opt in from the dashboard, after an explicit disclosure you acknowledge.
  • Public verification keys are readable from a well-known endpoint.
  • Opting out does not withdraw a week already published, and the disclosure says so.

Under the hood

  • Available and opt-in — not operating. Nothing has been published yet, and a published week would carry the integrity record and no message content.

A vendor security questionnaire answered from the code

Sixty-one questions answered from the source rather than from a template: every yes cites a mechanism or a test, and every no is said plainly rather than buried.

What's new for you

  • A reviewer can read the answers without asking for a call.
  • Every yes points at the mechanism or test behind it.
  • A published contact for reporting a vulnerability.

The customer-facing legal set, published

Terms of Service and a Privacy Policy drafted against the mechanisms this platform actually has, and linked from the signup form that asks you to accept them.

What's new for you

  • Terms and Privacy are published and linked from signup and both footers.
  • Both are generated from a single source, so the published page and the repository copy cannot drift.
  • A privacy contact address that accepts mail.

Under the hood

  • Both documents are labelled version 0.1 drafts and carry a banner saying counsel has not reviewed them. They are drafts, and they say so.

Notice and action, from intake to statement of reasons

Anyone can file an illegal-content notice against a message. A reviewer decides it in a queue, and an accepted takedown disables access across every delivery path — not just the one the notice arrived through — with a preservation hold and a statement of reasons recorded from the same transaction.

What's new for you

  • A public intake endpoint, and a status check for whoever filed.
  • An accepted takedown stops delivery on all three paths, not just one.
  • A decided notice can be reclassified without closing the counter-notice route.
  • Decision notifications and the statement of reasons are filed from a durable outbox.

Requests are parsed strictly, and errors say less

Error bodies are structurally incapable of carrying unescaped caller input, externally-facing URLs come from configuration rather than a request header, and caller-facing errors name the operation instead of an internal document section.

What's new for you

  • Error responses cannot echo caller text back into the body.
  • A spoofed host header no longer chooses a URL we print back.
  • Error messages read as product language rather than internal references.

v0.06.01 through v0.06.18

No user-visible changes — internal reliability, security and tooling.

Access, correct, export and erase your own data

Four calls on your own record: read it, correct it, export it, delete it. Erasure freezes the workspace and retires its AI accounts, and the deletion itself is recorded on the audit chain.

What's new for you

  • Read everything held about you in one call.
  • Correct your own details, behind a second-factor check.
  • Export a portable copy.
  • Delete your account; if you are the sole owner, the workspace goes with it.
  • The deletion appends its own record to the tamper-evident chain.

Authentication without a database round trip per call

Verified credentials are cached in process with a revocation ring that invalidates across replicas, so the hot path stops re-verifying from storage on every call while a revoke still takes effect promptly.

What's new for you

  • Lower latency on authenticated calls.
  • A revoked credential stops working promptly, across replicas.

The dashboard becomes the product

A grouped information architecture, a shared design system, a live workspace overview, and empty states that name the tool that fills them rather than saying nothing.

What's new for you

  • Navigation grouped by what you are doing, not by which endpoint it calls.
  • An overview that says what the workspace is actually doing.
  • Empty states that tell you which tool fills them.
  • The credential reveal leads with a paste-ready client configuration.

Under the hood

  • Static assets are fingerprinted, so a deploy can never pair new markup with stale styles.

Adjudicated content is destroyed when the matter is final

Once a takedown is final — appeal window closed, no live hold, no open court action — a sweep destroys the payload bytes while keeping the envelope row, the notice, the hold and the audit chain intact. The purge destroys content, not the record that it happened.

What's new for you

  • Content dies when the matter is final, rather than when the decision lands.
  • The record of the takedown survives the purge of its content.
  • An alarm fires if the purge is off while adjudicated content is being retained.

Under the hood

  • This sweep ships disabled and is switched on per environment, deliberately: the destruction has no undo, so enabling it is a decision someone makes rather than a default they inherit.

Plans that bind, and a page that shows where you stand

Plan allowances come from one source of limits typed as unlimited, soft or hard. A hard cap refuses with its own error; a soft one records the crossing and lets the work through.

What's new for you

  • See your plan, its allowances and your current usage in one place.
  • A refusal returns a specific plan-limit error rather than a generic one.
  • Overage allowances record the crossing instead of blocking work.

Under the hood

  • Enforcement is inert today: every workspace is on the uncapped developer-preview plan, so nothing is currently capped, and there is no billing.

AI accounts and their credentials, end to end

Create an AI account per agent, issue it scoped credentials, rotate them with an overlap window, and revoke either the credential or the whole account.

What's new for you

  • One identity per agent, with credentials you can rotate independently.
  • Rotation gives an overlap window instead of an immediate cutover.
  • Revoking an account retires its credentials in the same operation.
  • A renamed account keeps resolving under its old name for a grace period, so in-flight sends still land.
  • A revoked identity cannot have a live credential slipped in behind it.

Append-only becomes a database permission

The application identity is denied update and delete across the whole audit-chain surface, so append-only stops being a convention the code observes and becomes a limit the code cannot exceed.

What's new for you

  • The data plane cannot edit or delete an audit row, by permission rather than by discipline.
  • Appends still go through the one procedure that owns the chain.

Preservation holds that outrank retention

A preservation hold on a message stops every retention and anonymization path from touching it, enforced at the database rather than remembered by each sweep independently.

What's new for you

  • A hold blocks retention purges and anonymization while it is live.
  • Records under hold get an extended retention window.
  • A hold is released deliberately, through the same row that applied it.

A tamper-evident record of everything that happened

Every workspace-significant event appends a row to a per-workspace hash chain, written inside the same transaction as the change it records. A daily verifier walks each chain end to end, and a broken link freezes the workspace and raises an integrity alert.

What's new for you

  • Message accepted, leased, acknowledged, returned, dead-lettered and expired are all on the chain.
  • Account, credential, policy, authentication and override events too.
  • Each row chains the previous row's hash, so a removed or edited row is detectable.
  • A daily verifier checks every chain and raises an alert on a break.
  • The chain row commits with the change it records, or neither does.

Accessibility checked on the critical path

The signup, account-management and credential-reveal flows are checked against the WCAG 2.2 AA rule set in a real browser, against the rendered page rather than the source.

What's new for you

  • The critical path is checked for accessibility on every change.

Under the hood

  • Automated checking covers part of the standard, not all of it — so this is a floor we hold, not a claim of conformance.

Extend a lease on long work

A consumer still working on a message extends its lease rather than losing it to the expiry sweep.

What's new for you

  • Keep a message claimed while a long task finishes.
  • Caps stop a single consumer holding a message forever.
  • Available from both REST and MCP clients.

v0.05.01 through v0.05.22

No user-visible changes — internal reliability, security and tooling.

One token source for the brand, in light and dark

A semantic token layer generated from a single source into the brand kit, a standalone stylesheet and the dashboard, with contrast pairs computed in the build rather than judged by eye.

What's new for you

  • Light and dark are the same tokens rather than two hand-kept palettes.
  • Contrast ratios are computed as part of the build.

A session-end hook that reports its own token use

Drop in one hook and a session submits its token counts when it closes, so consumption lands next to the decisions that session recorded without anyone typing a number.

What's new for you

  • Automatic usage reporting at session close.
  • Token counts, not dollars.
  • Ships as part of the installer kit.

Transactional email that actually leaves the building

A real transactional email channel behind the notification seams, with password-reset delivery moved onto it and the sending domain verified. Delivery now reports whether it happened rather than assuming.

What's new for you

  • Password-reset emails are really sent, from a verified sending domain.
  • The delivery seam reports success or failure instead of assuming success.

An account-security page that can un-brick you

Disable and re-enrol your second factor, see and revoke active sessions, change your password while signed in, and keep recovery codes for a lost authenticator.

What's new for you

  • See every active session and end the ones you do not recognise.
  • Change your password without signing out first.
  • Recovery codes for a lost authenticator.
  • Enabling the second factor invalidates sessions created before it.

The dashboard stops signing you out mid-task

The dashboard rotates its refresh token in the background, so a working session outlives the short life of the signed session cookie without weakening it.

What's new for you

  • Stay signed in through a long working session.
  • The short-lived session cookie is unchanged; only the refresh is automatic.

Sign in with your organization directory

Microsoft Entra ID single sign-on, with proof key exchange and nonce checks, wired to both the sign-in and sign-up paths.

What's new for you

  • Sign in and sign up with Microsoft Entra ID.
  • A first sign-in creates or links an account under the same signup caps.
  • A second-factor challenge is honoured on the single sign-on path too.

Under the hood

  • Google and GitHub sign-in are scaffolded but not yet enabled.

Safe retries on every write

Send an idempotency key with any write and a repeat of the same request returns the original result instead of doing the work twice. The same key with a different body is refused as a conflict.

What's new for you

  • Retry a send, an acknowledgement or a webhook change without duplicating it.
  • A reused key with a changed body returns a conflict rather than silently overwriting.
  • Keys are scoped per calling principal, so two agents cannot collide.
  • One key cannot be stretched across two different operations.

Accepting terms records which terms

The acceptance recorded at signup is validated against a registry of published document versions, so the stored version always names a document that exists.

What's new for you

  • The version you accepted names a real published document.
  • Enforced on every path that records an acceptance.

Passwords are screened against known breaches

Both paths that accept a password — signup and reset — check it against a corpus of previously breached passwords and refuse a known one.

What's new for you

  • A breached password is refused at signup and at reset.

Rate limits that hold across replicas

A token-bucket limiter fronts send, receive, validate and lease operations, with per-credential and per-workspace buckets. Replicas share their state, so scaling out does not multiply anyone's allowance.

What's new for you

  • Rate-limit headers on every response, so a client can back off precisely.
  • Separate buckets for send, receive and validate.
  • Limits hold across replicas rather than per instance.
  • A restarted replica resumes from the recorded level instead of a full bucket.
  • The MCP surface is limited on the same buckets as REST.

Send a message that survives the session

Post a message to a named AI account in your workspace and it is validated, resolved, anchored and persisted in one transaction alongside its audit row and any webhook enqueue. Nothing is half-written: either the whole hand-off exists or none of it does.

What's new for you

  • One call durably hands work to another agent.
  • The envelope, its audit row and its webhook enqueue commit together.
  • Delivery is at-least-once.
  • The record says which surface a message arrived on, REST or MCP.

Brute force gets slower, not luckier

Throttles on every authentication surface, per source address and per account, with a lockout on repeated second-factor failures and constant-time behaviour on password reset.

What's new for you

  • Sign-in, signup, reset and second-factor verification are all throttled.
  • Repeated failures back off per account, not only per address.
  • Password reset answers the same way whether or not the address exists.
  • The bearer surface is throttled on both REST and MCP.

v0.04.01 through v0.04.31

No user-visible changes — internal reliability, security and tooling.

One pagination contract across every list

All ten list endpoints page the same way, over an opaque cursor bound to the query it was issued for — so a cursor cannot be replayed against different filters and quietly return the wrong page.

What's new for you

  • The same cursor contract on every list endpoint, with no exceptions.
  • A cursor is bound to its query and refused if the query changes.
  • Frozen before any outside client depends on it.

Sanctions screening on the send path

Workspace subjects are screened against OFAC's SDN list, refreshed daily, using name, phonetic and country matching. A hit holds the send and opens a review for a person to decide, and the gate fails closed.

What's new for you

  • Screening runs on the send path rather than after the fact.
  • A hit opens a review instead of silently allowing or denying.
  • The list refreshes daily from the published source.

A hosted MCP server your agent connects to directly

The whole product is exposed as MCP tools over two transports — stdio for a local agent, Streamable HTTP for a hosted one — running the same service graph as the REST API, so a tool call and a REST call do the same thing rather than merely resembling each other.

What's new for you

  • Connect an MCP client to the hosted server, or run it locally over stdio.
  • 86 tools covering messaging, discovery, policies, webhooks, audit and session state.
  • MCP calls carry the same idempotency and rate-limit behaviour as REST.
  • Resources for templates, active policies and recipient attention.

Under the hood

  • Parity between the two surfaces is pinned by a manifest and checked on every change, so the two cannot drift into doing subtly different things.

Publish a policy your agents must accept

A workspace owner publishes a versioned policy body; agents read the active policies and acknowledge them. Until they have, sends are refused with a specific error rather than a generic one.

What's new for you

  • Publish workspace policy your agents must accept before they can send.
  • Agents read active policies over REST or MCP and acknowledge them.
  • An unacknowledged policy blocks sends with its own error code.
  • The dry-run validate call tells you it would block, before you send.
  • Publishing is human-only and requires a second factor.

Acknowledge, retry or dead-letter

Acknowledging completes a message; negatively acknowledging returns it for redelivery, or sends it to the dead-letter state once it passes the retry ceiling.

What's new for you

  • Both operations check the lease and the caller in the same statement that changes the row.
  • A repeat acknowledgement on the same lease succeeds rather than returning a conflict.
  • A negative acknowledgement can carry a redelivery delay, or terminate the message.
  • Past the retry ceiling a message is dead-lettered, not lost.

A workspace freezes when its record is in doubt

If the daily audit-chain verifier finds a break, the workspace is frozen and an integrity alert is raised. A frozen workspace refuses new AI accounts and renames.

What's new for you

  • A detected chain break stops writes instead of continuing quietly.
  • The refusal is enforced under a lock, so a concurrent create cannot slip past it.

Identifiers are exact, everywhere

Every identifier on every read and write boundary is checked for its canonical form before it is used, so a near-miss spelling of an id is refused rather than resolved to a real row.

What's new for you

  • An identifier that is not in canonical form is refused.
  • Applied uniformly across messaging, accounts and session state.
  • REST and MCP return the same refusal for the same input.

Model-assisted lesson proposals, off by default

An optional pass over a project's resolved backlog can propose lessons into a triage queue, and enrich a rule's trigger surface. Proposals never become rules on their own.

What's new for you

  • Proposals land in a queue; a person promotes, rejects or supersedes each one.
  • That decision is terminal, and candidates cannot be hand-typed.
  • Bring your own provider key.

Under the hood

  • This ships switched off. Both passes default to disabled, no provider client is registered unless you configure a key, and there is a separate kill switch. With nothing configured the calls answer deferred and make no outbound request at all.

v0.03.01 through v0.03.07

No user-visible changes — internal reliability, security and tooling.

Every response identifies itself

Server-stamped headers on every response carry the request identity a client needs to correlate a call with what it later sees in the audit log.

What's new for you

  • A request identifier on every response.
  • The same behaviour across REST and the MCP transport.

Bring the history you already keep in markdown

Point the importer at a decision log, backlog or session history you already keep as markdown. It parses, previews as a dry run, then commits — and each entry is deduplicated on a hash of its own source block, so re-running an import is safe.

What's new for you

  • Preview an import as a dry run before anything is written.
  • Re-running is safe: unchanged entries are skipped rather than duplicated.
  • Every run keeps parsed, committed, skipped and errored counts.
  • Upload through the dashboard or post through the API.

Flow metrics over the backlog

Cumulative flow, throughput, aging work in progress and a cycle-time scatter, drawn from the backlog as it stands today.

What's new for you

  • Four flow charts in the dashboard, with nothing to configure.
  • Read straight from the backlog rows you already have.

Under the hood

  • There is no transition history behind these charts, so aging is measured from creation and dismissed items are excluded. The page says so, because a metric that hides its own basis is worse than none.

Rules retrieved by what you are about to do

Instead of a conventions file nobody reads, an agent asks with the change it is about to make and gets back only the rules whose every populated trigger dimension matches — file globs, operations, code patterns, languages, project attributes.

What's new for you

  • Ask with your change; get back only the rules that apply to it.
  • Triggers match across file, operation, pattern, language and project.
  • Rules are hand-authored, or derived from a lesson that reached enforced.
  • Replay the exact retrieval in the dashboard: what was returned, what was a candidate, what was suppressed.
  • Retiring a rule archives it rather than erasing it.

Browser clients can call the API

Cross-origin policy on the API, split into a public surface and a credentialed one, so a browser can reach the endpoints intended for it and no others.

What's new for you

  • Call the public endpoints from a browser.
  • Credentialed origins are handled separately from public ones.

Lessons with a forward-only lifecycle

Recurring pain becomes a lesson that moves observed, then documented, then enforced — and never backwards. A lesson cannot reach enforced until its prevention mechanism is written down, and that sentence is what a rule gets derived from.

What's new for you

  • File a lesson and append observations as it recurs.
  • Status only moves forward, held by the database rather than by convention.
  • Reaching enforced requires naming the prevention.

Token counts per session and per project

A session reports its own consumption in five classes plus turn counts, keyed so a retry overwrites rather than double-counts, and rolled up by project, day, week and month.

What's new for you

  • Per-session and per-project totals.
  • Idempotent by transcript, so a retried report does not double-count.
  • Rollups by day, week and month.

Under the hood

  • Token counts, not dollars. The figures are self-reported by the client, and the page says so.

A backlog agents file into and a team can read

Deferred work becomes a durable row with a state, a priority, an owner and a staleness clock, rendered as a board. Resolving requires closing notes or a commit; dismissing requires a reason; and a terminal state is absorbing, so an item cannot quietly reopen.

What's new for you

  • Agents file items; people triage, assign, reprioritize and close them.
  • A board in the dashboard over the same rows the agents write.
  • Closing an item requires saying how it was closed.
  • A staleness clock surfaces items nobody has touched.

An append-only decision log

One entry per material decision, linked to the session that produced it. The database rejects every delete and every edit except the two source links, so a correction is a new entry pointing at the one it supersedes rather than a rewrite of history.

What's new for you

  • Append a decision from an agent, read it as a person.
  • Corrections supersede; they never overwrite.
  • Query by author, by period, or by searching the text.
  • Entries link themselves to the session that produced them.

Sessions that resume instead of restarting

A build session is the unit of work an agent opens and closes. Starting one for the same project, machine, branch and actor returns the session already open rather than forking a second one.

What's new for you

  • Start is idempotent: the same context resumes rather than forks.
  • A rolling current-state note tells the next session where things stand.
  • Link a session continued on another machine.
  • Close with a history entry naming the pull requests and commits it produced.

Projects, the scope everything hangs from

Every piece of session state is scoped to a project inside your workspace, so two codebases' ledgers stay apart. A default project is created on first use without racing.

What's new for you

  • A default project exists before you need one.
  • Create, rename, archive and unarchive projects.
  • Available as MCP tools, REST routes and dashboard pages.

v0.02.01 through v0.02.22

No user-visible changes — internal reliability, security and tooling.

Claim work under a lease

A consumer asks for pending work and receives a batch under a time-boxed lease, claimed atomically so two agents never hold the same message. If the lease expires before the work is acknowledged, the message returns to pending and is delivered again.

What's new for you

  • Claim a batch in one call, with an optional long poll instead of busy-waiting.
  • A lease stops two agents working the same message.
  • A crashed consumer's work returns to the queue on its own.
  • Dequeue order is priority, then the time a message was accepted.

Read your messages without claiming them

A workspace owner can list and read messages over REST, separately from the consumer dequeue path, so a person or a tool can inspect traffic without taking it away from an agent.

What's new for you

  • List messages and fetch one by id.
  • Reading claims nothing and leases nothing.

A dashboard for the workspace

A web dashboard where a person signs up, signs in, enrols a second factor, creates AI accounts, issues and reveals credentials, and browses what their agents have been sending.

What's new for you

  • Sign up, sign in, reset a password and enrol an authenticator.
  • Create AI accounts and issue credentials without touching the API.
  • The credential secret is revealed once, in the browser.
  • Browse sent and received messages with their current state.

A command-line client

The pmq binary sends, claims, acknowledges and negatively-acknowledges messages from a shell, so the message plane is reachable from a script without writing a client.

What's new for you

  • pmq send, pmq pending, pmq ack, pmq nack.
  • Configuration by flag or environment variable.
  • JSON output for scripting, with meaningful exit codes.

v0.01.01 through v0.01.39

No user-visible changes — internal reliability, security and tooling.

Human sign-in, and sessions that resist replay

Sign in to the dashboard with an email address and password, hashed with Argon2id. Sessions are held by a signed cookie and refreshed by tokens that rotate on every use — if an old refresh token is ever replayed, the whole family is revoked rather than the replay being honoured.

What's new for you

  • Email and password sign-in, with an authenticator-app second factor.
  • Refresh tokens rotate on use; a replayed token revokes the family it belongs to.
  • Sensitive actions require a fresh second-factor assertion, not just a live session.
  • Sign out everywhere in one call.
  • Password reset by emailed token.

Discover who you can send to

A directory call lists the AI accounts in your workspace that an agent may address, so a sender does not have to be told recipient names out of band.

What's new for you

  • List addressable recipients over REST or MCP.
  • Descriptions come from the account record rather than a hand-kept list.

Check a message before you send it

A dry-run call runs the same validation, recipient resolution and policy gate as a real send, and reports what would happen without writing anything.

What's new for you

  • Validate a payload against its template without sending it.
  • See recipient-resolution and policy failures in advance.
  • It runs the same code path as send, so the answer matches.

Built-in templates, checked at send

Messages carry a template name and version, and the payload is checked against that template's schema when it is sent — so a malformed payload is refused at the boundary rather than surprising the agent that receives it.

What's new for you

  • A malformed payload is refused at send, not at the consumer.
  • Templates are versioned and readable over REST and MCP.
  • Three templates ship: a directive, a freeform note, and an assessment.

Expiry and retention run on their own

Two background passes expire messages past their time-to-live and anonymize payloads once the retention window closes.

What's new for you

  • Messages past their expiry stop being delivered.
  • Payloads are anonymized once the retention window passes.
  • Both run continuously rather than on request.

One canonical byte form for every payload

Payloads and audit rows are serialized through RFC 8785 JSON Canonicalization, so the same content always produces the same bytes. That is what makes an idempotency fingerprint and an audit hash something you can reproduce yourself.

What's new for you

  • Payload bytes are canonical, so a hash you compute matches the one we store.

Under the hood

  • The reference implementation is vendored and compiled in rather than re-implemented, so there is no second opinion about what canonical means.

Scoped credentials, issued per agent

Agents authenticate with a bearer credential issued to an AI account in your workspace. The secret is shown once at issue and stored only as a peppered digest, so it cannot be reproduced afterwards — including by us.

What's new for you

  • Issue a credential per agent rather than per person.
  • The plaintext secret is returned once and never again.
  • Every credential carries an explicit scope set.

v0.00.01 through v0.00.35

No user-visible changes — internal reliability, security and tooling.

Connection lost — reconnecting…

Couldn't reconnect. Reload the page.

An unexpected error has occurred. Reload