How Tenure handles your customers' data, your billing, and your AI agents.
Every record is scoped to an organization id and every query is filtered by the signed-in user's organization or the API key's organization. Public widget keys can only create and resolve cancel sessions.
Passwords are bcrypt-hashed. API keys are shown once and stored as SHA-256 hashes; they carry scopes, an optional expiry and a test-mode flag. Sessions are encrypted, HttpOnly, SameSite cookies that are invalidated on password change, on password reset and by "Sign out everywhere".
The credentials you connect (Stripe, Chargebee, Anthropic, Resend, live and test billing keys, and webhook and widget signing secrets) are encrypted at rest with AES-256-GCM under a key (SECRETS_KEY) that lives only in the deployment environment, never in the database. Set that key before connecting anything: without it a self-hosted deployment stores what you enter as you supplied it. Keys can be rotated with a documented script; the dashboard shows only the last four characters.
Five roles gate every configuration action server-side: owner (everything, including roles and deleting the workspace), admin (configuration, integrations and invites), developer (reads everything and manages API keys and webhooks, but not billing execution settings or the team), member (works cancel attempts, settings read-only) and viewer (read-only). Owners and admins can restrict the dashboard to an IP allowlist (CIDR). Changing someone's role signs their existing sessions out. The full permission matrix is in the security documentation that ships with Tenure.
Offers execute only from your published plan, only after an explicit accept, only server-side. Agents receive guardrails (max discount, no improvisation) and cannot call billing directly. The cancel path always proceeds even if Tenure is down.
Signed with HMAC-SHA256 over timestamp + body (x-tenure-signature, x-tenure-timestamp) so your backend can verify origin and reject replays. Every delivery is recorded with status, attempts and response code; failed sends retry with exponential backoff (up to 8 attempts) and can be replayed from the Webhook deliveries list on the Integrations page. Stripe webhooks are verified with your signing secret.
Tenure stores the fields you send (plan, MRR, tenure, usage signals) and cancel-session outcomes. Customers can be erased with all their sessions from the dashboard ("Erase customer" on the customer page); the API exports a customer's data but does not erase it. Owners can export the whole workspace as JSON or delete it outright (all child records cascade).
Every decision, execution, email and admin change is written to a hash-chained, verifiable audit log per organization: each row's SHA-256 hash covers the previous row, so deletions or edits are detectable with the Verify integrity check. The log is exportable as CSV or JSON by owners and admins, and retention is configurable per workspace (default 365 days; 0 keeps it forever). Rows past that age are purged nightly, and the purge itself is written to the log. Requests carry an x-request-id that is echoed in responses and structured logs for correlation.
Results reports what was observed: customer moments, offers accepted, billing changes confirmed and money collected, each number labelled with its kind and the count it rests on (a rate is withheld below 20). Each accepted offer's forecast is shown beside what billing actually collected once its period has ended. Tenure does not hold customers out as a comparison group today and never reports causal lift: a comparison group needs the measurement floor (at least 1,000 eligible accounts or 40 eligible customers a month), and no workspace is held out below it. Test-mode and simulated activity is never counted in live figures.
Tenure offers only what you published: each moment follows your plan's lines, their rows and your approved limits, and code applies every eligibility rule, cooldown and budget. The decision model answers typed questions about the moment (see Subprocessors); it never invents an offer, and no customer data is used to train models.
TypeSafe (typesafe.ai), the decision model Tenure asks what to offer, receives data from every workspace: for each moment, the moment type, bucketed billing state (price and tenure bands, never amounts), summaries of the usage facts you send, the offers in your plan, and up to 1,200 characters of the subscriber's typed text after email addresses, links, phone numbers, card-like numbers and the subscriber's name are removed; already-redacted cancel-reason text (up to 600 characters) to group feedback into themes; your public site text at setup; and your workspace's aggregate weekly figures. It never receives a subscriber's email address, name, customer id or billing amounts. Otherwise only the services you connect receive data: your billing provider (Stripe or Chargebee) for billing changes, Resend (email) and Anthropic (Claude, for plan drafting, questions about a decision, the weekly summary and feedback themes). Apart from TypeSafe and Firecrawl, nothing is sent to a service you have not configured. Firecrawl (firecrawl.dev), a page-rendering service on Tenure's own account, reads only your own public website: the page you give at setup (with your app's sign-in page, for its look), your pricing page (for plan features), your changelog or blog (for What's new suggestions), a screenshot of your app's page, and documents you choose to add; afterwards your pricing page, changelog and look are re-read at most weekly while you use Tenure. It never receives anything about your subscribers. Self-hosting keeps all data in your own infrastructure. The encryption key for stored secrets is supplied by your deployment environment (for example your platform's secret store or KMS); Tenure itself uses no external key-management service.
Tenure runs wherever you deploy it (Docker image provided); the database is yours. There is no shared multi-tenant data plane across deployments.
Found a vulnerability? Email security@churner.app (see /.well-known/security.txt). Please do not test against other tenants' data.