Changelog
Platform updates and new features
Machine-readable: /updates.txt
August 22, 2026 — testnet signer balances are no longer priced in dollars
- No fiat figure on testnet — suspension and deletion emails for a KMS signer priced the address's balance using a live ETH/USD feed even on
base-sepolia, so 0.0005 of free faucet ETH was rendered as $0.94 inside a warning that the funds would become permanently inaccessible. Testnet balances now render as 0.000500 ETH (base-sepolia testnet — no monetary value) and the oracle is not consulted at all.
- The deletion warning still stands — the key is still destroyed and the address still becomes permanently unusable, so that half of the notice is unchanged; only the claim that something of value is lost is dropped. Mainnet emails are byte-identical.
August 18, 2026 — apex custom domains: one nameserver change, Run402 does the rest
- Run402-hosted DNS zones — connecting an apex domain (
example.com) no longer requires moving your DNS to your own Cloudflare account. Opt in with desired.authority: "hosted_dns_zone" and Run402 hosts the domain's zone: your only step is pointing the registrar's nameservers at the assigned pair; web serving, ownership verification, TLS, and in-zone records are applied automatically once delegation is observed.
- Mail-safe by default — existing MX/TXT records are imported into the hosted zone verbatim before the nameserver change is recommended, and disclosed on the domain's
hosted_zone.imported_records.
- Disclosed, reversible custody — the domain aggregate reports
dns_hosting: "run402_hosted" with the zone state and assigned nameservers; disconnecting tears the zone down with an explicit warning.
- Canonical next_actions[] — ProjectDomain responses now use the platform-wide
next_actions[] vocabulary (first entry = recommended); the singular next_action and alternate_actions remain as deprecated aliases until published clients migrate.
- One custom-domain surface — the legacy standalone
/domains/v1 routes are retired (a traffic scan showed zero real callers); everything lives on /projects/v1/:project_id/domains/:domain, and a web-enabled connect registers serving in the same call under both authority modes.
- Zero PUT routes — the password route moved to
POST and the last PUT was unmounted (also dropped from the CORS allow-list). The verb allowlist is empty, so “no PUT” is now enforced by CI rather than by review.
- PUT aliases removed — the transitional
PUT forms for the domain ensure and wallet label no longer route; POST is the only form, and the verb allowlist is down to one pending entry.
- POST-canonical verbs, enforced — the domain ensure and wallet label move from PUT to POST, and a CI gate now fails any PUT route outside an explicit justified allowlist.
- Keys-only domain management — a project's own admin-capable credential can manage that project's domains, no wallet or session needed.
August 10, 2026 — uploads stop double-counting against your storage quota
- Your storage quota got its other half back — every upload holds a temporary reservation against your quota while it’s in flight, and the commit path was never letting go: each deploy’s full payload kept counting forever, on top of the real deduplicated content. Roughly a 1:1 shadow that quietly halved every organization’s usable storage. Commits now release the reservation the moment they land, and a cleanup reconciled 6.23 GiB of phantom reservations that had accumulated since April. Billing was never wrong — only the headroom number was lying, and it now tells the truth.
August 9, 2026 — a 401 names every credential it would have accepted
- “Sign in” errors now list every way in, not just the first one we checked — a route that accepts either a wallet signature or a logged-in session answered an unauthenticated request with
Missing SIGN-IN-WITH-X header, which reads as “a human must sign this with a wallet.” One agent read exactly that, decided the job belonged to its owner, and stopped — while holding a session the route would have taken. The error now names each accepted credential and how to get it.
- You can finally rotate project credentials from the CLI and SDK — the endpoints existed and were documented, but nothing shipped that could call them.
run402 credentials issue, list, status, rotate, revoke and token are now real commands, next to the existing local key cache under credentials project-keys.
run402 credentials status tells you whether you’re still on the old key — it needs no special permission, so a project can check its own posture. It lists what retirement is waiting on rather than a date, because there isn’t one to plan against.
August 8, 2026 — notifications name their subject
- Your alerts say which project they’re about — a project-scoped notification used to lead with an opaque
prj_1783064951883_0126. It now names the organization, the project, and the host it serves on, resolved fresh at delivery so a rename can never send a stale name.
- Telegram messages link straight to the project — the console deep-link was dropped whenever the event didn’t happen to carry an organization id, which was most of them. It’s now there whenever we can resolve the owner.
- The part of the message you needed is no longer the part that got cut — payload fields were ordered by how they happened to be stored and each value was capped at 120 characters inside a 4096-character message, which was enough to truncate an error notification at
"db is not …. Fields now render in a deliberate order with a budget scaled to the message, and anything still omitted says so and points at the feed.
August 7, 2026 — invalid input answers 400, not 500
- An invalid release spec is now your error, not ours — deploy plans whose spec was rejected by the release core (say, both
functions.replace and functions.patch, or an unknown key in a route entry) returned 500 INTERNAL_ERROR, blaming the gateway for a bad request. They now return 400 INVALID_SPEC with a resource field naming the exact slice of the spec that was rejected.
- Malformed JSON on the admin SQL route returns 400 — an unparseable body used to surface as an internal error. The 400 keeps the parser’s position detail so you can find the offending character, and never echoes your body back. A body that parses but isn’t an object now gets the same “No SQL provided” 400 as an empty one.
August 5, 2026 — human Buzz identity and clearer ownership records
- Humans can connect a public Buzz identity from Account — the new browser flow uses the existing Run402 session, a fresh passkey, an explicit public-correlation disclosure, and Buzz’s already-released signed callback. The resulting link is public attribution, not a sign-in method or organization permission.
- One completed handoff now names three separate records — the terminal consent receipt, public human identity link, and ordinary owner membership are returned and audited independently while the founder agent remains owner.
- Disconnecting identity and removing authority are separate choices — revoking the public identity link leaves memberships unchanged; removing membership leaves the link and completed receipt intact. Principal merges preserve the original signed proof while reporting the surviving account’s effective control.
August 4, 2026 — traceable Buzz ownership handoffs
- Support can see the exact last observed boundary — the latest offer-backed ownership attempt now carries a bounded sequence of browser and server stage codes, lifecycle timestamps, a deterministic diagnosis, and the last available gateway trace handle. This distinguishes Buzz-open, callback receipt, completion rejection or success, and expiry without screenshots.
- The receipt is deliberately not a browser transcript — it stores no signed approval, event id, credential, email, identity/session id, browser/network metadata, URL fragment, or arbitrary text. Client milestones are observations only and cannot change authority.
- Billing access now follows organization roles — balance and billing-history reads accept wallet or human control-plane login, then require an active
billing-or-higher organization role. Billing-pool linkage no longer acts as permission, so revoking a member removes access immediately and authorized collaborators can read organizations beyond their wallet’s own pool.
August 1, 2026 — one-request Buzz onboarding
- Fizz no longer stops after copying the skill — in managed Buzz, saying
Please install the run402.com skill installs the inert files and continues through preflight, setup, and verified identity connection in the same turn. There is no “available next turn” response or second setup question.
- Old Run402 clients update themselves before setup — v4.17.2 is the minimum trusted Buzz client because it first made a safe relay outage warning-only for founder setup. A missing or older agent-side CLI is upgraded and verified automatically, so the human is not sent to reconnect or restart Buzz based on stale client behavior.
- The demo is the first approval — once connected, Fizz offers one relevant quick demo and waits. After a verified deployment, the separate web handoff can add the human as co-owner while Fizz remains the founder-agent owner.
- Windows agents receive native install commands — the agent bootstrap now separates environment values from the installer command and provides PowerShell and
cmd.exe forms instead of assuming Bash syntax.
- Windows setup uses the managed Node runtime directly — Buzz capability checks accept the normal
buzz.exe help spelling, while npm and Run402 run through their JavaScript entrypoints instead of command shims. A process-boundary failure is no longer mislabeled as a broken npm installation.
July 31, 2026 — Buzz demo-first ownership
- Fizz shows the work before asking about ownership — after setup, the agent proposes one relevant demo, waits for approval, deploys it, and verifies the live result. Only then does it offer human co-ownership. Testnet faucet plumbing stays out of the ordinary conversation.
- Become an owner through a normal web link — the durable chat link is inert and grants nothing. The human signs in to Run402, uses a fresh passkey, checks the six-digit code in Buzz, and approves. A click alone never counts as completion.
- Fizz remains an owner — successful adoption adds the exact signed-in human as co-owner. It does not transfer the organization or projects, share credentials, or demote the founder agent.
- Setup failures arrive together with exact repairs — the new Buzz doctor checks the agent target, runtime, clients, Run402 origins, relay, and wallet profile before setup changes anything. Optional aggregate-only diagnostics can be disabled with
RUN402_TELEMETRY=0.
- Buzz itself remains unchanged — the handoff uses Buzz Desktop’s already-released browser callback behavior. Run402 owns the offer, login/passkey flow, target binding, completion, and authoritative polling.
- Acceptance feedback now keeps independent setup independent — the Buzz page gives agents a first-party install bootstrap that verifies the Run402 digest and workspace path. A safe relay certificate or availability problem no longer blocks founder-agent setup, but it still prevents community installation and enrollment until the public relay works. Unsafe relay destinations remain blocked.
- The human no longer needs the bootstrap URL — saying
Please install the run402.com skill in Buzz is enough. Run402’s apex routing guidance selects the Buzz-specific package and actual managed runtime; the command and detailed bootstrap remain agent-only.
July 31, 2026 — first-party Run402 skill distribution
- Run402 skills now install from Run402 itself — the canonical installer discovers
run402 and run402-buzz at run402.com and downloads an immutable, content-addressed artifact from the same first-party domain. GitHub remains a transport fallback, not a happy-path dependency.
- Use the agent target you actually run — the install guide names
claude-code, codex, goose, and universal, including one combined command for mixed environments. A digest mismatch stops before installation and never silently tries a different source.
- New releases are atomic without rollout flags — immutable artifacts are uploaded and verified before the discovery index changes. If live verification fails after publication, Run402 restores the previous index; older artifact URLs remain available.
July 31, 2026 — Lightning payment verification complete
- Lightning now follows the same payment workflow as every other method — agents keep using
pay.fetch, run402 pay, MCP pay_url, or tier set. The method plugs into the existing intent, idempotency, fulfillment, receipt, credit, and replay machinery instead of creating a separate agent workflow.
- A real two-node regtest purchase settles exactly once — one fresh fixed invoice is paid, one tier mutation commits, and repeating the identical purchase returns the retained result without moving funds again. Recovery drills also cover pending invoices, expiry, cancellation, restarts, older backups, credits, and retained liabilities.
- USD price and Bitcoin amount each have their own ceiling — quotes retain their source, timestamp, exact exchange rate, spread, and validity. Buyers approve maximum USD value, maximum invoice-plus-fee millisatoshis, and a separate routing-fee limit before the wallet dispatches.
- Production payment remains separately approved — the release packet and exact mainnet payee are approved for production assembly. Invoice creation remains unavailable until permanent readiness checks pass, and the first production payment still requires its own approval.
July 30, 2026 — Buzz community control plane
- Installing a skill no longer gets confused with granting authority — shared software stays inert. A community installation links the Buzz room to a Run402 organization, human adoption makes the Buzz owner a human co-owner, and each additional agent enrolls as its own principal with bounded project grants.
- The enrollment default is chosen, never inferred — new installations start non-default. A Run402 owner clears the old installation before selecting the new one, so discovery order can never silently rewrite the choice.
- Fizz can bootstrap; the human can adopt; Honey stays Honey — the first agent legitimately owns the organization it created, its human can become a separately authenticated co-owner after fresh passkey and Buzz-owner consent, and another agent can request bounded access without sharing Fizz’s wallet or creating a throwaway organization. Adoption does not demote Fizz or transfer projects or credentials.
- Buzz itself remains unchanged — a current Buzz owner or admin publishes Run402’s exact approval as an ordinary signed message. Run402 verifies the relay’s existing identity and membership snapshot, then owns public descriptor discovery and lifecycle. Revoking an installation blocks new enrollment but leaves existing grants alone until their enrollment is explicitly revoked.
- Expired really means expired — timeouts now become retained, audited lifecycle transitions instead of a display-only guess, including active enrollments when their bounded grants end. Relay checks also pin the validated public destination into each actual connection, so DNS rebinding and private-network targets fail closed.
- Status and recovery distinguish known state from the proposed next state — pending descriptors are labeled proposed, public policy summaries show exact capability and time limits, duplicate enrollment offers disappear while one is pending or active, and every recovery action carries complete safety metadata. Rate limits use the same exact delay in the response body and
Retry-After.
July 29, 2026 — Run402 for Buzz onboarding
- Buzz agents now have a dedicated path from the room to the runtime — run402.com/buzz explains the multiplayer workflow, separate-key identity proof, verified deployment receipt, and contextual test offer, with direct links to the open-source skill.
- The install command is shorter and still explicit — the direct one-skill GitHub directory needs no redundant selector or copy-mode flag, while the Codex target remains visible and setup still waits for the user’s request.
July 28, 2026 — public Buzz/Nostr agent identity
- One agent can prove two public identities without reusing either secret — the Run402 wallet and the Buzz/Nostr agent each sign a short-lived public challenge. Run402 verifies both sides and never asks for, reads, derives, or stores the Nostr private key.
- The link explains who acted; it grants no power — projects remain organization-owned and wallets, memberships, grants, and delegates remain the only control-plane authority. An
npub cannot authenticate, pay, own, deploy, or receive a transfer.
- Creator and deployment receipts keep immutable provenance — new project, plan, deploy, release, and transfer records capture the acting principal, authenticator, linked identity, and independent authority at action time. Revoking a link updates its current status without rewriting history.
July 27, 2026 — machine account-security routes are discoverable
- Bearer clients can manage the signed-in user’s account without a hosted Run402 cookie — the HTTP reference and OpenAPI now expose the already-live
/auth/v1/account/* routes for linked identities, passkeys, passwords, and browser sessions. Identity unlink is actor-scoped and accepts the provider_sub returned by identity reads as the request’s subject.
- Sensitive changes have an explicit five-minute freshness rule — ordinary user access tokens carry signed authentication time and work directly. Refreshing a token does not fake a new login; callers re-run a credential-verifying sign-in when the API returns
R402_AUTH_FRESHNESS_REQUIRED.
July 23, 2026 — verifiable commerce buyer and safe tier replays
- Agents can require wallet-rooted merchant evidence through the payment verb they already use — the SDK, CLI, and MCP buyer verify standard direct-merchant offers before payment and matching receipts afterward. Results keep settlement, current-attempt movement, replay, delivery, signer relationship, policy, and raw non-secret evidence separate; a missing required receipt after settlement never suggests paying again.
- One tier payment produces one entitlement outcome on x402, allowance, and MPP — canonical verified payment identity, the tier mutation, refunds, ledger entries, and the retained result now commit atomically. Replays report
payment_replay:true and funds_moved:false while preserving the original action and committed lease timestamps.
- Hosted receipt authoring waits for an interoperable standard — Core understands
pricing.receipt:"on_fulfillment", but Run402 Cloud rejects it before mutation until the x402 ecosystem publishes a portable payout-wallet-to-delegate authorization carrier. No hosted tenant or tier challenge advertises Run402 merchant evidence yet; ordinary priced routes and direct-merchant verification remain compatible.
- Managed signing is fail-closed behind that gate — signer creation is resumable and crash-recoverable, retired keys are scheduled for deletion after authorization expiry, challenge signing is bounded before KMS by admission budgets, caching, circuits, metrics, and kill switches, and encoded evidence is capped at 8 KiB.
July 22, 2026 — durable payment identity for tenant-priced routes
- A stable caller key prevents a second charge after process loss — send
Idempotency-Key on paid web routes. Run402 binds the verified payer, route, method, and compatible request to one durable payment id across processes. The raw key and signed authorization are never stored; changing wallets changes the payer and is not recovery.
- Retrying the same key is the status check — an unresolved attempt returns
PAYMENT_INTENT_PENDING with Retry-After and tells the caller to repeat the identical request with the same payer and key. A settled replay reports that it was deduplicated and whether this is first or replay delivery. Tenant handlers still run at-least-once and should deduplicate durable effects by payment id.
- Transfers and payout changes drain safely — Run402 fences the old payment generation before changing project ownership or an organization payout wallet. New keyed and keyless attempts wait; an old payment cannot be delivered to a new owner. Transfer preview shows blockers, active leases, and settled outgoing-generation intents.
- Clients and functions receive the same facts — routed function context and HTTP response headers now expose the accepted idempotency key, deduplication, current-attempt funds movement, and first/replay delivery. SDK, CLI, and MCP preserve exact pending and conflict recovery instead of collapsing it to a generic payment error.
- Minimum compatible package versions — use
@run402/functions 3.11.0 for the routed function payment context, and @run402/sdk, run402, or run402-mcp 4.11.0 for caller-keyed buyer recovery.
- Compatibility break for overlong custom authorizations — tenant challenges advertise a 300-second maximum. Hand-rolled x402 authorizations exceeding that bound plus five seconds of clock skew now fail before settlement; mint a bounded authorization and repeat the same key.
July 26, 2026 — same-tab email-code sign-in
- Stay in the tab where you started — managed email sign-in now presents one accessible six-digit code field after the request. The same email also keeps the familiar one-tap link as a fallback for people who prefer it or open mail elsewhere.
- Requests remain private and honest — an anonymous response says only that Run402 accepted the request; it never claims delivery or reveals whether the address has an account. A replacement becomes authoritative only after delivery is accepted or captured.
- Machine clients get the same coherent flow — request link, code, or both; retain the opaque challenge handle; then verify either the link token or the handle plus code through the existing CLI and MCP operations or the typed SDK.
July 21, 2026 — outbound email delivery hardening
- Authentication mail no longer inherits unrelated hard-bounce suppression — trusted authentication, project mail, platform notifications, and fallback traffic now use separate internal delivery policies. Authentication attempts still honor complaints and Run402 suppression rules.
- Every managed sender remains observable — managed identities receive a restrictive fallback event configuration, and delivery, bounce, and complaint telemetry identifies the internal purpose. Selecting the public
magic_link template remains ordinary project mail and grants no delivery privilege.
- SES reputation now pages through the existing alarm relay — bounce and complaint warning and critical thresholds are monitored before provider enforcement. No mailbox API, webhook, SDK, CLI, MCP, function, or Core contract changed.
July 20, 2026 — custom-domain status and encoded-path routing
- Own-zone domains report their serving state — Run402 now records a managed Cloudflare-zone hostname as active only after Cloudflare accepts its Worker binding, and safely self-heals older successful bindings that were stranded at pending on the next status read.
- Encoded percent signs route safely — stable-host paths are canonicalized once, so a valid encoded percent reaches its declared route instead of failing a second decoding pass; separator and traversal defenses remain unchanged.
July 20, 2026 — magic-link inbox safety
- The working sign-in email is easier to identify — magic-link subjects now include the UTC send time, and the body explains that requesting a replacement makes older links stop working.
- Static callback mistakes produce a warning —
POST /auth/v1/magic-link adds a non-blocking MAGIC_LINK_REDIRECT_STATIC_ALIAS warning when the callback path is currently served by a static route alias, helping projects catch marketing pages that displaced their token-exchange shell.
July 16, 2026 — telegram notifications + routing rules
- Bind a Telegram chat with one API call, no bot token —
POST /agent/v1/notifications/channels/telegram returns a single-use, 15-minute deep link (a private-chat link and a group link sharing one code); tapping it in Telegram activates the binding and confirms in-chat. GET /agent/v1/notifications/channels lists every channel — email, webhook, and every live Telegram binding — in one read.
- Routing rules decide which events reach which chat —
POST /agent/v1/notifications/rules filters by project, source (app or platform), event type, and class, each optional and combined with AND, so a rule can page exactly one chat for exactly one event type on exactly one project. No rules means no Telegram traffic at all; existing email and webhook preferences are untouched.
- Delivery is honest, not silent — Telegram rides the same ~60-second notification tick as email and webhook, groups bursts into one message per chat, and auto-disables a binding after 10 consecutive hard failures with a mandatory alert so a blocked bot never silently stops paging.
POST /agent/v1/notifications/test now verifies the full binding, rule, and delivery chain in one call.
- Fails closed until provisioned — the channel activates only once a platform operator wires up the dedicated notification bot; until then, connecting a channel returns a clear 503 instead of silently doing nothing.
July 15, 2026 — events feed display-order reads + console Activity card
- Latest-N feed reads —
GET /projects/v1/:project_id/events?order=desc&limit=N (and the org sibling) returns the newest events first, with before_cursor keyset pagination for older pages. The response still carries the live catch-up cursor, so a display surface hands off to "what's new since" polling without a discovery call; the ascending catch-up contract is unchanged.
- The console renders the feed — the project page on console.run402.com gains an Activity card: latest 20 events with humanized labels, class and source chips, payload disclosures, copyable drill-down commands, a text filter, and Load-older paging. App-emitted events render with a distinct chip and their raw type name — new vocabulary appears with no console release. The org tab formerly labeled "Activity" is now "Audit log".
July 15, 2026 — app events emit lane
- Your deployed code can write to its own events feed —
POST /projects/v1/:project_id/events is the write twin of the project events feed: service_key auth (own project only), body {event_type, payload?, idempotency_key?}, and the row lands as an ordinary feed entry with source:"app" — read back by every existing and future feed consumer (the GET routes, the CLI, the MCP tool) with zero extra work. Never lifecycle-gated, so an app in grace keeps recording its own facts. event_type must be flat snake_case and cannot name platform vocabulary, so an app can never impersonate a platform event; every consumer discriminates on (source, event_type). The response's next_actions is always platform-synthesized — an app-supplied payload can never inject its own.
- A per-tier daily quota, pooled across the organization — app-lane emission is bounded by a new
eventsPerDay tier limit (1,000 / 10,000 / 100,000 for prototype / hobby / team), summed across every project the org owns. A denied emit returns 403 QUOTA_EXCEEDED with the exact used/limit numbers.
- Both feed reads gain source and type filters —
GET /projects/v1/:project_id/events and GET /orgs/v1/:org_id/events accept ?source=app|platform and ?event_type=name[,name], composing with the existing cursor and limit unchanged.
July 15, 2026 — 402 reserved for real payment challenges
- HTTP 402 now means exactly one thing: a real payment challenge — the gateway's last three non-payment 402s are now 403: the storage-quota backstop on applies and asset uploads, the paid-function insufficient-allowance denial, and both delegate spend-cap denials. Every error code is unchanged — only the HTTP status moved. If your client branches on a literal 402 for a quota, tier-cap, allowance, or spend-cap denial, update it to check 403 instead.
July 12, 2026 — keyless CI error reads
- CI can watch the release it just shipped — keyless — a GitHub-OIDC CI session now reads its own project's error surface (
GET /projects/v1/:project_id/errors and /:fingerprint_id), so the promote gate (run402 errors --new-in <release> --watch --fail-on-new) needs no project key plumbed into CI. A deliberate, scoped widening: a CI session already holds deploy authority, so reading the resulting fingerprints — ids, normalized templates, frame names only, never bodies or secrets — is strictly less power and completes the deploy→watch loop. Read-only and own-project-only: another project gets 403, a revoked binding 401. Project apikeys are unchanged.
July 12, 2026 — platform incident attribution
- "My bug or the platform's?" is now a field on the response — during an open platform incident a matching error carries
correlated_platform_incident plus a poll pointer to your events feed, stamped identically on managed-subdomain and custom-domain invokes. It states the correlation and lets you judge — it never claims your code is fault-free, and it is absent when no incident correlates.
- Excluded platform faults are no longer a silent drop — the denials the error rollup correctly keeps out of your app's fingerprints are counted per project, and when a platform incident resolves each affected project's feed gains one
platform_incident event with your real failed-invocation count — never a fabricated number.
- Global incidents and a degraded rider — a gateway-wide incident rides a
platform_incidents[] sidecar on the feed read (never interleaved into events[]), and GET /agent/v1/operator/status, GET /tiers/v1/status, and the events feed carry platform_status: "degraded" while an incident is open and relevant to you — and on no other response.
July 12, 2026 — rehearsal commit identity
- Rehearsals are now bound certificates — every rehearsal upgrades its plan to reviewed mode, checks freshness before allocating a branch, and reports its fingerprint, concrete base release, snapshot capture time, and fidelity limits.
- The commit hint is exact and fail-closed — the report carries the complete
required_plan commit body. The gateway recomputes current facts immediately before mutation and returns REVIEWED_FACTS_CHANGED instead of committing evidence invalidated by a deploy, restore, secret-set change, or planner change.
- Restore wins over every open plan — snapshot restore now expires all uncommitted project plans inside the atomic slot flip, records the invalidated count, and tells callers to re-plan. No pre-restore plan can silently commit against the restored schema.
July 11, 2026 — release error rollup
- Durable error memory —
GET /projects/v1/:project_id/errors groups every function failure by deploy-stable fingerprint and attributes it to the release it first appeared under — including init crash-loops and invoke failures that never write an app log line.
- A promote gate you can script — the verdict block answers "did release N introduce new errors?" against the previously active release, with real invocation volume; apply/promote responses hand back the exact
run402 errors --new-in … --watch --fail-on-new command (exit 0 = clean).
- Storm-safe by construction — identical errors collapse onto one counted row, and a bad deploy producing 30 new fingerprints is one coalesced notification (preference-gated, never mandatory), not thirty.
- Honest fidelity — each fingerprint declares its quality; functions deployed before the new error side-channel show as coarse and upgrade automatically on redeploy. Public error responses are unchanged.
July 11, 2026 — project events feed
- Cursored per-project events feed —
GET /projects/v1/:project_id/events is a durable, ordered record of what happened to a project: deploy activations, mailbox suspensions, transfers, lifecycle cliffs, verification outcomes. One call with the stored cursor catches an agent up on everything since it last looked; every event carries drill-down next_actions.
- Org-wide view —
GET /orgs/v1/:org_id/events unions the feed across every project the org owns. Members only; a project's service key cannot read sibling projects' events.
- Stale cursors reset with a remedy — an expired or malformed cursor returns
reset: true plus an earliest_cursor to restart from, never a bare error and never a silent skip. Events are retained 90 days (a year for security/recovery/billing-critical classes).
- Deploy responses hand you the feed — successful applies and promotes include a poll pointer positioned at that deploy's own
deploy_activated event, so the post-deploy watch loop starts with zero documentation lookup.
July 11, 2026 — promote serving coherence
- Promote now moves public serving with the release pointer — cross-deployment rollback atomically repoints project-owned subdomains and uses the same durable, retryable KVS, CloudFront, and custom-domain propagation path as apply activation.
- Unservable historical releases fail safely — promote returns
PROMOTE_DEPLOYMENT_UNSERVABLE when the release snapshot or deployment row is gone and points operators at re-applying instead of switching into stale or missing content.
- Promote exposes edge convergence — the response includes the standard
edge block, and operation-scoped edge verification compares the previous live release with the promoted target so run402 deploy verify --wait composes directly with promote.
- Existing databases accept promote again — the operation-kind constraint is repaired from its legacy release/asset/mixed enum to the intended apply/promote contract.
- Snapshot restores keep their replacement slot leased — the schema-slot pool claim/grace path is now active by default, preventing a restored project from pointing at a replacement slot whose pool row still says free and disappearing from REST serving.
- Branch subdomains no longer block gateway restarts — the historical reserved-infix collision guard now runs only on first cutover, so legitimate platform-created branch hosts cannot make a later migration pass fail.
- Legacy restore drift self-heals — boot-time schema-slot reconciliation now moves a stale non-current project lease into grace before leasing the project's current pointer, preserving recovery data without violating the one-serving-slot invariant.
July 10, 2026 — recovery-event reachability
- Mandatory notifications reach org members — recovery/security/billing-critical notifications now resolve recipients from the verified wallet contacts and the verified emails of active org owners/admins, so a wallet-less org with a verified human owner is no longer skipped silently.
- Unreachability is visible —
GET /agent/v1/operator/status gains an operator_reachability block, GET /tiers/v1/status gains an operator_unreachable advisory, a suspended mailbox whose notification reached nobody says so in its recovery actions, and run402 doctor warns with the registration remedy.
- Verification challenges pass the default inbound policy — platform senders like
billing@mail.run402.com are admitted through reply_only/allowlist when the SES DKIM verdict passes, so the operator-contact challenge arrives without opening the policy. Spoofed platform senders get no bypass.
- New
mailbox_suspended email trigger — an email trigger can now subscribe to mailbox_suspended: an abuse suspension creates a durable function run with the reason, timestamp, evidence, and recovery actions, so an app observes its own outage without polling or a public webhook URL.
July 10, 2026 — mailbox suspension notifications
- Every suspension notifies the operator — the
mailbox_suspended notification previously fired only for mailboxes holding a sender role, so a suspended inbound-only mailbox could silence a project without anyone hearing. Suspensions now always notify the project operator, with the mailbox's roles (possibly none) in the metadata.
July 9, 2026 — tenant x402 priced-route payment errors
- Insufficient buyer funds are machine-readable — priced-route payment failures that Run402 can identify as a payer USDC shortfall now return
payment_insufficient_funds with the quoted amount, network, asset, and a fund_wallet next action instead of exposing only a raw facilitator execution reverted string.
July 9, 2026 — paid function idempotency
- Paid function calls now have a billing fence — paid direct invokes require
Idempotency-Key, canonicalize the JSON intent, exclude auth/payment proof material from the digest, and create an invocation record before allowance checks or dispatch. Same key and same intent replay the stored result/error; mismatched intent returns 409 idempotency_conflict.
- Sync DX rides the durable run substrate — a fresh paid call creates a function run, waits briefly for a result, or returns
202 idempotency_in_progress with run_id, operation_id, and next_actions[]. Insufficient allowance and other pre-dispatch failures release the key for pay-then-retry.
- Ambiguous outcomes are explicit — lost transport after dispatch becomes
ambiguous and is never redispatched by the gateway. Billing stays uncharged/refunded, the key is consumed, and sellers who need stronger external side-effect safety should accept a business-level dedupe token in their function payload.
July 7, 2026 — tenant x402 priced routes
- Function routes can charge fixed x402 prices — web route specs can attach
pricing:{mode:"always",amount_usd_micros,pay_to:"org_default_payout"} to function targets, such as 250000 for a $0.25 action, and Run402 settles the tenant payment before invoking the handler.
- Organizations can select the payout wallet — org admins and owners can set or clear the default payout wallet with
PUT /orgs/v1/:org_id/payout-wallet. The route requires fresh auth and reports recovery actions when no payout wallet is ready.
- Apps can audit and consume payment context — paid routed functions can read
getRoutedPaymentContext(), while GET /projects/v1/:project_id/tenant-payments lists redacted project payment records for developers and read-scoped delegates.
- Rejected priced-route proofs explain the failure — paid proof failures now return
TENANT_X402_PAYMENT_INVALID with details.x402_error; self_send_not_allowed points callers at using a buyer wallet distinct from the payout wallet.
- Function lists show the injected helper runtime floor — function list responses now include recorded/current/minimum
@run402/functions runtime versions plus runtime_stale, with new deploys injecting at least @run402/functions@3.7.0.
July 5, 2026 — operator health and recovery bug fixes
- Operator health diagnostics work again —
GET /agent/v1/operator/status now reads the current organization lifecycle model instead of retired project columns, so authenticated run402 doctor checks no longer hit a production 500.
- Snapshot restore migration registry reset is valid — restore confirmation records its synthetic apply operation with the supported
apply kind before resetting migration rows, avoiding an applied_migrations foreign-key failure.
- Project creation avoids slot-reuse FK races — schema-slot allocation no longer deletes terminal project tombstones while provisioning a new project, preventing content-reference cleanup races from surfacing as unrelated project-create failures.
July 4, 2026 — drop exposed tables in one release
- Migrate-drop an exposed table in one release — a release whose migration drops a REST-exposed table (or RPC) while removing it from
database.expose now commits cleanly instead of failing with a masked EXPOSE_FAILED "transaction is aborted" error.
- Truthful expose failures — expose failures surface the first real error, suggest the manifest edit for schema mismatches, and report partial mutation with a restore-snapshot pointer when the release's migrations had already committed.
July 4, 2026 — edge coherence and release identity
- Deploy responses explain edge convergence — apply commit responses and operation reads now include an
edge block with public-edge convergence state, durable pointer-update status for managed subdomain KVS, CloudFront invalidation, and custom-domain Worker KV propagation, plus a link to GET /apply/v1/operations/:operation_id/edge-coherence.
- Static releases expose release identity — stable static responses, Worker custom-domain responses, and materialized S3 objects now carry release id/generation identity. Tenant hosts also expose
GET /_run402/release.json with no-store caching, and user static files/routes under /_run402/ are reserved.
- Edge pointer propagation is durable — release activation records KVS, CloudFront, and custom-domain KV pointer updates before commit, records post-commit success or failure, emits operation events, and retries failed targets from the lease worker until recovered.
July 4, 2026 — data snapshots, branches, and apply rehearsal
- Deploys can rehearse migrations on branches — migration-bearing apply plans now advertise
rehearsal metadata, and POST /apply/v1/plans/:plan_id/rehearse snapshots the source project, creates a contained branch, applies the candidate plan there, runs checks, and returns a report with commit/discard/keep next actions. The source project and plan stay untouched.
- Project snapshots are restore points — new snapshot routes support manual create/list/get/delete and a two-step restore plan/confirm flow. Apply commit creates a pre-migration
restore_point before DDL when possible, while large or explicitly skipped cases report snapshot_skipped_reason.
- Branches are safe temporary project copies — branch routes create/list/renew/delete expiring copies from live data or snapshots. Branches use noindex derived hosts, sandbox email by default, keep schedules off unless requested, and mark function runtime context with
RUN402_BRANCH=1.
July 4, 2026 — domain-wide mailbox addresses
- Custom mailbox domains can cover every mailbox — ProjectDomain mailbox addressing now supports
all_mailboxes:true with custom mode after email receive is domain-wide. Every current and future mailbox local part can send from local@your-domain.com without enumerating slugs, while managed addresses remain receive-compatible fallbacks.
- Email activation no longer waits on unrelated web DNS — validation is scoped to the email plane, so web DNS conflicts still report clearly but do not block verified email receive or custom mailbox-address activation.
- Legacy verified inbound domains are healed on deploy — migration
v1_111 restores ProjectDomain state for projects that already had DKIM-verified, inbound-enabled custom domains before the ProjectDomain consolidation.
July 4, 2026 — content-tracked deploy migrations
- Generated SQL can use stable names — SDK, CLI, and MCP deploy authoring now accept migration
name for idempotent generated or seed SQL. Clients compile it to a content-derived wire id, so unchanged SQL noops and changed SQL applies as a new migration. Hand-authored schema migrations can keep using immutable id values.
- Checksum mismatch errors explain every fix —
MIGRATION_CHECKSUM_MISMATCH responses now list every conflicting migration with checksums and applied_at, then return next actions for switching generated SQL to name, minting a new versioned id, or requesting operator adoption for legacy migrations.
July 4, 2026 — tenant test sessions
- Tenant auth can be tested without real inboxes — service-key callers can mint deterministic watermarked users with
POST /auth/v1/test-sessions. Labels derive <label>@<project_id>.test.invalid, and responses include a 2-hour browser-session cookie value, a 2-hour bearer token with is_test:true, app origins, curl examples, and test_mode status.
- Test users and captured email are manageable — new
/auth/v1/test-users and /auth/v1/test-emails routes let agents list non-secret summaries, clean up watermarked users, and inspect messages captured from auth, platform, or mailbox sends to .test.invalid. Captured test email skips SES and outbound quota counters.
- Test traffic is visibly watermarked — routed app requests from test browser sessions carry
actor.isTest:true, x-run402-test-session: 1, and routed invocation log metadata. Normal signup paths reject .test.invalid with R402_AUTH_RESERVED_EMAIL_DOMAIN.
July 3, 2026 — ProjectDomain lifecycle and validation-safe email
- ProjectDomain is the canonical custom-domain workflow — agents now configure web, email send, email receive, and custom mailbox addresses through project-scoped
/projects/v1/:project_id/domains/:domain routes. Responses separate desired, observed, and effective state; include stable checks like email.receive.route; return DNS records with safety metadata and BIND lines; expose authority options; and provide one canonical next_action.
- Managed mailbox fallback is explicit — mailbox address selection reads ProjectDomain effective state only. When custom receive health drifts, mailbox primaries fall back to managed addresses, the domain reports
needs_repair, and agents get repair/test-receive actions without losing mailbox ids, history, or webhooks.
- Email validation can use product APIs — mailbox sends remain normal accounted outbound sends even for same-domain loopback, raw mode supports text-only payloads, attachments stay byte-preserving within documented limits, and mailboxes can opt into first-contact inbound with
reply_only, allowlist, or open.
- Recovery is operator-visible — project-scoped suppressions can be listed and cleared by API, simulator/self-domain/platform route failures no longer count as production reputation evidence, and default/auth sender suspensions emit events plus operator notifications with reason metadata.
July 3, 2026 — client update awareness and compatibility hints
- Gateway errors can now guide stale clients — recent Node SDK/CLI clients may send bounded advisory metadata in
Run402-Client, such as their surface and package version. The gateway parses it request-locally, never treats it as auth or trust, and does not enable browser custom headers yet. When a configured advisory policy matches a Run402-originated error, the original error remains and the envelope may add details.client_compatibility plus a semantic upgrade_client next action.
- Hard client minimums are staged — compatibility policy now supports observe, advisory, enforce, disabled, and per-policy rollback modes. A future scoped hard minimum can reject before mutation with
CLIENT_VERSION_UNSUPPORTED, mutation_state:"none", and safe_to_retry:true, but no broad stale-client block is enabled by default.
July 3, 2026 — sender trust, custom-domain auth, and project-key cache DX
- Inbound reply events expose SES sender trust —
reply_received mailbox webhook payloads and ReleaseSpec email-trigger function events now include sender_trust with the SES receipt-time spam, virus, SPF, DKIM, DMARC, processing-time, and recipient verdict metadata that Run402 already stores. Signing and audit apps can now persist those SMTP-time attestations directly from the event payload. Existing consumers can ignore the additive field.
- Custom domains no longer require a local service-key cache by default —
/domains/v1 routes now accept SIWX wallet, control-plane session, or scoped delegate auth with an explicit project_id. Service-key auth remains compatible, but a supplied mismatched project_id now returns PROJECT_CREDENTIAL_PROJECT_MISMATCH.
- Client project selection separates server truth from local keys — normal project list/get/use flows are server-authoritative. Local anon/service keys are treated as a credential cache for explicit key-required operations and report
PROJECT_CREDENTIAL_NOT_FOUND with source:"local_cache" when absent.
July 2, 2026 — platform security headers
- Project sites and APIs now get baseline browser hardening — Gateway-served project sites, managed subdomains, API responses, and gateway errors now include
X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-origin, and Content-Security-Policy: frame-ancestors 'none'. Run402-owned hosts also receive HSTS with includeSubDomains; customer custom domains keep the non-HSTS baseline so Run402 does not impose an HSTS policy on domains it does not own.
July 2, 2026 — deploy.apply progress events
- Deploy progress now has real phase events —
GET /apply/v1/operations/:operation_id/events now returns durable server-side events instead of a single synthesized status snapshot. Agents can see commit, stage, gating, migrate, expose, schema_settle, role_gate, activate, and ready transitions with phase details and duration_ms when available. Activation now breaks down further into activate.asset_copy_wait, activate.functions, activate.snapshot, activate.asset_variants, activate.transaction, and activate.side_effects. The route supports limit/cursor pagination and still returns one synthetic event for older operations.
- App installs have convergence state —
run402 up can record per-project/per-app install state through POST /apply/v1/app-installs and read it back with GET /apply/v1/app-installs. The state records status, manifest/graph digests, resource summaries, bindings, and the last deploy operation id, but never secret values.
July 2, 2026 — project-scoped managed mailbox addresses
- Deleted and archived projects now release project mail hosts — Fresh app clones can reuse the ergonomic project-name mailbox host, such as
notifications@kysigned5.mail.run402.com, after a previous same-name test project is deleted or archived.
- Mailbox names are now reusable per project — agents can create common app-local mailboxes like
notifications and forward-to-sign on every cloned project without global collisions. New managed addresses use local@<project-mail-host>.mail.run402.com, and the project mail host is allocated once so web-subdomain renames do not move email addresses.
- Project names are preferred for managed mail hosts — a project named
kysigned3 now gets addresses like notifications@kysigned3.mail.run402.com when that label is available, with deterministic collision fallbacks only when needed.
- Managed aliases stay stable through custom-domain promotion — mailbox responses include
managed_address. The primary address and outbound from_address switch to local@your-domain.com only after the custom sender domain is both DKIM-verified and inbound-enabled; replies to the managed address continue to route to the same mailbox.
- One wildcard inbound path covers managed project mail — Run402 now routes
*.mail.run402.com through the existing SES/S3/Lambda pipeline by resolving project mail host, then local part. The legacy local@mail.run402.com receive path remains for compatibility.
July 1, 2026 — durable function requests, function bundle shim, and webhook delivery JSON
- Email events can trigger functions directly — ReleaseSpec
functions.replace.<name>.triggers[] now supports type:"email" entries for mailbox reply_received, delivery, bounced, and complained events. Matching events create idempotent durable function runs with the canonical email payload under payload.event, so apps can react to inbound replies and delivery outcomes without polling or external webhook glue.
- Durable function requests are now the background-work API — service-key callers can create idempotent delayed/reliable requests with
POST /functions/v1/:function_name/runs, inspect/log/cancel/redrive them under /functions/v1/runs/:run_id, and correlate logs by fnrun_... / fnatt_.... The target function receives a normal POST with X-Run402-Trigger: function_run and a typed envelope. The function helper, SDK, CLI, and MCP docs now expose the same surface, and prototype-tier projects can try it with smaller caps.
- Function bundles no longer collide with user
createRequire imports — the Lambda wrapper now aliases its internal CommonJS bridge instead of declaring createRequire at top level, so user code can import createRequire from node:module without failing at bundle load.
- Webhook delivery timestamps are JSON strings — mailbox webhook delivery list/read responses now serialize
created_at, next_attempt_at, and delivered_at as ISO-8601 strings, matching the public timestamp contract.
June 2026 and earlier are in the complete machine-readable history at
/updates.txt.