Stop us if you've heard this one before:
You're on the security & compliance team. A new SaaS tool lands on your desk. The marketing team is excited and wants to onboard it. You're generally used to these tools asking for all kinds of OAuth permissions that would let an app post on your behalf, read every DM in your inbox, or require full account access — even though it promises it won't abuse it.
This post is for you.
Here's exactly what Vibewatch asks for, what it stores, and — more importantly — what it deliberately doesn't.
The philosophy: The best way to keep data safe is to not have it in the first place.
Every byte of sensitive data you collect is a byte that has to be defended. So the strongest security posture isn't a thicker vault. It's a smaller one.
Vibewatch is built around that idea. The product reads community signal — posts, replies, and messages in the channels you've explicitly added — and turns it into sentiment reports. The vast majority of that signal is already fully public (X mentions, subreddit posts, open Discord channels) but where it isn't, you control exactly which channels and group chats Vibewatch can see. Either way, the product doesn't need your DMs, your customer list, the ability to manage your server, or the ability to post on your behalf to do its job — so it doesn't ask for any of them.
Read-only permissions. Most of what follows is a consequence of that one decision.
What Vibewatch asks for, by platform
X (Twitter)
Vibewatch does not log in to your X account.
There is no "connect your X account" button anywhere in the product. Vibewatch only reads public posts and mentions — the same kind of data anyone with an X account can already see.
Vibewatch can't tweet from your handle, follow or unfollow anyone, read your DMs, or change your account settings. None of that is something we're capable of doing.
Discord
Vibewatch joins your server as a shared, read-only bot. The install link requests exactly two Discord permissions: VIEW_CHANNEL and READ_MESSAGE_HISTORY. That's it.
It cannot send messages, kick or ban members, manage roles, change channel settings, or read DMs.
One thing worth being upfront about: the bot reads the channels your server admins choose to add it to. Most teams point it at their public community channels, since that's where the sentiment signal lives. But if an admin grants the bot access to a private channel, the bot will read messages there too — that's how Discord's permission model works for any bot. You're always in control of which channels Vibewatch can see, and you can revoke that access at the channel or server level at any time. If you remove the bot from your server, every read path stops immediately.
Telegram
Telegram integration uses a bot token you provide (the standard Telegram Bot API pattern — you create a bot via @BotFather, paste the token into Vibewatch). The token is stored fully encrypted on Vibewatch servers (more on that below).
Bot tokens on Telegram are inherently scoped: a bot can only see messages in chats it's been added to, and it cannot read user DMs that don't involve the bot. Vibewatch reads from those chats in read-only mode and never sends messages of its own.
Same disclosure as Discord: the chats Vibewatch sees are the chats you add the bot to. Most teams use it on their public or community-facing Telegram groups, but if you add it to a private group, the bot will read messages there too — that's how Telegram's bot model works. You control that choice, and you can remove the bot from any chat to cut off access immediately.
Reddit ingestion uses Reddit's Devvit app platform. A moderator of your subreddit installs the Vibewatch Devvit app, and Reddit forwards new posts, comments, and their delete events from that subreddit to Vibewatch over HMAC-signed webhooks. There is no Reddit user OAuth flow anywhere in the product.
The app subscribes to exactly four read-only event triggers — post submit, comment submit, post delete, comment delete — and makes no Reddit API write calls of any kind. It cannot post, comment, vote, moderate, ban, or send messages, because the code paths to do those things do not exist in the app. The only outbound destination from the Devvit app is Vibewatch's ingest endpoint, which is the only domain allowlisted in the app manifest.
The setup nonce that links your subreddit to your Vibewatch org is one-time, stored encrypted, and revocable from the Vibewatch dashboard. Uninstalling the Devvit app from your subreddit cuts off the event stream immediately.
Bluesky
Bluesky reads public posts through the AppView API. We have our own Vibewatch account that we authenticate through to read posts — so we don't need yours. There is no Bluesky user OAuth flow, no DM access, and no posting endpoint.
Other public sources (Nostr, Farcaster, Lens, Snapshot, GitHub Discussions, YouTube, Discourse)
These platforms expose public read APIs that don't require user authentication. Vibewatch reads public posts, casts, notes, governance proposals, discussions, video comments, or forum topics from the public keys, handles, channels, repositories, or spaces you configure.
Farcaster, YouTube, and GitHub Discussions are accessed using API keys that Vibewatch created — no key needed from you. Nostr, Lens, Snapshot, and Discourse are read with unauthenticated public requests. In every case Vibewatch is acting as a public API client; none of these integrations involve a credential tied to your account, and none of them can post, comment, vote, or modify state on your behalf. On Nostr specifically, that's enforced by cryptography rather than policy — posting requires a private key that never leaves your client.
Sending reports out: Slack and Notion
The previous section covered everywhere Vibewatch reads data. There are two places it writes: into your Slack workspace, or into your Notion workspace, to deliver brand reports. These are the only integrations in the product where Vibewatch holds a write-capable OAuth token — and in both cases the write is narrowly scoped to a destination you pick at install time.
Slack
Vibewatch's Slack integration is write-only by design. Most Slack apps a security team is asked to review request channel-history scopes so they can pull conversations in — that's where the risk lives. Vibewatch's app holds no message-read scopes of any kind (no channels:history, groups:history, im:history, or mpim:history). It is structurally incapable of reading a single message in your workspace, public channel or private.
What it can do is push reports out to one channel you choose at install. The full scope list is just three: incoming-webhook (Slack prompts you during install to pick a single delivery channel, then provisions a webhook URL bound to that channel), chat:write (lets the bot DM the installer with delivery alerts), and emoji:read (so reports render correctly when your workspace uses custom emoji). The webhook URL is stored encrypted on Vibewatch's servers.
Notion
Notion's integration model doesn't use OAuth scopes the way most platforms do — access is gated by which pages you explicitly share with the integration. During install, Notion's native picker asks you to select the pages or workspaces Vibewatch can see; the resulting access token is constrained to that selection and cannot reach anything you didn't share.
After install, you pick a single parent page from the Vibewatch dashboard. Reports are written as child pages under that parent. Vibewatch cannot read or modify anything outside the pages you shared, and revoking the integration in Notion's settings cuts off all access immediately.
What we store — and what we don't
We store:
- Messages from the channels you've connected, so we can score them and let you re-open old reports.
- Your sentiment scores, corrections, and the qualitative rules the system has learned from your feedback.
- The minimum account metadata needed to render a report — handles, server names, channel names, and any
npubs you've added. Adding a second handle to an existing integration (e.g. brand and founder on X) doesn't expand permissions — each handle is read under the same read-only auth model as the first. - Integration credentials (e.g., your Telegram bot token), encrypted on our servers. Nostr has no credential to store.
We don't store:
- Direct messages. Vibewatch can't read DMs on any platform — not on X, Discord, Telegram, Reddit, Bluesky, or Nostr. Whether a channel you add Vibewatch to is public or private, one-to-one DMs aren't part of what the bot can see.
- Passwords. Authentication is handled by Clerk, an industry-standard user management tool. We never see your password.
- Payment card numbers. Billing goes through Stripe's hosted Checkout — cards are entered directly into Stripe's page, and the only thing our server sees is the resulting subscription status.
The point isn't that we protect this data carefully — it's that we can't access it in the first place. There's no internal tool we could use to read your DMs, look up your password, or pull your card number, because none of those things ever enter our systems. That's by design.
Encryption and the boring stuff (that still matters)
- In transit: TLS everywhere, enforced via HSTS.
- Security headers: A strict Content-Security-Policy,
X-Frame-Options: DENY,X-Content-Type-Options: nosniff, a restrictivePermissions-Policy(camera, microphone, and geolocation all disabled), and a tightReferrer-Policy. - Credential encryption: Integration credentials (bot tokens, third-party API keys) are encrypted at the column level using authenticated symmetric encryption before they're written to the database. The encryption key lives outside the database.
- At rest: Stored data sits on a managed database with at-rest encryption at the storage layer.
- Authentication: Delegated to Clerk. The application never sees user passwords, and session validity is enforced on every authenticated request.
- Payments: Delegated to Stripe's hosted Checkout. Card data never reaches our servers.
A few things I'm deliberately not claiming, because we haven't formally implemented them yet: SOC 2 attestation, a formal key-rotation cadence, a published data-retention schedule for raw messages, or per-user audit logging on data reads. If those are dealbreakers for your team, email me — I'd rather have the conversation than oversell.
Backups and self-deletion
Backups run automatically on a daily cadence to encrypted off-site storage (Cloudflare R2), retained for 30 days with automatic pruning of older snapshots.
When you delete your organization from the Vibewatch dashboard, it's a hard delete: messages, integration credentials, reports, sentiment data, and API keys are removed from the live database immediately, and any active sessions or tokens scoped to that organization are invalidated. Backup snapshots taken before the deletion age out on the same retention schedule and are then pruned.
What this means for your team
If your social media manager is asking to connect Vibewatch, here's the short version you can take back to your team:
- Vibewatch can't post from your accounts. The ability doesn't exist in the product.
- Vibewatch can't read DMs on any platform.
- Discord access is two permissions only — read channels and read message history — and only on the channels your admins explicitly grant.
- X uses no user OAuth at all.
- Reddit ingestion is a moderator-installed Devvit app that subscribes only to post/comment submit and delete events. It has no write capability on Reddit — no posting, modding, voting, or messaging.
- Bluesky uses app-level authentication, never per-user.
- Nostr, Farcaster, Lens, Snapshot, GitHub Discussions, YouTube, and Discourse all read public APIs — some via a Vibewatch-held API key, some unauthenticated. None require a credential from you, and none have write capability.
- Slack and Notion are the only places Vibewatch writes anywhere. The Slack app is write-only — it holds no message-read scopes and is structurally incapable of reading conversations in your workspace; it only posts reports to the one channel you pick at install. Notion reports write under one page you pick at install (the token is scoped to pages you explicitly shared with the integration).
- Telegram uses a bot token you provide, stored encrypted.
- Passwords, card numbers, and private messages are all data we deliberately don't collect.
If you're a security or compliance reviewer and you want to go deeper — specific subprocessors, data residency, retention windows, vendor questionnaires — email security@vibewatch.io and I'll get you what you need.
