Skip to content

PostEveryPlatform / Trust

Security and account access

Keep control of what connects, what an agent can do and when a post goes out. This brief describes the safeguards and limits implemented in our app, including optional services and incomplete reporting arrangements.

Last checked against our code:

On this page

How you connect platforms

Connect a social account through our posting partner’s hosted portal. PostEveryPlatform does not ask you to type your social platform password into our app. Bundle.social handles the connection flow and returns account details to the workspace, so you can choose where a post goes without handing a platform password to an AI agent.

Our account records contain the platform, partner account ID, handle, display name, avatar URL, follower count, connection status and local settings. The account schema has no social password or platform access-token column. A connected account can be disconnected from the app; the partner must accept the disconnect before we remove the connection locally.

What an AI agent can and cannot do

New API keys start with read, draft, schedule and reply permissions. Publish and webhook permissions are separate choices. Read allows access to workspace content; draft allows writing drafts; schedule allows scheduling. Reply can send replies, likes and hide actions without a post approval step. Choose only the permissions your integration needs.

Agent posts wait for approval by default. There are two controls: a key or connected app can have “Posts skip my approval” enabled, and the owner can turn the workspace approval switch off. Either can let ordinary agent posts skip the hold. Publish permission is still needed to post immediately. A draft is saved without an approval hold.

Agents cannot connect or disconnect accounts, change billing, change the login, manage team membership, change approval settings or approve posts. They cannot generate paid AI images or videos. The same restrictions apply through the REST API, MCP and the built-in agent because their requests pass through the shared permission policy.

Every agent request that reaches a feature is logged when the asynchronous log write succeeds. Requests refused before that point, including missing permissions and no-plan write refusals, are not recorded there. Logging errors are suppressed so they do not break the request; this activity history is not a complete or guaranteed security audit trail.

Keys and sessions

API keys are stored as SHA-256 hashes. The app shows a prefix and metadata, rather than the stored raw secret. New bearer requests check revocation and expiry against the database. Revocation blocks subsequent key authentication; a request already admitted can finish. Rotating a key gives the old key a 600-second grace window unless you revoke it earlier.

Browser sessions last 30 days. The session cookie is HttpOnly and SameSite=Lax, and uses Secure on HTTPS. Settings can count other signed-in sessions and sign out every other device while keeping the current session. This does not revoke API keys or connected AI apps; revoke those separately in AI agents settings. There is no device-by-device session list.

MCP connections use OAuth authorization with PKCE S256. Authorization codes last 10 minutes, access tokens last one hour and refresh tokens last 30 days. Tokens are hashed in storage, refresh tokens rotate, and reuse of a rotated refresh token revokes the grant. You can revoke a connected app independently of your browser session.

Sign-in protection

Passwords are salted and hashed with PBKDF2-SHA256 using 100,000 iterations. Sign-in checks use the same password work for unknown emails and known accounts. Login defaults allow 30 attempts per IP per 15 minutes, eight wrong passwords per email and IP, and 40 wrong passwords per email across IPs. A limit returns HTTP 429 with a wait time.

Reset requests default to 10 per IP per hour and three per email per hour. Signup defaults to 10 per IP per hour; the checked production configuration sets 40. Operators can configure these limits. Reset links expire and are single use. Google sign-in is optional and is available only when its client credentials are configured.

Webhooks

Outgoing webhooks go to HTTPS destinations the customer sets. Deliveries carry a PEP-Signature generated with HMAC-SHA256 over the timestamp and payload using the webhook secret. Receivers should verify it before acting. Delivery retries are capped at five attempts; a webhook is not a promise that a remote service accepted the event.

A key or connected app needs webhook permission to manage its own hooks. Revoking its access also removes its hooks. Webhook payloads can contain post and comment text, so granting this permission authorizes that data to leave the workspace for the chosen destination.

Where data lives

PostEveryPlatform runs on Cloudflare Workers, with structured data in D1 and media files in R2. This describes the configured services, not a country-level data residency guarantee. Uploaded media is reachable through an unguessable public URL so the posting partner can download it; it is not a private file vault. Backup objects are excluded from that media route.

Who processes data

The table describes destinations present in the server code and when they are used. It does not assert that every optional AI service is enabled. Bundle is the configured production posting provider. Upload-Post and the sandbox adapter remain available in code but are not selected by the production configuration.

Customer-selected webhooks receive event payloads. Feed readers, media imports, OAuth client-metadata and logo fetches contact customer or app-selected public destinations. Generated image and video downloads also follow provider-returned file URLs after URL checks. These are dynamic destinations rather than a fixed processor list.

Public-profile watchlists send the selected handle to Bluesky's public profile API or an allowed Mastodon instance to read public profile details and counts. Mastodon requests are limited to mastodon.social, mastodon.online and fosstodon.org. These lookups do not use the watched person's login. They run when a profile is added and for daily snapshots.

Server destinations and activation conditions
Service / hostData and purposeWhen used
Bundle.social (api.bundle.social)Post text, media URLs, account identifiers and engagement actions for connected networks.Production posting provider.
Stripe (api.stripe.com)Billing email, workspace references and subscription choices for payments.When checkout or subscription operations run.
Resend (api.resend.com)Recipient email, message content and transactional links.When email is configured; reserved test domains are skipped.
Cloudflare (D1 / R2 / Workers)App requests, database records, uploaded files and backups.Configured hosting and storage.
OpenRouter (openrouter.ai)Prompts, selected text, voice context and agent conversation/tool context.When AI writing or the agent is enabled.
fal.ai (fal.run / queue.fal.run)Image/video prompts and optional reference image URL.When FAL_API_KEY is configured.
Google Gemini (generativelanguage.googleapis.com)Image prompts and image-generation input.Optional image provider when configured and selected.
Google sign-in (accounts.google.com / oauth2.googleapis.com / openidconnect.googleapis.com)Authorization code and verifier; profile identity is read for sign-in.Optional when Google OAuth credentials are configured.
Upload-Post (api.upload-post.com)Posting/account data if this adapter is selected.Optional adapter; not the configured production provider.
Bluesky public profile API (public.api.bsky.app)Selected public profile handle, to read profile details and follower, following and post counts.When a Bluesky watchlist profile is added or its daily snapshot runs.
Mastodon (mastodon.social / mastodon.online / fosstodon.org)Selected public profile handle, to read profile details and follower, following and post counts.When a Mastodon watchlist profile is added or its daily snapshot runs; only these instances are allowed.

How long we keep things

Cleanup runs on scheduled jobs or feature operations, so the periods below are cleanup thresholds rather than exact deletion deadlines. Comments are swept when the inbox syncs. Some operational records have no timed cleanup in this branch; absence of a timer is not a promise of short retention. The table distinguishes those records from data with explicit cleanup.

Agent actions have no timed deletion job and belong to the workspace through a cascading foreign key. They remain until the owned workspace is removed through account deletion. Posts, support tickets and other workspace records also have no general age-based deletion policy in this branch. AI usage records (ai_usage) and AI media jobs (ai_media_jobs) have no foreign keys to users or workspaces and survive account and workspace deletion. Neither table has timed cleanup. Usage records retain user/workspace IDs, request metadata, token counts and costs, without prompt or reply text. Media jobs retain prompts, user/workspace IDs, provider URLs and request, credit and cost metadata.

Cleanup thresholds implemented in this branch
RecordRetention / cleanup
Events and email logs90 days for events; 30 days for email logs.
Sessions and auth tokensExpired sessions; auth tokens one day after expiry, in nightly cleanup.
Throttle and unfinished uploadsThrottle rows and pending uploads older than one day.
Google sign-in recordsFinished or abandoned records older than one day, when a Google sign-in starts.
Feed deduplication recordsRecords older than 30 days for that feed, when feed items are imported or refreshed.
Import keysWorkspace keys older than two days, when an import is saved.
Orphan filesEligible files with no media row older than one day; each nightly sweep is capped.
Inbox comments and replies120 days, swept during workspace inbox sync.
Status samples and provider eventsSeven days; alerts 90 days.
Bot counters400 days; counters group paths rather than retaining approval tokens.
Delivery history and partner-day summariesDays older than 400 days, during nightly status-history maintenance.
Public-profile watchlist snapshotsDays older than 400 days, during scheduled watchlist snapshot processing (minute and nightly jobs).
API request bookkeepingOld rate windows after two minutes; idempotency records after one day in scheduled cleanup. API and MCP writes also remove unfinished idempotency records older than two minutes when the same key is reused. Completed webhook deliveries after 30 days; pending deliveries excluded.
MCP authorization recordsCodes one day after expiry; token pairs after refresh expiry. Revoked grants after 90 days only without remaining token rows.
Unused OAuth clientsMetadata clients after 30 days without a grant; never-used registered clients after seven days without a grant. Sweeps are capped.
Agent action historyNo timed cleanup; workspace foreign-key cascade removes it on account deletion.
AI usage and AI media jobsai_usage and ai_media_jobs survive account and workspace deletion without foreign-key cascades or timed cleanup. Usage keeps identifiers, request metadata, counts and costs; media jobs also keep prompts and provider URLs.
Portable backups14 dated nightly copies; separate from primary row deletion.

Backups

The nightly job creates a portable JSON copy of data tables in R2 and keeps 14 dated copies. It excludes sessions, one-time auth tokens, throttle rows and email logs. Other tables can contain customer content and webhook secrets. The code also notes D1 Time Travel with a 30-day restore window; this page does not verify an actual restore or promise a recovery time.

Export and delete

You can export workspace data as JSON or CSV while signed in, including after a plan ends. Exports are paginated, so follow the next-page link to collect the full set. Deleting an account requires password confirmation and the word DELETE. The app first attempts to stop subscriptions and remove partner profiles, and returns an error if that step fails.

On successful account deletion, owned workspaces and their foreign-key-linked rows are deleted through database cascades and media deletion is attempted. AI usage (ai_usage) and AI media jobs (ai_media_jobs) survive because they have no user/workspace foreign keys, and neither has timed cleanup. Retained usage data includes user/workspace IDs, request metadata, counts and costs; media-job data also includes prompts and provider URLs. Posts you wrote in someone else’s workspace stay there, credited to its owner. A keyed email hash remains to prevent another free trial. Backups age out separately, and orphan-file cleanup retries files left without a database record. We do not claim that every copy vanishes instantly.

Incidents

The public status page shows current checks and an operator notice when one is set. The API reads STATUS_NOTICE for that notice and keeps status samples for seven days in this branch. A permanent incident archive is not built here. This brief does not claim an uptime percentage, certification or independent audit.

Reporting a vulnerability

Signed-in users can open Settings and use Support to save a ticket. Include the affected URL, what happened and concise reproduction steps without passwords, keys or other people’s data. The ticket is saved in the workspace and the server attempts email forwarding. Saving a ticket does not establish that a person received it.

A verified security mailbox has not been supplied for this profile, and a reachable reporting recipient still needs operator confirmation. No response deadline or reward is promised here. If the app says forwarding failed, the saved ticket alone is not a confirmed vulnerability-reporting channel. The published security contact points to this section so that limitation is visible before you submit.

Questions

Can an agent approve its own post?

No. The shared permission policy blocks agents from approval routes and account, billing and login changes.

Does revoking a key stop a request already running?

Revocation blocks new authentication. A request admitted before revocation can finish.