Skip to content

Security & privacy

This page describes the security posture that is shipped and live at publication time. Nothing here is planned or aspirational.

Credentials

  • Users authenticate per connection with their own Bloomy Earth Dashboard → Integration API credentials. There are no operator-held Bloomy API secrets.
  • Credentials are verified against the Bloomy API before any token is issued, then stored encrypted inside the OAuth token's properties — never in logs, never in tool results, never in error text.
  • OAuth grants are re-verified against the Bloomy API at refresh time and revoked immediately when the credentials are rejected, so a revoked application password cannot keep minting access tokens.

Scopes and resource binding

  • The resource server rejects tokens minted for another resource (validation runs over a Workers service binding from the resource server to the authorization server).
  • mcp:read is required at the transport level; the three write tools additionally check mcp:write on every call. Both checks read the live token scope, so narrowing the scope on a refresh tightens the token immediately.
  • The scopes sealed into the token at consent time are a forensic divergence signal only — never an allow path.

Sign-in abuse

The consent approve path is rate-limited per IP and per username. Abuse of the sign-in page is throttled without touching the token surface.

Your conversation stays yours

Conversation content is never sent to Bloomy Earth. Estimation receives only counters — response counts, or token counts when the host exposes them. Actions receive only the confirmed parameters of that action. All inputs are validated in the Worker before any Bloomy API call: positive integers, title and content size, gift fields, email shape.

The two-call confirmation floor

Every write tool — plant_trees, offset_co2_by_tonne, post_activity — requires two calls. A first call with the intended arguments and no confirmationCode executes nothing; it returns a one-time code plus a summary of exactly what the second call would do. Only a second call repeating the identical arguments with that code spends or publishes anything.

The code works once, expires after about five minutes, and redeems only for the same account, client and argument set. Every refusal outcome spends nothing:

  • Declined → "not executed — the user declined this action. Nothing was spent. Do not retry unless the user explicitly asks you to."
  • Wrong or already-used code → "not executed — the confirmation code was never issued or has already been used. Nothing was spent. Do not retry unless the user explicitly asks you to."
  • Expired code → nothing executes; a fresh first call mints a new code.

This floor is server-side and identical for every host. A host's own approval dialog or setting sits above it and cannot replace it.

This documentation site

The site you are reading is static: pages are pre-built HTML, there are no cookies, no analytics, no accounts, and no third-party runtime requests — assets such as fonts and scripts are vendored into the site at build time rather than fetched from a CDN in your browser.